简体   繁体   中英

selecting from a combo box with data from csv in vb.net

I have a .csv file that I load in a combo box inside a data grid view. My csv is like this:

prodname,prodcode,amt
prodname1,prodcode1,amt1
prodname2,prodcode2,amt2

prodname is what I am displaying in the combobox inside the datagridview.

What i want is when I select prodname1 , prodcode1 and amt1 will be displayed on the same row in the data grid view. I am just starting to fumble around in vb.net and will be grateful if someone help me.

This is what I have for now:

    Dim cmb As New DataGridViewComboBoxColumn()
    cmb.HeaderText = "Product Name"
    cmb.Name = "cmb"
    DataGridView2.Columns.Add(cmb) 'code for a combobox column in datagridview

    Dim filename As String
    Dim dt As New DataTable
    filename = "/file/path/here"
    Dim sr As New IO.StreamReader(filename)

    Dim newline() As String = sr.ReadLine.Split(","c)
    dt.Columns.AddRange({New DataColumn(newline(0)), _
                         New DataColumn(newline(1))})
    While (Not sr.EndOfStream)
        newline = sr.ReadLine.Split(",")
        Dim newrow As DataRow = dt.NewRow
        cmb.Items.Add(newline(0))
        newrow.ItemArray = {newline(1)}
        dt.Rows.Add(newrow)
    End While
    DataGridView2.DataSource = dt

UPDATE:

I updated my code as per Alex's answer but I still get an error.

    Dim cmb As New DataGridViewComboBoxColumn()
    cmb.HeaderText = "Product Name"
    cmb.Name = "cmb"
    DataGridView1.Columns.Add(cmb)

    AddHandler DataGridView1.CellValueChanged, AddressOf DataGridView1_OnCellValueChanged
    AddHandler DataGridView1.CurrentCellDirtyStateChanged, AddressOf DataGridView1_OnCurrentCellDirtyStateChanged

    Dim filename As String

    filename = "/path/to/file"
    Dim sr As New IO.StreamReader(filename)

    Dim newline() As String = sr.ReadLine.Split(","c)
    dt.Columns.AddRange({New DataColumn(newline(0)), _
    New DataColumn(newline(1))})

     While (Not sr.EndOfStream)
        newline = sr.ReadLine.Split(","c)
        Dim newrow As DataRow = dt.NewRow
        cmb.Items.Add(newline(0))
        'newrow.ItemArray = {newline(1)} 
        dt.Rows.Add(newrow)
        dicItems.Add(newline(0), newline.Skip(1))
    End While
    DataGridView1.DataSource = dt
End Sub

Private Sub DataGridView1_OnCellValueChanged(ByVal s As Object, ByVal e As DataGridViewCellEventArgs)
    If e.ColumnIndex = 0 Then
        Dim changedCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
        For i As Integer = 0 To dt.Columns.Count
            dt.Rows(e.RowIndex).Item(i) = dicItems(changedCell.Value.ToString)(i) **error here**
        Next
    End If
End Sub

Private Sub DataGridView1_OnCurrentCellDirtyStateChanged(ByVal s As Object, ByVal e As EventArgs)
    If DataGridView1.IsCurrentCellDirty Then
        DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
    End If
End Sub
  • he used semi-colon on his sample, but i am sticking to my comma. :)

The error says Cannot find column 2 or when I tweak something, the error becomes The given key was not present in the dictionary on the same line

这是我在Excel中完成的csv文件

You need two new Event Handlers:

AddHandler DataGridView1.CellValueChanged, AddressOf DataGridView1_OnCellValueChanged
AddHandler DataGridView1.CurrentCellDirtyStateChanged, AddressOf DataGridView1_OnCurrentCellDirtyStateChanged

The first is to recognize if the cell value of your combobox has changed. The latter is to fire the OnCellValueChanged when you click on a combobox item (default behavior is that the event is only fired after you leave the cell). Put that code in the Forms constructor or Load event handler.

Additionally you have to store which prodname has which details (eg prodname1 => prodcode1,amt1 ). In my example I did this with a Dictionary<Key: string => Values: IEnumerable<string> .

Class Form1
   Private dicItems As New Dictionary(Of String, IEnumerable(Of String))
   Private dt As New DataTable
   ...
   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
     While (Not sr.EndOfStream)
        newline = sr.ReadLine.Split(","c)
        Dim newrow As DataRow = dt.NewRow
        cmb.Items.Add(newline(0))
        dt.Rows.Add(newrow)
        'Fill Dicitonary here. Key: newLine(0), values: newLine(1,2,...n)
        dicItems.Add(newline(0), newline.Skip(1))
     End While
   End Sub

The code of the event handlers are pretty straight forward:

  Private sub DataGridView1_OnCurrentCellDirtyStateChanged(s As Object, e As EventArgs)
        If DataGridView1.IsCurrentCellDirty Then
             DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
        End If
     End sub

=> Fire the CellValueChangedEvent via Commiting the current combobox item change.

Private sub DataGridView1_OnCellValueChanged(s As Object, e As DataGridViewCellEventArgs)
    If e.ColumnIndex = 0 Then
        Dim changedCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex)
        For i As Integer = 0 To dt.Columns.Count 
            dt.Rows(e.RowIndex).Item(i) = dicItems(changedCell.Value.ToString)(i)
        Next        
    End If
End sub

=> Check if the combobox has changed ( ColumnIndex = 0 ) and get the changed cell.
Lookup in the dictionary to find the corresponding prodcode,amt with the given key ( prodname ).
Set the new value in the DataTable (you have to make dt a class field instead of a variable in your Load method).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM