How I can set the index of Datagridview to 0 - vb.net

How I can set the index of DataGridView to 0?
I developed a pharmacy software where I want to add values from TextBoxes into DataGridView with adding a new row. It is working but the problem is when I clear the value of DataGridView by using this code
dgvSoldMedicineInfo.Rows.Clear()
then when I try the previous procedure it show this error in VB.NET
Index was out of range, Must be non-negative and less than the size of the collection. Parameter name:index
Code:
Dim rowcounter As Integer = 0
Private Sub btnCalculate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculate.Click
dgvSoldMedicineInfo.Rows.Add()
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnBarcodeNo").Value = txtBarcodeNo.Text
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnName").Value = dgvSale.CurrentRow.Cells(2).Value
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnQuantity").Value = txtQuantity.Text
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnSalePrice").Value = txtSalePrice.Text
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnAmount").Value = txtTotalAmount.Text
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnReject").Value = "Reject"
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnStockID").Value = dgvSale.CurrentRow.Cells(0).Value
dgvSoldMedicineInfo.Rows(rowcounter).Cells("ColumnStockQuantity").Value = dgvSale.CurrentRow.Cells(3).Value
System.Math.Max(System.Threading.Interlocked.Increment(rowcounter), rowcounter - 1)
End Sub

There's really no point to that rowcounter variable in that context and it's bad form to keep using dgvSoldMedicineInfo.Rows(rowcounter) over and over again. The proper way to do that would be like so:
Dim rowIndex = dgvSoldMedicineInfo.Rows.Add()
Dim row = dgvSoldMedicineInfo.Rows(rowIndex)
Dim cells = row.Cells
cells("ColumnBarcodeNo").Value = txtBarcodeNo.Text
cells("ColumnName").Value = dgvSale.CurrentRow.Cells(2).Value
'etc.
That said, why do that when the Add method is overloaded and will accept all the cell values up front?
dgvSoldMedicineInfo.Rows.Add(txtBarcodeNo.Text,
dgvSale.CurrentRow.Cells(2).Value,
...)

Related

Pass values from Numeric control into corresponding cells in DataGridView control with a button

I want to move the values from each of four Numeric Up/Down controls into the DataGridView columns/rows with a button. For instance, the operator sets the values in the up/down numeric controls and then clicks the button. The program should then add a new row to the DataGridView and pass whatever values that are in the Numeric Up/Down controls into the new cells of the new row. As of now, I have the adding new rows part of it working as well as the delete button working (delete last row of the DataGridView). Now, how to pass the Numeric control values into the cell of the new row of the DataGridView with the button? Each new row created of the DatGridView has four cells to correspond to the four Numeric up/down controls. Thank you.
Private Sub addStep_btn_Click(sender As Object, e As EventArgs) Handles addStep_btn.Click
LftMtr_Data_Grid.ColumnCount = 4
LftMtr_Data_Grid.RowCount = LftMtr_Data_Grid.RowCount + 1
LftMtr_Data_Grid.Columns(0).HeaderText = " Spindle Speed (rpm)"
LftMtr_Data_Grid.Columns(1).HeaderText = " Accel Rate (rpm/S)"
LftMtr_Data_Grid.Columns(2).HeaderText = " Decel Rate (rpm/S)"
LftMtr_Data_Grid.Columns(3).HeaderText = " Time (S)"
For Each c As DataGridViewColumn In LftMtr_Data_Grid.Columns
c.Width = 120
Next
Dim rowNumber As Integer = 1
For Each row As DataGridViewRow In LftMtr_Data_Grid.Rows
If row.IsNewRow Then Continue For
row.HeaderCell.Value = "Step " & rowNumber
rowNumber = rowNumber + 1
Next
LftMtr_Data_Grid.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
rowCount1 = LftMtr_Data_Grid.RowCount
txtBox1.Text = rowCount1
End Sub
Try something like below. Note that you don't need to setup the column headers everytime, just once in the Load() event would do!
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LftMtr_Data_Grid.ColumnCount = 4
LftMtr_Data_Grid.Columns(0).HeaderText = " Spindle Speed (rpm)"
LftMtr_Data_Grid.Columns(1).HeaderText = " Accel Rate (rpm/S)"
LftMtr_Data_Grid.Columns(2).HeaderText = " Decel Rate (rpm/S)"
LftMtr_Data_Grid.Columns(3).HeaderText = " Time (S)"
For Each c As DataGridViewColumn In LftMtr_Data_Grid.Columns
c.Width = 120
Next
LftMtr_Data_Grid.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
End Sub
Private Sub addStep_btn_Click(sender As Object, e As EventArgs) Handles addStep_btn.Click
Dim values() As Object = {NumericUpDown1.Value, NumericUpDown2.Value, NumericUpDown3.Value, NumericUpDown4.Value}
Dim index As Integer = LftMtr_Data_Grid.Rows.Add(values)
LftMtr_Data_Grid.Rows(index).HeaderCell.Value = "Step " & (index + 1)
LftMtr_Data_Grid.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders)
End Sub
Private Sub delStep_btn_Click(sender As Object, e As EventArgs) Handles delStep_btn.Click
If LftMtr_Data_Grid.Rows.Count > 0 Then
LftMtr_Data_Grid.Rows.RemoveAt(LftMtr_Data_Grid.Rows.Count - 1)
End If
End Sub
End Class
I figured it out on my own. Here is what I came up with:
Dim rowNumber As Integer = 1
For Each row As DataGridViewRow In LftMtr_Data_Grid.Rows
If row.IsNewRow Then Continue For
row.HeaderCell.Value = "Step " & rowNumber
LftMtr_Data_Grid.CurrentCell = LftMtr_Data_Grid.Rows(LftMtr_Data_Grid.RowCount - 1).Cells(0)
LftMtr_Data_Grid.CurrentRow.Cells(0).Value = LftMtr_Speed_Incr.Value
LftMtr_Data_Grid.CurrentRow.Cells(1).Value = LftMtr_Accel_Incr.Value
LftMtr_Data_Grid.CurrentRow.Cells(2).Value = LftMtr_Decel_Incr.Value
LftMtr_Data_Grid.CurrentRow.Cells(3).Value = test_Time_Incr1.Value
rowNumber = rowNumber + 1
Next
This application works with an empty or partially filled dataGridView. When the user clicks the button, the code creates a new row in the dataGridView, makes the new row the selected row, and then finally populates each of the cells in the new row with the values that are in the four Numeric Up/down controls (could be a text box too depending on your application). This is code copied directly from my specific application. Yours may differ slightly with variable names, label text, etc.

How to compare DataGridView cell data to DataSet cell data

In a VB.NET WinForms project I'm working on in VS2013 I am detecting when the user changes something in a cell on the CellValueChanged event. When a row in the DataGridView is found that is different from the DataSet I highlight the row in pink.
In my code though, I only know how to iterate through all of the rows, rather than just compare the row that fired the CellValueChanged event to the DataSet.
Here's my current code:
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer)
' Force ending Edit mode so the last edited value is committed
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
Dim currentColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
Console.WriteLine("Row index: " & dt.Rows.IndexOf(row))
' This works
dgvEmployees.Rows(rowIndex).DefaultCellStyle.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
Next
Next
End If
End Sub
As you can see, I'm passing the row and column index of the changed cell, so how can I take that and compare it to the specific row and/or cell in the unchanged DataSet?
UPDATE
Nocturnal reminded me that I need to allow for sorting of the DGV, so using row indexes won't work. He offered this as a solution (changed slightly to work with my objects):
If Not dsChanged Is Nothing Then
For Each dtrow As DataRow In dsChanged.Tables("employees").Rows
If DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID.ToString = dgvEmployees.Rows(rowIndex).Cells("employeeID").Value.ToString Then
For i As Integer = 0 To dsChanged.Tables("employees").Columns.Count - 1
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID)
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
End If
Next
End If
However, I'm getting an error on the If DirectCast... line saying "Column named "employeeID" cannot be found." I'm not sure if the error is on the DataSet or on the DGV, but there is an employeeID column in the database and DataSet. There is an employeeID as a bound column for the DataGridView, but it is set to Visible = False. That's the only thing I can think of that could possibly cause that error, but if it's a bound column, I would think it could be compared against as in this case.
FINAL WORKING VERSION
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource("employees", e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal dataSetName As String, ByVal rowIndex As Integer, ByVal columnIndex As Integer)
' Takes a dataset and the row and column indexes, checks if the row is different from the DataSet and colors the row appropriately
EmployeesBindingSource.EndEdit()
Dim dsChanges As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanges Is Nothing Then
For Each dtrow As DataRow In dsChanges.Tables("employees").Rows
If DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID.ToString = dgvEmployees.Rows(rowIndex).Cells("employeeID").Value.ToString Then
For i As Integer = 0 To dsChanges.Tables("employees").Columns.Count - 1
If dtrow.RowState.ToString = DataRowState.Added.ToString Then
' TODO: Color entire new row
ElseIf dsChanges.Tables(dataSetName).Rows(0).HasVersion(DataRowVersion.Original) Then
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID)
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' TODO: Need to change the BackColor back to what it should be based on its original alternating row color
End If
End If
Next
End If
Next
End If
End Sub
My project has four DGVs in it, so this will eventually be expanded to allow for all four DGVs to be checked for changes.
have a look at this approach it is simlar but only iterating the specific Table
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex, sender.DataSource.datamember.ToString)
End Sub
and comparing the ID of the given Table
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer, tablename As String)
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dtrow As DataRow In dsChanged.Tables(tablename).Rows
If DirectCast(dtrow, EmployeesDataSet.EmployeeRow).EmployeeID = dgvEmployees.Rows(rowIndex).Cells("EmployeeID").Value Then
Dim currentColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
For i As Integer = 0 To dsChanged.Tables(tablename).Columns.Count - 1
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.EmployeeRow).EmployeeID)
' This works
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
End If
Next
End If
End Sub
and i am only changing the backcolor of the cell that was changed not the entire row....but depends how you would use that information anyways
EDIT:
with
Console.WriteLine(EmployeesDataSet.Employee(rowIndex)(columnIndex, DataRowVersion.Original).ToString())
Console.WriteLine(EmployeesDataSet.Employee(rowIndex)(columnIndex, DataRowVersion.Current).ToString())
you can see Current and Original Values
123456

Copy data from C1FlexGrid to C1FlexGrid

I'm using a C1FlexGrid, which version I'm not entirely sure. I am trying to copy rows that are selected in FlexGridA to FlexGridB, and so far I'm unable to locate anything online to help, and all of the functionality that I've tried to use so far (such as add) does not work.
How can I accomplish this?
I HAVE to use C1FlexGrids, so if the answer is for a regular MSFlexGrid it won't work. I've already tried using some solutions for those and they don't work either.
EDIT:
I now have information copying between tables, but it's copying the entirety of what the table has after it's filtered, not just the selected rows.
There are two flexgrids. On form1 is fgResults, on form2 is fgDelete. I want to copy the selected rows from fgResults to fgDelete so that a user can see what they've selected to delete from the database before just blindly clicking and deleting something they don't want to.
Here is what I have to copy the data:
AddFilterRow(MultiDelete.fgDelete)
Dim MS As System.IO.MemoryStream = New System.IO.MemoryStream
fgResults.WriteXml(MS)
MS.Position = 0
MultiDelete.fgDelete.ReadXml(MS)
The issue is, again, it's adding EVERYTHING that was filtered, not just the selected rows.
So after several hours of digging, I found a workaround as there doesn't appear to be a direct way to copy one row from a C1FlexGrid to another.
Dim DT As New DataTable
For c = fgResults.Cols.Fixed To fgResults.Cols.Count - 1
DT.Columns.Add(fgResults.Cols(c).Name, fgResults.Cols(c).DataType)
Next
For r = fgResults.Rows.Fixed To fgResults.Rows.Count - 1
If fgResults.Rows(r).Selected Then
Dim row As DataRow = DT.NewRow()
For c = fgResults.Cols.Fixed To fgResults.Cols.Count - 1
If fgResults(r, c) Is Nothing Then
If fgResults.Cols(c).DataType.FullName = "System.DateTime" Then
row.Item(c - fgResults.Cols.Fixed) = Date.MinValue
ElseIf fgResults.Cols(c).DataType.FullName = "System.Double" Then
row.Item(c - fgResults.Cols.Fixed) = 0
Else
row.Item(c - fgResults.Cols.Fixed) = ""
End If
Else
row.Item(c - fgResults.Cols.Fixed) = fgResults(r, c)
End If
Next
DT.Rows.Add(row)
End If
Next
What I'm doing here is creating a new datatable, adding all rows to it that are selected, and then I fill the second grid with the created datatable. If anyone has a more direct way of doing this I am all ears, but this works for now for what I'm trying to accomplish.
i have the code to copy c1 flex grid cells to excel format
Dim fCol as integer
Dim fRow as integer
Private Sub Flex_EnterCell(ByVal sender As Object, ByVal e As System.EventArgs) Handles Flex.EnterCell
fRow = Flex.RowSel
fCol = Flex.ColSel
End Sub
Private Sub Copy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Copy.Click
Dim lRow As Integer, nRow As Integer
Dim lCol As Integer, nCol As Integer
Dim nText As String
lRow = Flex.RowSel
lCol = Flex.ColSel
For nRow = fRow To lRow
For nCol = fCol To lCol
nText = nText & IIf(IsDBNull(Flex.Item(nRow, nCol)), Convert.ToChar(Keys.Tab), Flex.Item(nRow, nCol)) & Convert.ToChar(Keys.Tab)
Next
nText = nText & vbCrLf
Next
Clipboard.SetText(nText)
End Sub

Binary Search or Insertion Sort with list view [Visual Basic .net]

Recently when creating a program for my client as part of my computing project in visual basic .net I've came across a problem, which looks like following; In order to receive additional marks for my program I must take an advantage of either Binary Search or Insertion Sort subroutine declared recursively, so far the only place I can use it on is my View form which displays all reports generated by program but the problem with this is since I'm using MS Access to store my data all of the data is downloaded and placed in listview in load part of form. So the only way I can use it is by running it on listview which is a major problem for me due to the fact that I'm not very experienced in vb.
For binary search I have tried downloading all of the items in specified by user column into an array but that's the bit I was struggling on the most because I'm unable to download all items from only one column into an array. Also instead of searching every single column user specifies in my form in which column item is located (For example "19/02/2013" In Column "Date"), In my opinion if I manage to download every single entry in specified column into an array it should allow me to run binary search later on therefore completing the algorithm. Here's what I've got so far.
Sub BinarySearch(ByVal Key As String, ByVal lowindex As String, ByVal highindex As String, ByVal temp() As String)
Dim midpoint As Integer
If lowindex > highindex Then
MsgBox("Search Failed")
Else
midpoint = (highindex + lowindex) / 2
If temp(midpoint) = Key Then
MsgBox("found at location " & midpoint)
ElseIf Key < temp(midpoint) Then
Call BinarySearch(Key, lowindex, midpoint, temp)
ElseIf Key > temp(midpoint) Then
Call BinarySearch(Key, midpoint, highindex, temp)
End If
End If
End Sub
Private Sub btnSearch_Click(sender As System.Object, e As System.EventArgs) Handles btnSearch.Click
Dim Key As String = txtSearch.Text
Dim TargetColumn As String = Me.lstOutput.Columns(cmbColumns.Text).Index
Dim lowindex As Integer = 0
Dim highindex As Integer = lstOutput.Items.Count - 1
'Somehow all of the items in Target column must be placed in temp array
Dim temp(Me.lstOutput.Items.Count - 1) As String
' BinarySearch(Key, lowindex, highindex, temp)
End Sub
For Insertion sort i don't even have a clue how to start, and the thing is that I have to use my own subroutine instead of calling system libraries which will do it for me.
Code which I have to use looks like following:
Private Sub InsertionSort()
Dim First As Integer = 1
Dim Last As Integer = Me.lstOutput.
Dim CurrentPtr, CurrentValue, Ptr As Integer
For CurrentPtr = First + 1 To Last
CurrentValue = A(CurrentPtr)
Ptr = CurrentPtr - 1
While A(Ptr) > CurrentValue And Ptr > 0
A(Ptr + 1) = A(Ptr)
Ptr -= 1
End While
A(Ptr + 1) = CurrentValue
Next
Timer1.Enabled = False
lblTime.Text = tick.ToString
End Sub
Any ideas on how to implement this code will be very appreciated, and please keep in my mind that I'm not very experienced in this language
Perhaps this might give you a place to begin. If you already have a ListView with "stuff" in it you could add a button to the form with the following code to copy the Text property for each item into an array:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myArray(Me.ListView1.Items.Count - 1) As String
Dim i As Integer
' load array
For i = 0 To Me.ListView1.Items.Count - 1
myArray(i) = Me.ListView1.Items(i).Text
Next
' show the results
Dim s As String = ""
For i = 0 To UBound(myArray)
s &= String.Format("myArray({0}): {1}", i, myArray(i)) & vbCrLf
Next
MsgBox(s, MsgBoxStyle.Information, "myArray Contents")
' now go ahead and manipulate the array as needed
' ...
End Sub

populate datagridview according to selected row in another datagridview

I have two datagrid gridproperty and gridpropertyselection. There is one table which contains data. i have to papulate data in datagridviw named gridpropertyselection accoring to selected row in gridProperty datagrid.
I want to which event will be for for this. i trid the following code . but getting error in Dim index As Integer = gridProperty.CurrentRow.Index this line
Private Sub gridProperty_SelectionChanged(ByVal Sender As Object, ByVal e As System.Windows.Forms.DataGridViewRowStateChangedEventArgs) Handles gridProperty.RowStateChanged
Dim dtPropertySelection As DataTable = m_ds.Tables(0)
Dim i As Integer
Dim count As Integer = gridPropertySelection.Rows.Count
' If (gridProperty.CurrentRow.IsNewRow IsNot Nothing) Then
Dim index As Integer = gridProperty.CurrentRow.Index
Dim PropertyID As Integer = gridProperty.Rows(index).Cells("PropertyID").Value
While i < dtPropertySelection.Rows.Count
If PropertyID = dtPropertySelection.Rows(i).Item("PropertyID") Then
gridPropertySelection.Rows.Add()
gridPropertySelection.Rows(count).Cells("colSelectionDescription").Value() = dtPropertySelection.Rows(i).Item("SelectionDescription")
gridPropertySelection.Rows(count).Cells("colAssociatedText").Value() = dtPropertySelection.Rows(i).Item("AssociatedText")
count = count + 1
End If
i = i + 1
End While
You can use the CellClick event of the datagridview.
Also, try to use
Dim index As Integer = gridProperty.CurrentCell.RowIndex()