DataTable.Delete() Removing rows before Accept Changes - vb.net

I'm having an issue where I mark several rows for deletion within a loop, but when it gets to a certain point in the loop, the rows actually start to be removed.
As you can see what I'm basically doing is checking if the row needs to be deleted and if so, add it to a new table and delete it.
The problem is this works for the first 60 ish rows, then all of a sudden the rows appear to actually be removed and it eventually throws a row with that index doesn't exist error (at 65).
The original table is a list of contacts with firstname, lastname, email and company, with 70 records.
I tried to cut the list in half, but then the issue started happening at around row 23.
dtSelectCompany = dt_data.Clone
Dim s_company As String
Dim b_add As Boolean
Dim dtCompanies As Data.DataTable
For i = 0 To dt_data.Rows.Count - 1
b_add = False
s_company = dt_data.Rows(i).Item(columnsDictionary("company")).ToString
If s_company = "" Then : b_add = True
Else
dtCompanies = crm_functions.getCompaniesByName(s_company.Replace(" ", "%"))
If dtCompanies.Rows.Count > 1 Then : b_add = True
ElseIf dtCompanies.Rows.Count = 1 Then
dt_data.Rows(i).Item(columnsDictionary("company")) = dtCompanies.Rows(0).Item("id")
Else : b_add = True
End If
End If
If b_add Then
Dim temp_row As Data.DataRow = dtSelectCompany.NewRow
temp_row.ItemArray = dt_data.Rows(i).ItemArray.Clone()
temp_row.Item("fullName") = temp_row.Item(columnsDictionary("firstname")) & " " & temp_row.Item(columnsDictionary("lastname"))
dtSelectCompany.Rows.Add(temp_row)
dt_data.Rows(i).Delete()
End If
Next

Instead of a counter, use a datarow, for example:
dtSelectCompany = dt_data.Clone
Dim s_company As String
Dim b_add As Boolean
Dim dtCompanies As Data.DataTable
Dim MyDataRow as DataRow
For Each MyDataRow IN dt_data.Rows
b_add = False
s_company = MyDataRow("company").ToString
If s_company = "" Then : b_add = True
Else
' not sure what crm_functions is, so left this alone
dtCompanies = crm_functions.getCompaniesByName(s_company.Replace(" ", "%"))
If dtCompanies.Rows.Count > 1 Then : b_add = True
ElseIf dtCompanies.Rows.Count = 1 Then
MyDataRow("company")) = dtCompanies.Rows(0).Item("id")
Else : b_add = True
End If
End If
If b_add Then
Dim temp_row As Data.DataRow = dtSelectCompany.NewRow
temp_row = MyDataRow
temp_row.Item("fullName") = temp_row.Item(columnsDictionary("firstname")) & " " & temp_row.Item(columnsDictionary("lastname"))
dtSelectCompany.Rows.Add(temp_row)
MyDataRow.Delete()
End If
Next
Wrote this off the top of my head, so .....

Related

How can I solve the problem on Create Multi-Series Chart

I tried to made a chart through Vb.Net, it seems not work. Here is my Coding:
Private Sub btn_Rate_Click(sender As Object, e As EventArgs) Handles btn_Rate.Click
Label37.Visible = True
Label39.Visible = True
Label48.Visible = True
Label49.Visible = False
Label51.Visible = False
Label52.Visible = False
Label37.Text = "The Chart of " & Label38.Text & " by Rate of Incidents "
Label48.Text = "From" & " " & Label42.Text & " " & "to" & " " & Label45.Text
If DropDownList13.SelectedIndex = -1 Then
Label39.Text = Label40.Text
Else
Label39.Text = Label40.Text & Label41.Text
End If
btn_Print.Visible = True
Dim dtRate As DataTable = New DataTable("dtRates")
For Each cell As TableCell In gvRate.HeaderRow.Cells
dtRate.Columns.Add(cell.Text.Trim())
Next
For Each row As GridViewRow In gvRate.Rows
dtRate.Rows.Add()
For i As Integer = 0 To row.Cells.Count = -1
dtRate.Rows(row.RowIndex)(i) = row.Cells(i).Text.Trim()
Next
Next
Dim departments As List(Of String) = New List(Of String)()
departments = (From p In dtRate.AsEnumerable() Select p.Field(Of String)("Department")).Distinct().ToList()
If RateChart.Series.Count() = 1 Then
RateChart.Series.Remove(RateChart.Series(0))
End If
For Each department As String In departments
Dim UserDepartment = department
Dim X As Integer()
X = (From p In dtRate.AsEnumerable()
Where p.Field(Of String)("Department") = UserDepartment
Order By p.Field(Of String)("Period_Shown")
Select Convert.ToInt32(p.Field(Of String)("Period_Shown"))).ToArray()
Dim Y As Decimal()
Y = (From p In dtRate.AsEnumerable()
Where p.Field(Of String)("Department") = UserDepartment
Order By p.Field(Of String)("Period_Shown")
Select Convert.ToDecimal(p.Field(Of String)("Rate_Int"))).ToArray()
RateChart.Series.Add(New Series(department))
RateChart.Series(department).IsValueShownAsLabel = True
RateChart.Series(department).BorderWidth = 3
RateChart.Series(department).ChartType = SeriesChartType.Line
RateChart.Series(department).Points.DataBindXY(X, Y)
Next
RateChart.Legends(0).Enabled = True
End Sub
There had two error Message. The one is In Line24
Where p.Field(Of String)("department") = department
Error Meaage:
Using the iteration variable "department" in a query expression may have unexpected results. Instead, create a local variable within the loop and assign it the value of the iteration variable.
The other is In Line41
RateChart.Legends(0).Enabled = True
Error Meaage:
Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index
For the second error; Line 41: The error says "The index is out of range". That means you were trying to index an object with a value that was not valid.

How do you replace the last occurance of a , with the word "and"?

How do you replace the last occurance of a , with the word and? Can you please give me an idea?
i have 3 checkboxes, 1 rich textbox
to display the output, 1 button
(Aparri) or (Camalanuigan) or (Lallo)
Cagayan(Aparri, Camalanuigan) or Cagayan(Aparri,Camalanuigan,Lallo)
I would like the output to be like this: #Cagayan(Aparri and Camalanuigan) or #Cagayan(Aparri,Camalanuigan And Lallo)
this is my code:
Dim rws As String
If Aparri.Checked = True Then
close_parenthesis.Checked = True
If rws = "" Then
rws = "(" + Aparri.Text
End If
End If
If Aparri.Checked = False Then
rws = ""
End If
If Camalanuigan.Checked = True Then
close_parenthesis.Checked = True
If rws = "" Then
rws = "(" + Camalanuigan.Text
Else
rws = rws & ", " & Camalanuigan.Text
End If
End If
If Lallo.Checked = True Then
close_parenthesis.Checked = True
If rws = "" Then
rws = "(" + Lallo.Text
Else
rws = rws & ", " & Lallo.Text
End If
End If
If close_parenthesis.Checked = True Then
If rws = "" Then
Else
rws = rws + close_parenthesis.Text
End If
End If
Display.Text = rws.ToString
Output: (Aparri,Camalanuigan,Lallo)
i want the out like this (Aparri,Camalanuigan and Lallo)
Here, I haven't even seen your code but I get what you want to do by looking at the picture. It can be done in shorter version but I have explained what's going on in each and every line so it's lengthy.
I have written this code:
'let's say the string is "Aparri, Camalanuigan, Lallo" . that's what your code does, right?
dim Strng as string = "Aparri, Camalanuigan, Lallo"
'now find the position of last appearing ","
Dim comaposition As Integer
comaposition = Strng.LastIndexOf(",") 'it is zero based
'if not found, it will return -1 and u can exit, no need to do the work
if commaposition = "-1" then
exit sub
end if
'remove the comma
Dim String_After_Removing_Comma As String
String_After_Removing_Comma = Strng.Remove(comaposition, 1)
'add "and" in the same position where comma was found
Dim final_string As String
final_string = String_After_Removing_Comma.Insert(comaposition, " and")
'show it on the textbox
DisplayTxt.Text = final_string
You can do this thing after finding your final string (rws in your code).
Hope this helps
You can use the following function to replace last occurrence.
Public Function ReplaceLastOccurrence(ByVal source As String, ByVal searchText As String, ByVal replace As String) As String
Dim position = source.LastIndexOf(searchText)
If (position = -1) Then Return source
Dim result = source.Remove(position, searchText.Length).Insert(position, replace)
Return result
End Function
and you use display text as
Display.Text = ReplaceLastOccurence(rws, ",", "and")
in your last line of code
You always can do it by yourself with single loop and knowledge about last index
' Create array of selected strings
Dim selectedTexts =
New List(Of CheckBox) From { Aparri, Camalanuigan, Lallo }.
Where(Function(checkbox) checkbox.Checked).
Select(Function(checkbox) checkbox.Text).
ToArray()
' Separate selected strings by delimeters
Dim lastIndex = selectedTexts.GetUpperBound(0)
Dim builder = New StringBuilder()
For i As Integer = 0 To lastIndex
If i > 0 Then
Dim delimeter = If(lastIndex > 0 AndAlso lastIndex = i, " and ", ", ")
builder.Append(delimeter)
End If
builder.Append(test(i))
Next
' Wrap with parenthesis if result not empty
If builder.Length > 0 Then
builder.Insert(0, "(")
Dim close = If(close_parenthesis.Checked, close_parenthesis.Text, "")
builder.Append(close)
End If
' Print result
Display.Text = builder.ToString()

Pictures wont become visible

So today in my Computer Programming Class, we created a project called CaseStudy. I saw a way to make the program have more replay value. I decided to morph the code and interface to be like a Hangman game. I've got the limbs to appear, but only after clicking Ok on the messageBox.
I'm wondering if anyone has a way to make these limbs appear in real time.
Here is the important code:
Dim SECRET_WORD As String = newSecretWord
Const FLAG As Char = "!"
Const GUESS_PROMPT As String = "Enter a letter or " & FLAG & " to guess word:"
Dim numGuesses As Integer = 0
Dim letterGuess As Char
Dim wordGuess As String
Dim tempWord As String
Dim endGame As Boolean
Dim wordGuessedSoFar As String = ""
Dim lenght As Integer = SECRET_WORD.Length
wordGuessedSoFar = wordGuessedSoFar.PadLeft(lenght, "_")
Me.lblSecretWord.Text = wordGuessedSoFar
Dim tempLetterGuess = InputBox(GUESS_PROMPT, Me.Text)
If tempLetterGuess = Nothing Then
endGame = True
Else
letterGuess = tempLetterGuess
End If
Do While letterGuess <> FLAG And wordGuessedSoFar <> SECRET_WORD And Not endGame
numGuesses += 1
For letterPos As Integer = 0 To SECRET_WORD.Length - 1
If SECRET_WORD.Chars(letterPos) = Char.ToUpper(letterGuess) Then
tempWord = wordGuessedSoFar.Remove(letterPos, 1)
wordGuessedSoFar = tempWord.Insert(letterPos, Char.ToUpper(letterGuess))
Me.lblSecretWord.Text = wordGuessedSoFar
End If
Next letterPos
If wordGuessedSoFar <> SECRET_WORD Then
tempLetterGuess = InputBox(GUESS_PROMPT, Me.Text)
If tempLetterGuess = Nothing Then
endGame = True
Else
letterGuess = tempLetterGuess
End If
End If
Loop
If wordGuessedSoFar = SECRET_WORD Then
MessageBox.Show("You guessed it in " & numGuesses & " guesses!")
ElseIf letterGuess = FLAG Then
wordGuess = InputBox("Enter a word: ", Me.Text)
If wordGuess.ToUpper = SECRET_WORD Then
MessageBox.Show("You guessed it in " & numGuesses & " guesses!")
Me.lblSecretWord.Text = SECRET_WORD
Else
MessageBox.Show("Sorry, you lose.")
End If
Else
MessageBox.Show("Game over.")
lblSecretWord.Text = Nothing
End If
Dim place As Integer = SECRET_WORD.Length - 1
If tempLetterGuess <> SECRET_WORD.Chars(place) Then
numWrong += 1
End If
If numWrong = 1 Then
picHead.Visible = True
End If
If numWrong = 2 Then
picBody.Visible = True
End If
End Sub
End Class
I can take any other pictures if you'd like.
If I'm understanding you right, you want to show your "pictures" before the user sees the message. If so, you need to move the following code to an area just before your MessageBox and just after the InputBox:
Dim place As Integer = SECRET_WORD.Length - 1
If tempLetterGuess <> SECRET_WORD.Chars(place) Then
numWrong += 1
End If
If numWrong = 1 Then
picHead.Visible = True
End If
If numWrong = 2 Then
picBody.Visible = True
End If

Visual Basic Split() returning null

Code for reading and splitting from file:
Public Sub LoadAccount()
currentfilereader = New StreamReader(filename)
Dim Seperator As Char = " "c
For count As Integer = 0 To NumUsers - 1
textstring = currentfilereader.ReadLine
Dim words() As String = currentfilereader.ReadLine.Split(Seperator)
Username = words(0)
Password = words(1)
If words(2) = "1" Then
AccessGranted = True
Else
AccessGranted = False
End If
Users(count, 0) = Username
Users(count, 1) = Password
Users(count, 2) = AccessGranted
Next
currentfilereader.Close()
End Sub
Code for logging in:
Public Sub Login()
Dim InvalidUsername, InvalidPassword As Boolean
InvalidUsername = True
InvalidPassword = True
LoginName = Form1.tbun.Text
LoginPassword = Form1.tbpw.Text
For count As Integer = 0 To NumUsers - 1
If LoginName = Users(count, 0) Then
InvalidUsername = False
If LoginPassword = Users(count, 1) Then
InvalidPassword = False
CurrentUsername = LoginName
CurrentPassword = LoginPassword
CurrentAccessGranted = Users(count, 2)
loggedin = True
Else
MsgBox("Invalid Password")
End If
Else
MsgBox("Invalid Username")
End If
Next
End Sub
Code for calculating number of users:
Public Sub NumberOfUsers()
currentfilereader = New StreamReader(filename)
NumUsers = File.ReadAllLines("Accounts.txt").Length
MsgBox("There are " & NumUsers & " users")
End Sub
I have added a MsgBox to show the number of users to make sure all is working fine which returns the value of 2, since I currently have 2 lines in the text file, "a a 1" and "b b 1".
However when this line runs, Dim words() As String = currentfilereader.ReadLine.Split(Seperator), it returns null.
The purpose of subtracting 1 from the NumUsers in the count is since the count starts at zero along with the array. Meaning that if I didn't it would check 3 times if there is only 2 users in the file. But I just can't seem to figure out what is wrong and why it is returning null.
You call ReadLine twice for each user:
textstring = currentfilereader.ReadLine
Dim words() As String = currentfilereader.ReadLine.Split(Seperator)
This means that for the first user you read both lines, and for the second user you read nothing, leading to the empty split array.
Replace
Dim words() As String = currentfilereader.ReadLine.Split(Seperator)
With
Dim words() As String = textstring.Split(Seperator)

Finding Missing numbers in a given range

So i have a problem with my codings and was wondering if anyone can help me.
Basically i'm using VB.NET and MSSQL to make a program on finding missing numbers in between a given range set by the user. The program will read from the table and give the output on a textbox. And the above codes are so far what i can come up with. But the problem is, i get wrong output and not what i want. Here's an image of the output.
Function FindingMissingNumber() As String
Dim intX As Integer = Nothing
Dim intY As Integer = Nothing
Dim strSting As String = Nothing
Dim strSqlQUery As String = Nothing
Dim cmdSqlCommand As Data.SqlClient.SqlCommand = Nothing
Dim rdrDataReader As Data.SqlClient.SqlDataReader = Nothing
'------------------------------------------------------------------------------------------------------------------------
'-> Process
'------------------------------------------------------------------------------------------------------------------------
strSqlQUery = "Select ExReportPolicyNo From DBReport Order by ExReportPolicyNo"
Dim msSqlConnection As New Data.SqlClient.SqlConnection()
'NOTE - You may need to CHECK your connection string!!! in the line below
msSqlConnection.ConnectionString = "Data Source=SISBSQL\SISBSQL;Initial Catalog=ExceptionReport;User ID=sa;Password=123;"
cmdSqlCommand = New Data.SqlClient.SqlCommand(strSqlQUery, msSqlConnection)
If cmdSqlCommand.Connection.State = Data.ConnectionState.Closed Then cmdSqlCommand.Connection.Open()
rdrDataReader = cmdSqlCommand.ExecuteReader()
If rdrDataReader.HasRows Then
Do While rdrDataReader.Read()
intX = txtRangeLeft.Text
intY = txtRangeRight.Text
'intY = rdrDataReader.GetValue(rdrDataReader.GetOrdinal("ExReportPolicyNo"))
Do While intX <> intY
intX = intX + 1
If intX <> intY Then
strSting = strSting & intX & ", " 'if it is not, then record the non sequential number into the string
Else
Exit Do
End If
Loop
Loop
End If
If cmdSqlCommand.Connection.State = Data.ConnectionState.Open Then cmdSqlCommand.Connection.Close()
'return string
Return strSting
'tidy up
intX = Nothing
intY = Nothing
strSting = Nothing
strSqlQUery = Nothing
cmdSqlCommand = Nothing
rdrDataReader = Nothing
End Function
As you can see the program loops it multiple times, and give out the wrong output. The output should read only "286118, 286120, 286121". Question is where did i went wrong?
Try this (using linq)
Change query to return rows between start and end value
Select distinct ExReportPolicyNo From DBReport
Where ExReportPolicyNo between #start and #end
Order by ExReportPolicyNo
Create List from your query:
Dim originalList as List(Of Integer)
If rdrDataReader.HasRows Then
Do While rdrDataReader.Read()
originalList.Add(rdrDataReader.GetInt(0))
Loop
End If
Create List of range from your start and end number
//Dim rangeList = Enumerable.Range(286117, 286121 - 286117 + 1).ToList()
Dim starti = Int32.Parse(txtRangeLeft.Text)
Dim endi = Int32.Parse(txtRangeRight.Text)
Dim rangeList = Enumerable.Range(starti, endi - starti + 1).ToList()
Find all missing numbers
Dim missingList = originalList.Except(rangelist)
Create CSV string from list above
strString = String.Join(",", missingList.Select(x => x.ToString()).ToArray())