ERROR: make sure that the index is less than the size of the collection - vb.net

When I select/click the first 2 rows individually, I am fine. I get an error if I select/click any row after that. The error message is:
" Index was out of range. Must be non-negative and less than the size of the collection"
I added a RowIndexCount to count how many rows the application is reading, and it returns 84. What is possible wrong with it?
VB.NET
Dim rowDGVDataPhys As Integer = DGVDataPhys.CurrentCell.RowIndex
txtRowIndex.text = rowDGVDataPhys
DGVDataPhys.Rows(rowDGVDataPhys).Selected = True
DGVData.Enabled = True
DGVDataPhys.Enabled = True
Dim CountRowIndexes As Integer = 0
CountRowIndexes = DGVDataPhys.RowCount
'To capture how many total rows in the GRID.
MsgBox(CountRowIndexes) 'I found 84 rows
vDeptID = DGVDataPhys.Rows(DGVDataPhys.SelectedCells(rowDGVDataPhys).RowIndex.ToString()).Cells("DeptKey").Value
vDeptName = DGVDataPhys.Rows(DGVDataPhys.SelectedCells(rowDGVDataPhys).RowIndex.ToString()).Cells("DeptName").Value

You are indexing row using the SelectedCells collection, not the Current cells Row index...
Do this instead
vDeptID = DGVDataPhys.Rows(rowDGVDataPhys).Cells("DeptKey").Value
vDeptName = DGVDataPhys.Rows(rowDGVDataPhys).Cells("DeptName").Value

Related

How to add a new row into DataGridView and fill it with data

This is my code
Public Sub InvoicItmCall()
'If IteDataTb.Rows.Count = 0 Then Exit Sub
SellingDGView.Rows.Add()
SellingDGView.Rows.Item(0).Cells(0).Value = SellingDGView.Rows.Item(0).Cells(0).Value + 1
SellingDGView.Rows.Item(0).Cells(1).Value = IteDataTb.Rows(0).Item("IteFName")
SellingDGView.Rows.Item(0).Cells(2).Value = IteDataTb.Rows(0).Item("IteFSizeUnit")
SellingDGView.Rows.Item(0).Cells(4).Value = IteDataTb.Rows(0).Item("IteFSellpris")
SellingDGView.Rows.Item(0).Cells(6).Value = IteDataTb.Rows(0).Item("IteVat")
'Dim unused = SellingDGView.Rows.Add(rows)
End Sub
Right now, the code works fine and fills the first row on the grid, this is for a barcode scanner. When I scan one barcode, it fills the row with the appropriate data. However, when I scan another code, it overwrites the older row.
I want it to add a new row and add the other data to it.
So when I scan a different item after the first one, it should fill up a new row.
How do I do that?
Thanks in advance :)
EDIT:
I have found a workaround
If IteDataTb.Rows.Count > 0 Then
For Each row As DataRow In IteDataTb.Rows
SellingDGView.Rows.Add(row.Item("IteFName"), row.Item("IteFSizeUnit"), row.Item("IteFSellpris"), row.Item("IteVat"))
Next row
End If
This creates a new row every time and fills it. But now I want to fill specific cells.
How do I do that?
Right now it fills everything inappropriately.
If you wanted to do it the way you originally were, I'd do it like this:
Dim index = SellingDGView.Rows.Add()
Dim newRow = SellingDGView.Rows(index)
'Dim newRow = SellingDGView.Rows(SellingDGView.Rows.Add())
Dim dataRow = IteDataTb.Rows(0)
newRow.Cells(0).Value = SellingDGView.Rows(0).Cells(0).Value + 1
newRow.Cells(1).Value = dataRow("IteFName")
newRow.Cells(2).Value = dataRow("IteFSizeUnit")
newRow.Cells(4).Value = dataRow("IteFSellpris")
newRow.Cells(6).Value = dataRow("IteVat")
If you wanted to use the more appropriate overload of Add that I mentioned and you used in your second example:
For Each row As DataRow In IteDataTb.Rows
SellingDGView.Rows.Add(SellingDGView.Rows(0).Cells(0).Value + 1,
row("IteFName"),
row("IteFSizeUnit"),
Nothing,
row("IteFSellpris"),
Nothing,
row("IteVat"))
Next
The If statement is pointless.
Also, I doubt that you're getting the next ID in the best way with that expression that adds 1 but that's a different question.
Every time that you need a new row, you can do as follows:
Dim i As Integer = SellingDGView.Rows.Add()
SellingDGView.Rows.Item(i).Cells(0).Value = i
SellingDGView.Rows.Item(i).Cells(1).Value = IteDataTb.Rows(j).Item("IteFName")
SellingDGView.Rows.Item(i).Cells(2).Value = IteDataTb.Rows(j).Item("IteFSizeUnit")
SellingDGView.Rows.Item(i).Cells(4).Value = IteDataTb.Rows(j).Item("IteFSellpris")
SellingDGView.Rows.Item(i).Cells(6).Value = IteDataTb.Rows(j).Item("IteVat")
Herein, I've assumed that the variable "j" indicates to your desired row in IteDataTb datagridview. I mean that you should control the "j" variable yourself. I can help you if know more about the IteDataTb.

Referencing value from Excel Listbox item in .Match function in VBA

I am hoping to use the string value of a selected Listbox item in a .Match function within VBA - I need the the value '1' to be entered into the row where the value of the selection matches a value in column "A:A", on a specific column.
What I thought I would be able to do is to use a .value argument for the selected ListBox item, however this seems to either error out or give me a Boolean response, which isn't what I am after (I am after the actual string value of the item).
I have already looped through all items to set the Selected argument to True, and then I am looping through the list one by one to add '1' to the correct range.
Here is the code I thought would work (but doesn't, it throws an error of "Run-time error '13': Type mismatch" which is presumably down to the .Value not being a String.
For x = 0 To Me.CreditsEmployeesListBox.ListCount - 1
Me.CreditsEmployeesListBox.Selected(x) = True
Next
For i = 0 To Me.CreditsEmployeesListBox.ListCount - 1
If Me.CreditsEmployeesListBox.Selected(i) = True Then
employeeRow = WorksheetFunction.Match(Me.CreditsEmployeesListBox(i).Value, IndexSheet.Range("A:A"), 0)
IndexSheet.Range(Cells(employeeRow, showCodeColumn).Address).Value = 1
End If
Next
It errors out on the 'employeeRow = ...' line. Here, I am essentially trying to ask it:
employeeRow = WorksheetFunction.Match(<value of the currently referenced ListBox item>,IndexSheet.Range("A:A"),0)
Is this possible with VBA or am I going about this the wrong way?
Thanks
Matt
As an "hybrid" answer (as there is more than one problem) try this:
For x = 0 To Me.CreditsEmployeesListBox.ListCount - 1
Me.CreditsEmployeesListBox.Selected(x) = True
Next
Dim employeeRow As Variant
For i = 0 To Me.CreditsEmployeesListBox.ListCount - 1
If Me.CreditsEmployeesListBox.Selected(i) = True Then
employeeRow = Application.Match(Me.CreditsEmployeesListBox.List(i), IndexSheet.Columns(1), 0)
If IsNumeric(employeeRow) Then IndexSheet.Cells(employeeRow, showCodeColumn).Value = 1
End If
Next
This also should avoid VBA-errors.
If any questions are left, just ask :)

Excel VBA - count number of different parameters in table

I have some problems with my excel VBA code, it does not work and yes, I do not know why...
I want to add each Record number once in a collection. My code looks like this:
For i = 1 To lo.ListRows.Count
Count = 1
Do While recordList.Count >= Count
recordFound = False
If lo.ListColumns("Record").DataBodyRange.Rows(i) = recordList(Count) Then
recordFound = True
End If
If recordFound = False Then
recordList.Add (lo.ListColumns("Record").DataBodyRange.Rows(i))
End If
Count = Count + 1
Loop
Next
What it does now, it returns empty collection...
Whould be great if you could help me guys!
There is no real need to test the Collection to see if the item exists if you give it a key.
You can code something like:
On Error Resume Next
For I = 1 To lo.ListRows.Count
With lo.ListColumns("Record").DataBodyRange.Rows(I)
RecordList.Add Item:=.Value, Key:=CStr(.Value)
End With
Next I
On Error GoTo 0
Adding an item with the same key will cause the operation to be rejected. If you are concerned about other errors than the duplicate key error, you can always check the error number in the inline code and branch depending on the results.
I haven't been able to test this with the reference to lo but it works with a reference to a range
Dim objDictionary As Object
Dim dictionaryKey As Variant
Dim i As Long
Set objDictionary = CreateObject("Scripting.Dictionary")
For i = 1 To lo.ListRows
objDictionary.Item(CStr(lo.ListColumns("Record").DataBodyRange.Rows(i))) = objDictionary.Item(CStr(lo.ListColumns("Record").DataBodyRange.Rows(i))) + 1
Next i
For Each dictionaryKey In objDictionary.keys
' Do something
Next dictionaryKey
I have used a dictionary object instead of a normal collection object as it should do what you are trying to do. Because the item is incremented each time, you can also return the count of each item by using
objDictionary.item(dictionaryKey)

Get row index if some column value is equal to something

In this datatable there are no duplicates, I need the row index where column x value equals 2. I would do it like this:
Dim rowIndex As Integer = 0
For i = 0 To mtable.Rows.Count - 1
If mtable.Rows(i)("x") = 2 Then
rowIndex = i
Exit For
End If
Next
I will be calling this process multiple times per second. Is there a faster way to do this in .NET?
DataTable select could work, i think it should be faster than iterating over the collection of rows.
var index = mtable.Rows.IndexOf(mtable.Select("x = 2").FirstOrDefault());
Multiple times per second is a bit vague - tens or thousands?
You could create a hash table mapping the value of "x" to the row number:
Dim nLookups = mtable.Rows.Count - 1
Dim lookupHash As New Hashtable(nLookups)
For i = 0 To nLookups
lookupHash.Add(CInt(mtable.Rows(i)("x")), i)
Next
then
Dim rowSought As Integer = -1
If lookupHash.ContainsKey(2) Then
rowSought = lookupHash(2)
End If
Or if the range of possible values of "x" is suitable, you could use an array to map the value to the row number.

Not able to add values in second Combobox

Here is my code.
for example TextBox1.Text= 12,34,45,67,67
Dim process_string As String() = TextBox1.Text.Split(New Char() {","})
Dim process As Integer
For Each process In process_string
Combo1.Items.Add(process)
count = count + 1
Next process
total_process.Text = count
End If
Dim array(count) As String
Dim a As Integer
For a = 0 To count - 1
array(a) = Combo1.Items(a).ToString
Next
a = 0
For a = count To 0
Combo2.Items.Add(array(a).ToString)
Next
i want to add values in reversed order in combobox2 that are available in combobox1
but when i run the application the second combobox remains empty and not showing any value.
You've specified this for loop
For a = count To 0
But you need to add STEP -1 to go backwards like that.
For a = count To 0 Step -1
2 things. First of all, K.I.S.S. Keep it simple stupid
For i As Integer = ComboBox1.Items.Count - 1 To 0 Step -1
ComboBox2.Items.Add(ComboBox1.Items(i))
Next
second: It didn't work because you forgot the Step -1 on your last loop
~~~~~~~~~~~~~~Edit~~~~~~~~~~~~~~
Sorting the data in a combo box should be done with the sorted property on a combo box
ComboBox3.Sorted = True
Sorting the data in reverse order should be done with arrays as you were trying to do before. The following code should suffice:
Dim List As ArrayList = ArrayList.Adapter(ComboBox3.Items)
List.Sort()
List.Reverse()
ComboBox4.Items.AddRange(List.ToArray)
If you wanted to get creative, you could potentially create your own combo box class and make your own version of the sorted property that allows for "sort alpha", "sort numeric", "sort alpha Desc", and "sort numeric desc" and perhaps some other options. But I'd only do that if you were going to use this in a lot of places.