Delete a row in DataDridView when a value of NumericUpDown equal to zero - vb.net

For Each row As DataGridViewRow In DataGridView1.Rows
If row.Cells(0).Value = "Hawaiian" Then
row.Cells(1).Value = Double.Parse(NumericUpDown1.Value)
row.Cells(2).Value = Double.Parse(row.Cells(1).Value) * price
Exit Sub
End If
Next
DataGridView1.Rows.Add("Hawaiian", 1, price)
the code I put in NumericUpDown to add the item to DataGridView1 is above
I want the row to be deleted when Qty or Amount equal to zero, in this case, is the row for Hawaiian be delete
If NumericUpDown1.Value = 0 Then
DataGridView1.Rows.RemoveAt(DataGridView1.CurrentRow.Index)
End If
I tried this but it only deleted the first row in DataGridView1. Please help me if you know the answer, I really appreciate it. I have been trying to solve this for a week, used so many methods online all not work, I still have no clue.
Expand: the code I added from the comment, it's not deleting
The code

You are making this far more complicated than it has to be. To simplify things, I suggest you create a method that takes three (3) parameters; a string pizza name, a decimal quantity and a decimal price.
Inside this method, the first step is to check to see if quantity is zero. If it is zero, then loop through all the rows in the grid until we find the pizza name. If the pizza name is NOT found then we can return as the row is not there to begin with. If the row IS found, then we will delete that row.
If the quantity is NOT zero, then we will loop through all the rows in the grid until we find the pizza name. If the pizza name is NOT found, then we know we want to “add” the row to the grid. If the pizza name IS found, then update the quantity and amount cells.
This method may look something like…
Private Sub AddOrRemovePizzaInGrid(targetPizza As String, quantity As Decimal, price As Decimal)
If quantity = 0 Then
For Each row As DataGridViewRow In DataGridView1.Rows
If row.Cells("Item").Value IsNot Nothing Then
If row.Cells("Item").Value.ToString().Equals(targetPizza) Then
DataGridView1.Rows.Remove(row)
Return
End If
End If
Next
Return
End If
' quantity is not zero
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
If row.Cells("Item").Value IsNot Nothing Then
If row.Cells("Item").Value.ToString().Equals(targetPizza) Then
row.Cells("Qty").Value = quantity
row.Cells("Amount").Value = quantity * price
Return
End If
End If
End If
Next
' if we get here - the target pizza was not found so add as new row
DataGridView1.Rows.Add(targetPizza, quantity, quantity * price)
End Sub
In addition, since there are numerous NUD (NumericUpDown) controls on the form and each NUD is tied to a specific pizza, then instead of having a ValueChanged event for “each” NUD, I suggest you create ONE (1) ValueChanged event and have “each” NUD subscribe to this same event. When the event fires, we will check to see “which” NUD is changing its value, then simply call the above method with the proper info. This should reduce the number of events you have to manage down to one ValueChanged event for all the NUDs.
To make the code more readable I suggest you give each NUD a more logical name like NUD_Pepperoni, NUD_Hawaiian etc… as we will use the NUDs Name property to identify “which” NUDs value has changed. This event that uses the above method may look something like…
Private Sub NUD_ValueChanged(sender As Object, e As EventArgs) Handles NUD_Pepperoni.ValueChanged, NUD_Hawaiian.ValueChanged, NUD_Americano.ValueChanged
Dim target_NUD As NumericUpDown = CType(sender, NumericUpDown)
Select Case target_NUD.Name
Case "NUD_Pepperoni"
AddOrRemovePizzaInGrid("Pepperoni", target_NUD.Value, 8.5D)
Case "NUD_Hawaiian"
AddOrRemovePizzaInGrid("Hawaiian", target_NUD.Value, 8.5D)
Case "NUD_Americano"
AddOrRemovePizzaInGrid("Americano", target_NUD.Value, 8.5D)
' add more pizza types here
End Select
End Sub

According to the screenshot I think that you want to delete the item row from the DataGridView when its quantity set to zero, if so:
You have first to look to the row index in DGV then delete it by doing this:
Make a sub to find the related row & delete it
Call this sub from ValueChanged event of the Numeric object, like this:
Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged
If NumericUpDown1.Value = 0 Then
DeleteRowFromDGV("Hawaiian")
End If
End Sub
Private Sub DeleteRowFromDGV(itemName As String)
With DataGridView1
Dim rowToDelete As Short
For i As Short = 0 To .RowCount - 1
If .Item(0, i).Value = itemName Then 'suppose that the column index of item name is 0
rowToDelete = i
Exit For
End If
Next
.Rows.RemoveAt(rowToDelete)
End With
End Sub

Related

Select a specific row from ComboBox and add amount in other Column from same row in DataGridView VB.NET

I'm using VB.NET for a small project. I have a DataGridView with some rows and columns.
I want to send amounts inside a specific row & column. For this purpose I'm using a ComboBox to select the receiver, but I cant manage to select the specific row & column for the amount.
Here is a photo of the form:
[
I managed to add the receivers inside the ComboBox and to add an amount, but in all rows.
This is code (it auto generates the rows for now).
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim rowId As Integer = Me.DataGridView1.Rows.Add()
Dim row As DataGridViewRow = Me.DataGridView1.Rows(rowId)
row.Cells("Column1").Value = "UNITED BANK"
row.Cells("Column2").Value = "1000"
row.Cells("Column3").Value = "ExampleInfo"
Dim rowId2 As Integer = Me.DataGridView1.Rows.Add()
Dim row2 As DataGridViewRow = Me.DataGridView1.Rows(rowId2)
row2.Cells("Column1").Value = "FREE BANK"
row2.Cells("Column2").Value = "2000"
row2.Cells("Column3").Value = "ExampleInfo"
Dim bolAdd As Boolean = False
Dim strValue As String
For Each myRow As DataGridViewRow In Me.DataGridView1.Rows
bolAdd = True
strValue = myRow.Cells("Column1").Value
For Each myItem As String In Me.ComboBox1.Items
If myItem = strValue Then bolAdd = False
Next
If bolAdd AndAlso Not (strValue Is Nothing) Then Me.ComboBox1.Items.Add(strValue)
Next
If Me.ComboBox1.SelectedIndex = -1 Then
Me.ComboBox1.SelectedIndex = 0
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each rowX As DataGridViewRow In Me.DataGridView1.Rows
rowX.Cells(1).Value = Val(rowX.Cells(1).Value) + Val(TextBox1.Text)
Next
End Sub
End Class
With this code, I'm able to add an amount, but to all rows.
I want to add an amount only to the row I selected in the ComboBox.
Your current code in the Button1_Click event is adding the amount from the text box to ALL the rows in the grid regardless of “what” value is selected in the combo box.
From what you describe, you want the amount from the text box to be added to rows that “match” the value in the combo box. The current code is never checking this, so the value from the text box is added to all the rows in the grid.
Therefore, the code needs to check to see if the value in Column1 "Receiver" “matches” the value in the combo box. If it DOES match, then add the value from the text box to the current value in Column2 "USD."
It is unclear if there may be more rows in the grid that have the same Column1 "Receiver" value and if you want to update those values also. I am assuming that there will only be ONE row in the grid that “matches” the value in the combo box. Therefore, once we find this value and add the amount, then we are done and the code will return without looping through the rest of the rows in the grid.
So is what you need to do is alter the code in the button click event to do this checking as described above.
There are a lot of checks we need to make. We need to check that the combo box has a value to compare to. Also, before we check ANY cell value, we need to make sure the cells value is not null BEFORE we try and call the cell's Value ToString method.
In addition, the cell MAY have a value, however, it may not be a number, so we have to check and make sure the value in the cell is an actual number and the same would apply to the text box.
So, walking through the code below would go something like…
If (Int32.TryParse(TextBox1.Text, addedValue)) … checks to see if
the text box amount is a valid number.
If (Not String.IsNullOrEmpty(targetComboValue)) … checks to make
sure the combo box value is not empty.
Then we start the loop through all the rows in the grid.
If (Not rowX.IsNewRow) … checks to see if the row is the “new” row
which we will ignore this “new” row.
If (rowX.Cells("Column1").Value IsNot Nothing) … checks to make
sure the “Receiver” cell is not null
If (rowX.Cells("Column1").Value.ToString() = targetComboValue) …
checks to see if the “Receiver” cells value matches the value in the
combo box.
If (rowX.Cells("Column2").Value IsNot Nothing) … check to make sure
the “USD” cell is not null.
And Finally,…
If (Int32.TryParse(rowX.Cells("Column2").Value.ToString(), currentValue)) … check to see if the value in the “USD” cell is a valid number.
If all these checks succeed then add the value from the text box to the current value in the “USD” cell.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim targetComboValue = ComboBox1.SelectedItem
Dim addedValue As Int32
Dim currentValue As Int32
If (Int32.TryParse(TextBox1.Text, addedValue)) Then
If (Not String.IsNullOrEmpty(targetComboValue)) Then
For Each rowX As DataGridViewRow In Me.DataGridView1.Rows
If (Not rowX.IsNewRow) Then
If (rowX.Cells("Column1").Value IsNot Nothing) Then
If (rowX.Cells("Column1").Value.ToString() = targetComboValue) Then
If (rowX.Cells("Column2").Value IsNot Nothing) Then
If (Int32.TryParse(rowX.Cells("Column2").Value.ToString(), currentValue)) Then
rowX.Cells("Column2").Value = currentValue + addedValue
Return
End If
End If
End If
End If
End If
Next
End If
End If
End Sub
I hope this makes sense.
You can edit the desired row just by using a syntax as follow:
Me.DataGridView1.Rows(1).Cells(2).Value = "your string"
So if you want to select corresponding to your combo index :
Dim myId As Integer = Me.ComboBox1.SelectedIndex
Me.DataGridView1.Rows(myId).Cells(2).Value = "your string"
But this assuming that the count of combo and DataGridView are same.
If not you should think about to add an id Column in your DataGridView ...
If you mean something else please explain, I will edit.

Create x-axis for department and y-axis for total ticket based on datagridview vb.net

i am a beginner in vb. i have a datagridview which the data extract from excel file. My data look like this
. I want to create a column chart where x-axis is Department and y-axis is total of status ticket that is open and close.Below is my code which i have stuck and i know i get errors but this is the idea.
i want the result like this
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Chart1.Series("Open").Points.AddXY("Finance", value)
Me.Chart1.Series("Open").Points.AddXY("ITMS", value)
Me.Chart1.Series("Open").Points.AddXY("RV", value)
Me.Chart1.Series("Open").Points.AddXY("Security", value)
Me.Chart1.Series("Close").Points.AddXY("Finance", value)
Me.Chart1.Series("Close").Points.AddXY("ITMS", value)
Me.Chart1.Series("Close").Points.AddXY("RV", value)
Me.Chart1.Series("Close").Points.AddXY("Security", value)
For Count As Integer = 0 To DataGridView1.Rows.Count - 2
Chart1.Series("Open").Points.AddXY(DataGridView1.Item(1, Count).Value, DataGridView1.Item(1, Count).Value)
Chart1.Series("Close").Points.AddXY(DataGridView1.Item(1, Count).Value, DataGridView1.Item(1, Count).Value)
Next
End Sub
End Class
From what I can decipher from the pictures of the data and the chart… you want the number of “open-close” tickets from “Finance” for the first two data points in the chart. The other points are ITMS, RV and Security “departments.” The problem with the posted code is that the current loop is not “adding” the “open” tickets or “closed” tickets for each department. The code is simply “adding” another point to the chart instead of “adding 1” to the existing point.
Tracing the posted for loop using the picture of the grid data, this will add a total of nine (9) points in the chart, the “SAME” nine points are in both the Open/Close” series. However, since departments like “Finance” have three (3) points with the same value, this will display in the chart as three (3) separate “Finance” “departments” … it is here that you need to “add” 1 to the value of the existing “Finance-open/close” point and not simply add “another” “Finance-open/close” point.
The code will need to loop through the grids rows and accumulate the total number of rows that have “Finance” AND “Open”, “Finance” AND “Close”, “ITMS” AND “Open” … etc. This will give you the charts “y” values for each department-open/close. Given this, one possible solution is to write a method that takes two string parameters (department, status) and returns an integer that contains the numbers of rows that match “both” the department and status. These would become the data points for the chart. In this example, you would only be adding eight (8) data points, One for “Finance” “Open” another for “Finance” “Close” … etc... I hope that makes sense.
Below is a simple loop through the grids rows that accumulates the eight points. The method described above is not necessarily the best approach if the data set is large. The described method would loop through the grid a total of eight (8) times. Once for “Finance” and “Open”, another loop through the grid to get “Finance” “Close” … etc. The code below loops through the grid only “once”, however this approach requires the addition of the 8 variables. Pick your poison… hope this helps.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' 8 variables to hold the totals
Dim FinanceOpenCount = 0
Dim FinanceCloseCount = 0
Dim ITMSOpenCount = 0
Dim ITMSCloseCount = 0
Dim RVOpenCount = 0
Dim RVCloseCount = 0
Dim SecurityOpenCount = 0
Dim SecurityCloseCount = 0
' loop through each row and "ADD" 1 to the proper variables
For Each row As DataGridViewRow In DataGridView1.Rows
Select Case row.Cells("Department").Value
Case "Finance"
If (row.Cells("Status").Value = "Open") Then
FinanceOpenCount += 1
Else
FinanceCloseCount += 1
End If
Case "ITMS"
If (row.Cells("Status").Value = "Open") Then
ITMSOpenCount += 1
Else
ITMSCloseCount += 1
End If
Case "RV"
If (row.Cells("Status").Value = "Open") Then
RVOpenCount += 1
Else
RVCloseCount += 1
End If
Case "Security"
If (row.Cells("Status").Value = "Open") Then
SecurityOpenCount += 1
Else
SecurityCloseCount += 1
End If
End Select
Next
' add the points to the chart
Chart1.Series("Open").Points.Clear()
Chart1.Series("Close").Points.Clear()
Chart1.Series("Open").Points.AddXY("Finance", FinanceOpenCount)
Chart1.Series("Close").Points.AddXY("Finance", FinanceCloseCount)
Chart1.Series("Open").Points.AddXY("ITMS", ITMSOpenCount)
Chart1.Series("Close").Points.AddXY("ITMS", ITMSCloseCount)
Chart1.Series("Open").Points.AddXY("RV", RVOpenCount)
Chart1.Series("Close").Points.AddXY("RV", RVCloseCount)
Chart1.Series("Open").Points.AddXY("Security", SecurityOpenCount)
Chart1.Series("Close").Points.AddXY("Security", SecurityCloseCount)
End Sub
Multiple looping method described above.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Chart2.Series("Open").Points.Clear()
Chart2.Series("Close").Points.Clear()
Chart2.Series("Open").Points.AddXY("Finance", GetDeptStatusCount("Finance", "Open"))
Chart2.Series("Open").Points.AddXY("ITMS", GetDeptStatusCount("ITMS", "Open"))
Chart2.Series("Open").Points.AddXY("RV", GetDeptStatusCount("RV", "Open"))
Chart2.Series("Open").Points.AddXY("Security", GetDeptStatusCount("Security", "Open"))
Chart2.Series("Close").Points.AddXY("Finance", GetDeptStatusCount("Finance", "Close"))
Chart2.Series("Close").Points.AddXY("ITMS", GetDeptStatusCount("ITMS", "Close"))
Chart2.Series("Close").Points.AddXY("RV", GetDeptStatusCount("RV", "Close"))
Chart2.Series("Close").Points.AddXY("Security", GetDeptStatusCount("Security", "Close"))
End Sub
Private Function GetDeptStatusCount(department As String, status As String) As Int32
Dim count = 0
For Each row As DataGridViewRow In DataGridView1.Rows
If (row.Cells("Department").Value = department And row.Cells("Status").Value = status) Then
count += 1
End If
Next
Return count
End Function

ArgumentOutOfRangeException on Datagridview with 1 row

I have a strange problem. I have a form with on it 2 unbounded datagridviews and 2 buttons. With the buttons I switch the rows from 1 datagrid to the other.
In the beginning the left datagrid is filled with a number of rows and the right datagrid is empty. So when I click on the button "Add" the selected row from the left datagrid is removed and added to the right datagrid. With the button "Delete" the selected row of the right datagrid is added back to the left datagrid.
When there is only one row in the right datagrid, and I select it to "delete" it, the row is removed from the right datagrid and added to the left without an exception. Now I have a situation where there is only one row in the left datagrid and when I click "Add" to move it to the right datagrid I get an ArgumentOutOfRangeException (index is out of bounds...)
Below is the code which throws the exception
For i As Integer = DgvLeft.SelectedRows.Count - 1 To 0 Step -1
ind = DgvLeft.SelectedRows(i).Index
If ind > 0 Then
DgvLeft.Rows.RemoveAt(ind)
Else
DgvLeft.Rows.Remove(DgvLeft.SelectedRows(i))
End If
Next
So I store the row index in a variable. The first time I used the RemoveAt function and the exception is thrown. To resolve this I added the If-structure and tried the Remove function. But again the exception is thrown.
I don't understand why the exception is thrown. I use the same code for the "delete" button and there it doesn't happen. Also when I store the RowIndex in a variable the index is known, but not when I try to Remove the row.
Can someone help me with this strange problem?
Since the posted for loop is “broken”, I feel it is unnecessary to question what you are trying to accomplish here. However, given what you described where there are two grids and two buttons (Add/Delete) on a form. When the “Add” button is clicked, it moves the “selected rows” from the “left” grid to the “right” grid, and then deletes the “selected rows” rows from the “left” grid. If the “Delete” button is clicked, then the opposite process happens moving the “selected rows” from the right grid to the left grid, then delete the selected rows from the right grid.
If this is correct, then it appears you are making this more complicated than it has to be. This would be much easier if you used a data source of some form. However, to break the above problem down, it appears that two methods may come in handy for what you want to do. The first one could simply add the selected rows from one given grid to another given grid. The next method would simply delete the selected rows from a given grid. With these two methods implemented, the “add” button would be…
AddSelectedRows(dgvLeft, dgvRight)
RemoveSelectedRows(dgvLeft)
The delete button would be…
AddSelectedRows(dgvRight, dgvLeft)
RemoveSelectedRows(dgvRight)
Before I explain the code below, it should be noted that your current posted code is making a huge programming “no-no” and without question is a problem for you. As Mary and others have pointed out, “changing the value of the counter variable in a loop or (as the code does) changing the collection it is looping through is rarely if ever done.”
Try the code below it may make things easier,
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
AddColumns(dgvLeft)
AddColumns(dgvRight)
FillGrid(dgvLeft)
End Sub
Private Sub FillGrid(dgv As DataGridView)
For i = 0 To 15
dgv.Rows.Add("C0R" + i.ToString(), "C1R" + i.ToString(), "C2R" + i.ToString())
Next
End Sub
Private Sub AddColumns(dgv As DataGridView)
Dim txtCol = New DataGridViewTextBoxColumn()
txtCol.Name = "Col0"
txtCol.HeaderText = "Col 0"
dgv.Columns.Add(txtCol)
txtCol = New DataGridViewTextBoxColumn()
txtCol.Name = "Col1"
txtCol.HeaderText = "Col 1"
dgv.Columns.Add(txtCol)
txtCol = New DataGridViewTextBoxColumn()
txtCol.Name = "Col2"
txtCol.HeaderText = "Col 2"
dgv.Columns.Add(txtCol)
End Sub
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
AddSelectedRows(dgvLeft, dgvRight)
RemoveSelectedRows(dgvLeft)
End Sub
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
AddSelectedRows(dgvRight, dgvLeft)
RemoveSelectedRows(dgvRight)
End Sub
Private Sub RemoveSelectedRows(dgv As DataGridView)
Dim totalRowsToDelete = dgv.SelectedRows.Count
Dim selectedRow As DataGridViewRow
For i = totalRowsToDelete - 1 To 0 Step -1
selectedRow = dgv.SelectedRows(i)
If (Not selectedRow.IsNewRow) Then
dgv.Rows.RemoveAt(dgv.SelectedRows(i).Index)
End If
Next
End Sub
Private Sub AddSelectedRows(sourceDGV As DataGridView, destinationDGV As DataGridView)
Dim selectedRowCount = sourceDGV.Rows.GetRowCount(DataGridViewElementStates.Selected)
If (selectedRowCount > 0) Then
Dim selectedRow As DataGridViewRow
For i = 0 To selectedRowCount - 1
selectedRow = sourceDGV.SelectedRows(i)
If (Not selectedRow.IsNewRow) Then
destinationDGV.Rows.Add(selectedRow.Cells(0).Value.ToString(),
selectedRow.Cells(1).Value.ToString(),
selectedRow.Cells(2).Value.ToString())
End If
Next
End If
End Sub
You are changing the value of DgvLeft.SelectedRows.Count in your For loop.
Try...
Dim RowCount As Integer = DgvLeft.SelectedRows.Count
For i As Integer = RowCount - 1 To 0 Step -1
I want to thank Mary for her answer, because that made me think about my code. I looked at the code of the "delete" button, where I use the same for loop, and that code doesn't throw an exception. So there must be a difference between the code of my two buttons.
This is an expanded piece of my code in the "add" button:
For i As Integer = DgvLeft.SelectedRows.Count - 1 To 0 Step -1
'fill the array with the row values
For j As Integer = 0 To DgvLeft.Columns.Count - 1
fields(j) = DgvLeft.SelectedRows(i).Cells(DgvLeft.Columns(j).Name).Value
Next
'delete the row in datagrid Left
ind = DgvLeft.SelectedRows(i).Index
If ind > 0 Then
DgvLeft.Rows.RemoveAt(ind)
Else
DgvLeft.Rows.Remove(DgvLeft.SelectedRows(i))
End If
'add the row in datagrid Right
DgvRight.Rows.Add(fields)
Next
In the code snippet above I attempt to remove a row BEFORE I add the array of values from this row to the other datagrid. When I looked at the code of the "delete" button I attempt to remove the row AFTER I add the array of values to the other datagrid.
So I moved this piece of code below the code of adding the array of values and it worked. Probably the index exception is thrown by the array rather than the datagridview.

How to validate data on datagridview to prevent duplicate

for example i have "NID" as textbox and datagrid with #NID field.
i want save NID with Value "N001" to #NID on datagrid.
how to prevent duplicate when i save NID with value "N001" to datagrid.
I trying like this but error
private sub save()
dim dgv as datagridview1
if dgv.CurrentRow.Cells(0).value = NID.text then
msgbox("Data duplicate")
else
dgv.rows.insert(.NewRowIndex, NID.text)
end if
end sub
help me
thanks
In your code, you are only checking the current row of the DataGridView. You need to check all the rows.
'For loops are inclusive, meaning that both indexes will be reached.
'dgv.Rows is a zero indexed collection so "dgv.Rows(dgv.RowCount)" would give an error
For i = 0 To dgv.RowCount - 1
If dgv.Rows(i).Cells(0).Value = NID.Text
MsgBox("Duplicate data")
Exit Sub 'So no insert occurs
End If
Next
'code to insert row

Find missing value in a numbers sequence - DGV column

I tried searching and didn't have any success in fixing my problem so I tried finding my own solution.
First I found max (Max) value (min value is always 1), then I set loop to search value by value, but something is wrong with my loop.
For i As Integer = 1 To Max
For y As Integer = 0 To DataGridView1.Rows.Count - 1
If DataGridView1.Rows(y).Cells(0).Value = i Then
Else
builder2.Append(i & ",")
End If
Next
Next
To me loop looks OK but it's not working. If value i is found do nothing if it's not found add i to stringbuilder, and so on until it reaches Max value. But whatever combination I've tried I get some weird results.
Numbers are sorted from lowest to highest.
I've also extracted all values from DGV column to comma delimited string if it's easier that way...
EDIT :
Just for experimenting with that loop I've put i = 40 to 50 (to reduce the range). I know that missing values in DGV column are 40-46 and 59.
This is what I've got with loop above :
You can use LINQ to find missing numbers quite easily. You just need to get the existing numbers into a List, and then you can use Max() to find the largest number, and Except() to find the missing ones.
I put a DGV named DataGridView1 with one column, a button named bnPopulateDGV, and a button named bnFindMissingNumbers on a new Windows Form, and used the following code (with Option Infer On):
Private Sub bnPopulateDGV_Click(sender As Object, e As EventArgs) Handles bnPopulateDGV.Click
DataGridView1.Rows.Clear()
Dim seq1 = Enumerable.Range(1, 100).ToList()
Dim rand As New Random
' knock some out
For i = 1 To 5
seq1.RemoveAt(rand.Next(0, 50))
Next
For Each s In seq1
DataGridView1.Rows.Add(New String() {s.ToString()})
Next
End Sub
Private Sub bnFindMissingNumbers_Click(sender As Object, e As EventArgs) Handles bnFindMissingNumbers.Click
Dim existingNumbers As New List(Of Integer)
For Each r As DataGridViewRow In DataGridView1.Rows
existingNumbers.Add(CInt(r.Cells(0).Value))
Next
Dim min = 1
Dim max = existingNumbers.Max()
Dim missingNumbers = Enumerable.Range(min, max - min + 1).Except(existingNumbers)
MsgBox("Missing: " & String.Join(", ", missingNumbers))
End Sub