Check datatable has row at selected index using loop - vb.net

Check if datatable has row at selected index using a for loop
i Want to check here if datatable has row at that value of 'i' which comes from loop
Private Sub btnAct_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAct.Click
Gross = 0
Dim i As Integer
Dim dr As DataRow = Nothing
Act1 = dt.Rows(0)("Account")
Act2 = dt.Rows(0)("Account")
'Next
For i = 0 To 100 Step 1
If ( i Want to check here if datatable has row at that value of 'i' which comes from loop) Then
else
If (Act1 = Act2) Then
Else
Act1 = dt.Rows(i - 1)("Account")
For k As Integer = 0 To (i - 1) Step 1
Act2 = Convert.ToString(dt.Rows(k)("Account"))
If (Act1 = Act2) Then
Gross += Convert.ToInt32(dt.Rows(k)("Total_Gross_Amount"))
End If
Next
dr = dt.NewRow()
dr("Account") = "Total"
dr("Total_Gross_Amount") = Gross
Gross = 0
dt.Rows.InsertAt(dr, i)
Act2 = Convert.ToString(dt.Rows(i + 1)("Account"))
End If
Act1 = Convert.ToString(dt.Rows(i + 1)("Account"))
dt(i)("Sno") = i + 1
Next
End If
'Next
End Sub
I have a datatable And I want to check it has row at selected value which comes from a for loop

Simple - LINQ to the rescue:
For i = 0 To 100
' Functionally equivalent to
' dt.Rows.Cast(Of DataRow)().ElementAtOrDefault(i).
Dim rowAtIndex = dt.AsEnumerable().ElementAtOrDefault(i)
If rowAtIndex IsNot Nothing Then
' Do something with the row.
End If
Next
Or a slightly less expressive, but better optimised version:
For i = 0 To 100
Dim rowAtIndex As DataRow = Nothing
If i < dt.Rows.Count Then
rowAtIndex = dt.Rows(i)
' Do something with the row.
Else
' Row at index does not exist.
End If
Next
The big question here is though: does i really need to go beyond dt.Rows.Count - 1 (which is the index of the last row in the DataTable)? If not, I'd rather change the loop to
For i = 0 To dt.Rows.Count - 1

Related

DataTable.Rows.Count always returns 0 - VB.NET

I'm trying to populate DataGridView cells with information from two (parent, child tables). Everything works just fine, except for this part table.Rows.Count. It always returns 0, no matter that I have one record in the table.
This is the code:
Private Sub Query__tbl_purchase_order_articlesDataGridView_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles Query__tbl_purchase_order_articlesDataGridView.CellEndEdit
Dim table As DataTable = Orders_DBDataSet.Tables("tbl_list_of_articles")
Dim selectedRowCount As Integer = Query__tbl_purchase_order_articlesDataGridView.CurrentCell.RowIndex
Dim art_ID As Integer = CInt(Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(0).Value)
Dim art_ttl As String
Dim art_ttl_tr As String
Dim mu As String
Dim art_ttl_i As Integer
Dim art_ttl_tr_i As Integer
Dim mu_i As Integer
Dim art_ID_t_i As Integer
Dim art_ttl_t_i As Integer
Dim art_ttl_tr_t_i As Integer
Dim mu_t_i As Integer
Dim i As Integer
'search for column index in DataGridView
For i = 0 To Query__tbl_purchase_order_articlesDataGridView.Columns.Count - 1
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "article_name" Then
art_ttl_i = i
End If
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "article_name_tr" Then
art_ttl_tr_i = i
End If
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "masurement_unit" Then
mu_i = i
End If
Next
'search for column index in "table"
For i = 0 To table.Columns.Count - 1
If table.Columns(i).ColumnName.ToString = "article_ID" Then
art_ID_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "article_name" Then
art_ttl_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "article_name_tr" Then
art_ttl_tr_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "masurement_unit" Then
mu_t_i = i
End If
Next
For i = 0 To table.Rows.Count
If art_ID = CInt(table.Rows(i).Item(art_ID_t_i).ToString()) Then
art_ttl = table.Rows(i).Item(art_ttl_t_i).ToString()
art_ttl_tr = table.Rows(i).Item(art_ttl_tr_t_i).ToString()
mu = table.Rows(i).Item(mu_t_i).ToString()
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(art_ttl_i).Value = art_ttl
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(art_ttl_tr_i).Value = art_ttl_tr
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(mu_i).Value = mu
Exit For
End If
Next
End Sub
Also, I tied to test it like this, but the result is the same. It can find a table index, but always return 0 as a table row count.
'test ========================================
Dim x, y As Integer
For x = 0 To Orders_DBDataSet.Tables.Count - 1
If Orders_DBDataSet.Tables(x).TableName.ToString = "tbl_list_of_articles" Then
y = x
End If
Next
x = 0
For Each row As DataRow In table.Rows
x = x + 1
Next
'============================================
x = Orders_DBDataSet.Tables(y).Rows.Count
Most of the times this happened to me because I was not actually using the instance of the dataset "connected" to the form. What does this mean? You either don't populate the dataset instance tied to the form in the Load event, or you are populating it but you are somehow using other instance of it. This has a higher chance of happening if you are sending data between forms as well.

prevent go to next row when duplicated value in `datagridview`

I have datagrid that user will add values in just one column , and i want to prevent duplicated data in this column, i had mange that by the code bellow,
what I want is to keep the selection (focus) in the same editing cell(x)
if the entered data is duplicated, so I tried to get the current row index and return to it if the data is duplicated but its not working.
row_index = DataGridView1.CurrentRow.Index.ToString()
Dim cell As DataGridViewCell = DataGridView1.Rows(row_index).Cells(1)
DataGridView1.CurrentCell = cell
DataGridView1.BeginEdit(True)
NOTE : User will Add barcode number, so he will use barcode scanner or add it manually and press enter key.
Private Sub DataGridView1_RowValidated(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowValidated
If DataGridView1.Rows.Count > 2 Then
Dim i As Integer = 0
Dim row_index As Integer
' loop condition will loop while the row count is less or equal to i
While i <= DataGridView1.Rows.Count - 1
Dim j As Integer = 1
' loop condition will loop while the row count is less or equal to j
While j <= DataGridView1.Rows.Count - 1
Dim str As String = DataGridView1.Rows(i).Cells(1).Value()
Dim str1 As String = DataGridView1.Rows(j).Cells(1).Value()
If Not str1 = "" AndAlso Not str = "" Then
If str1 = str Then
'row_index = DataGridView1.SelectedCells.Item(i).RowIndex.ToString()
row_index = DataGridView1.CurrentRow.Index.ToString()
Dim cell As DataGridViewCell = DataGridView1.Rows(row_index).Cells(1)
DataGridView1.CurrentCell = cell
DataGridView1.BeginEdit(True)
Exit Sub
End If
End If
j += 1
End While
i += 1
End While
End If
End Sub
You can try it also in a for loop. This is how I do it. If what you mean is to stop/retain the selection(focus) or go to in a cell/row whenever it is a duplicate with the current data you have. This should work fine.
enter code here
For i = 0 To Datagridview1.Rows.Count - 1
If Datagridview1.Rows(i).Cells(1).Value = DataYouWillInput Then
DataGridView1.CurrentCell = DataGridView1.Rows(i).Cells(1)
Exit for
End If
Next
enter code here
If your condition returns true with the condition of current data and data you'll be adding. Just exit your loop. Use this.
DataGridView1.CurrentCell = DataGridView1.Rows(i).Cells(1)

ArgumentOutOfRangeException was Unhandled , Index was out of range

I want to ask if anyone knows this why this error occurs? So there are 2 forms. The first calculation form there is no error and this is the second calculation form which produces the error, after searching here and there masi not yet enlightenment, maybe someone can help?
THIS SCREENSHOT OF ERROR
this full source code
Public Class FrmHitung2
Private Sub FrmHitung2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim dt As DataTable = openDT("SELECT * FROM tb_rel_alternatif2 WHERE kode_crips NOT IN (SELECT kode_crips FROM tb_crips2)")
If dt.Rows.Count > 0 Then
msgError("Anda belum mengatur nilai untuk setiap alternatif, silahkan atur di menu Nilai Bobot")
BtnCetak.Enabled = False
Else
Dgv1.AllowUserToAddRows = False
Dgv1.AllowUserToDeleteRows = False
Dgv1.ReadOnly = True
Dgv1.AutoGenerateColumns = False
awal()
End If
End Sub
Sub awal()
Dgv1.Columns.Clear()
Dgv1.Rows.Clear()
Dgv1.Columns.Add("nim", "Kode")
Dgv1.Columns("nim").ReadOnly = True
Dgv1.Columns.Add("nama_mahasiswa", "Nama")
Dgv1.Columns("nama_mahasiswa").ReadOnly = True
dr = openDR("SELECT * FROM tb_alternatif2 ORDER BY nim")
While dr.Read()
Dgv1.Rows.Add(dr(0), dr(1))
End While
dr = openDR("SELECT kode_kriteria, atribut FROM tb_kriteria2 ORDER BY kode_kriteria")
While dr.Read()
Dgv1.Columns.Add(dr(0), dr(0))
Dgv1.Columns(dr(0).ToString()).ToolTipText = dr(1).ToString()
End While
For a = 0 To Dgv1.Rows.Count - 1
dr = openDR("SELECT c.nama_crips FROM tb_rel_alternatif2 r " &
" LEFT JOIN tb_crips2 c ON c.kode_crips = r.kode_crips " &
" WHERE nim='" & Dgv1.Rows(a).Cells(0).Value & "' ORDER BY r.kode_kriteria")
Dim b As Integer = 2
While dr.Read
Dgv1.Rows(a).Cells(b).Value = dr(0)
b = b + 1
End While
Next
Dgv1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
BtnCetak.Enabled = False
End Sub
Function get_col_max(ByVal dgv As DataGridView, ByVal col_name As String) As Double
Dim max As Double = 0
If dgv.Rows.Count > 0 Then max = Val(dgv.Rows(0).Cells(col_name).Value)
For Each row As DataGridViewRow In dgv.Rows
If Val(row.Cells(col_name).Value) > max Then
max = Val(row.Cells(col_name).Value)
End If
Next
get_col_max = max
End Function
Function get_col_min(ByVal dgv As DataGridView, ByVal col_name As String) As Double
Dim min As Double = 0
If dgv.Rows.Count > 0 Then min = Val(dgv.Rows(0).Cells(col_name).Value)
For Each row As DataGridViewRow In dgv.Rows
If Val(row.Cells(col_name).Value) < min Then
min = Val(row.Cells(col_name).Value)
End If
Next
get_col_min = min
End Function
Private Sub BtnHitung_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnHitung.Click
Dim a, b As Integer
awal()
Dgv1.copyTo(Dgv2)
For a = 0 To Dgv2.Rows.Count - 1
dr = openDR("SELECT c.nilai FROM tb_rel_alternatif2 r " &
" LEFT JOIN tb_crips2 c ON c.kode_crips = r.kode_crips " &
" WHERE nim='" & Dgv2.Rows(a).Cells(0).Value & "' ORDER BY r.kode_kriteria")
b = 2
While dr.Read
Dgv2.Rows(a).Cells(b).Value = dr(0)
b = b + 1
End While
Next
Dgv2.copyTo(Dgv3)
For Each row As DataGridViewRow In Dgv2.Rows
For b = 2 To Dgv2.Columns.Count - 1
Dim v = row.Cells(b).Value
If Dgv2.Columns(b).ToolTipText = "benefit" Then
Dgv3.Rows(row.Index).Cells(b).Value = v / get_col_max(Dgv2, Dgv2.Columns(b).Name)
Else
Dgv3.Rows(row.Index).Cells(b).Value = get_col_min(Dgv2, Dgv2.Columns(b).Name) / v
End If
Next
Next
dr = openDR("SELECT kode_kriteria, bobot FROM tb_kriteria2 ORDER BY kode_kriteria")
While dr.Read()
Dgv3.Columns(dr(0).ToString()).ToolTipText = dr(1).ToString()
End While
Dgv3.copyTo(Dgv4)
For Each row As DataGridViewRow In Dgv3.Rows
For b = 2 To Dgv3.Columns.Count - 1
Dim v = row.Cells(b).Value
Dgv4.Rows(row.Index).Cells(b).Value = v * Val(Dgv3.Columns(b).ToolTipText)
Next
Next
Dgv4.Columns.Add("total", "Total")
For Each row As DataGridViewRow In Dgv4.Rows
For b = 2 To Dgv2.Columns.Count - 1
row.Cells("total").Value = row.Cells("total").Value + row.Cells(b).Value
Next
Next
Dgv4.copyTo(Dgv5)
Dgv5.Sort(Dgv5.Columns("total"), System.ComponentModel.ListSortDirection.Descending)
For Each row As DataGridViewRow In Dgv5.Rows
execute("UPDATE tb_alternatif2 SET total=#0, rank=#1 WHERE nim=#2", row.Cells("total").Value, row.Index + 1, row.Cells("nim").Value)
Next
TabControl1.SelectedTab = TabRangking
BtnCetak.Enabled = True
End Sub
Private Sub BtnCetak_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnCetak.Click
LapRangking.ShowAsChild(Me.MdiParent)
End Sub
Private Sub BtnKeluar_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnKeluar.Click
Me.Close()
End Sub
End Class
Why are your using dr.Read() at one place and dr.Read in another. Underlined in RED. Maybe the DataReader is not populated yet!, It should be dr.Read()
That error occurs when you try to access an array or other collection with an index that doesn't exist. Note that indexing starts at 0 all the way to Count - 1.
From you screenshot I can see the error occurs at this line Dgv1.Rows(a).Cells(b).Value = dr(0). a is defined in a For loop this way, For a = 0 To Dgv1.Rows.Count - 1 so it is unlikely that is the culprit.
You may want to check the value of b which you have started with a value of 2. If you're trying to access the second item in the collection, you will have to change that line to read...
Dim b As Integer = 1 ' If you wanted to start from the 2nd cell.
While dr.Read
Dgv1.Rows(a).Cells(b).Value = dr(0)
b = b + 1
End While
b is likely growing past the number of cells you have and causing that problem.
Note: I have changed the definition of b to start at 1
Update 2
After looking at your code again, I'm seeing something that I seem to have missed when looking at line that caused the error. You are defining b as, Dim b As Integer = 2 ' I recommended changing that to 1 and using it to access the columns in your dataset/reader. But when I look at your queries, something else reveals itself. The 1st one in the awal() method is
SELECT * FROM tb_alternatif2 ORDER BY nim
which returns an ordered set with an unknown (to me anyway) number of rows and columns. You are then looping through adding the 1st and 2nd columns of the data reader to rows of what I assume is a data grid view. After that, you make a call to another query
SELECT kode_kriteria, atribut FROM tb_kriteria2 ORDER BY kode_kriteria
which returns an ordered set with 2 columns that you add as columns to the data grid view. Next you have the query
SELECT c.nama_crips FROM tb_rel_alternatif2 r --... truncated
which returns one column which is when you are defining b. Somewhere between the number of columns you are creating and then addressing them with b, you are probably hitting an off by one error. Or more than off by one. Assuming the 2nd query creates for you 10 columns and the third query returns 15 rows, you will quickly run out of columns to address using .Cells(b).Value in your code.
It is unclear to me what you are trying to do with this, but I would recommend trying to define your query again and binding once to the data grid. As an aside: I would also recommend using parameters for constructing your queries because the way you have done isn't too secure... SQL injection and all that.

Checking existing database record items against listbox items

I have a datatable that I am adding records to in my windows forms application. this datatable only has 2 columns and the first column is the primary key and is an integer. The second column contains names and I need to automatically add a list of names from a listbox to the table. Most of these names will already have their own record in the table but there will be different names in the listbox each time. I need to check the existing record items against the listbox items to make sure no duplicates get added, but if there is a name in the listbox that does not exist in the datatable, add a new record for that name.
What I have tried so far is this:
Private m_cn As New SqlConnection()
Private m_DA As SqlDataAdapter
Private m_CB As SqlCommandBuilder
Private m_DataTable As New DataTable
Private m_IntRowPosition As Integer = 0
Private Sub btnInsertIntoDatabase_Click(sender As Object, e As EventArgs) Handles btnInsertIntoDatabase.Click
Dim drReadRow As DataRow = m_DataTable.NewRow()
Dim dcReadCol As DataColumn = m_DataTable.Columns.Item(1)
Dim intLoopCounter As Integer = 0
Dim unique As Boolean = True
If m_DataTable.Rows.Count = 0 Then
For m_IntRowPosition = 0 To (lstScannedNames.Items.Count() - 1)
Dim drNewRow As DataRow = m_DataTable.NewRow()
drNewRow("emp_id") = m_IntRowPosition
drNewRow("emp_name") = RTrim(lstScannedNames.Items.Item(RTrim(m_IntRowPosition)))
m_DataTable.Rows.Add(drNewRow)
Next m_IntRowPosition
GoTo SomeWhereElse
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ElseIf m_DataTable.Rows.Count > 0 Then
For m_IntRowPosition = 0 To m_DataTable.Rows.Count
For intLoopCounter = 0 To lstScannedNames.Items.Count - 1
If RTrim(m_DataTable.Rows(m_IntRowPosition).Item(1)) = lstScannedNames.Items.Item(intLoopCounter) Then
unique = False
ElseIf RTrim(m_DataTable.Rows(m_IntRowPosition).Item(1)) <> lstScannedNames.Items.Item(intLoopCounter) Then
unique = True
lstScannedNames.SelectedIndex = intLoopCounter
intLoopCounter = lstScannedNames.Items.Count - 1
End If
Next intLoopCounter
If (unique) = True Then
Dim drNewRow As DataRow = m_DataTable.NewRow()
drNewRow("emp_id") = m_DataTable.Rows.Count()
drNewRow("emp_name") = lstScannedNames.Items.Item(lstScannedNames.SelectedIndex)
m_DataTable.Rows.Add(drNewRow)
Else
unique = True
End If
Next m_IntRowPosition
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
End If
SomeWhereElse:
m_DA.Update(m_DataTable)
MessageBox.Show("Operation Completed")
End Sub
The area of focus is the ElseIf statement. When I run this code and there are already records in the database, it adds the first name that is in the list and not in the datatable, to the datatable. It then adds the first name from the list to a new record, for each item in the list, which is about 20 times but it depends on the list length. I've been trying different things and I know I'm close but I've been stuck for a while.
Reverse your logic. Loop over the items in the listbox and check if they are present in the datatable
....
For intLoopCounter = 0 To lstScannedNames.Items.Count - 1
Dim name = lstScannedNames.Items.Item(intLoopCounter)
Dim rowExist = m_DataTable.Select("emp_name = '" & name & "'")
if rowExist Is Nothing OrElse rowExist.Length = 0 Then
Dim drNewRow As DataRow = m_DataTable.NewRow()
drNewRow("emp_id") = m_DataTable.Rows.Count()
drNewRow("emp_name") = name
m_DataTable.Rows.Add(drNewRow)
End If
Next m_IntRowPosition
...
Using the DataTable.Select method avoids to write an explicit loop to find the duplicate. And you can directly add the row when you are certain that there is no duplicate

how to execute for loop for items checked in 3 checkedlistbox

i made a report for taking output of employees in a company.i made a code for that.but it only show the first items checked.how to impliment for loop in this.
Dim i As Integer
Dim j As Integer
Dim k As Integer
For i = 0 To Employee_Bank_dtl.CheckedListBox1.Items.Count - 1 Step i + 1
If Employee_Bank_dtl.CheckedListBox1.GetItemCheckState(i) = CheckState.Checked Then
Dim xx As String = (CType(Employee_Bank_dtl.CheckedListBox1.Items(i), DataRowView))("VC_BRNAME")
For j = 0 To Employee_Bank_dtl.CheckedListBox2.Items.Count - 1 Step j + 1
If Employee_Bank_dtl.CheckedListBox2.GetItemCheckState(j) = CheckState.Checked Then
Dim yy As String = (CType(Employee_Bank_dtl.CheckedListBox2.Items(j), DataRowView))("vc_empstatus")
For k = 0 To Employee_Bank_dtl.CheckedListBox3.Items.Count - 1 Step k + 1
If Employee_Bank_dtl.CheckedListBox3.GetItemCheckState(k) = CheckState.Checked Then
Dim zz As String = (CType(Employee_Bank_dtl.CheckedListBox3.Items(k), DataRowView))("vc_value")
Dim str = "xxxxxxxxxxxxxx"
conobj.readdata(str)
conobj._adpt.Fill(Me.DataSet10.BRANCH_MAST)
Me.ReportViewer1.RefreshReport()
End If
Next
End If
Next
End If
Next i
You should increment through the collection of items like this not the way you are doing it. You should be able to find the properties you are looking for. Set a break point within the inner loop and right click on quickwatch on the item and you will see all the properties of that item which will contain what your looking for.
For Each item In CheckedListBox1.Items
'set the item property to the right property that holds "VC_BRNAME"
If item.property = "VC_BRNAME" Then
End If
If item.checkstate.checked = True Then
End If
Next
Its my mistake replacing k + 1 to +1 in the 3rd loop will got the right answer