如何在多列 DataGridView 中使用 cellendedit 和 vb.net 中的 multi oledb 命令

how to use cellendedit in multi column datagridview with multi oledb command in vb.net

提问人:siwa86 提问时间:11/7/2023 最后编辑:siwa86 更新时间:11/9/2023 访问量:71

问:

我正在尝试在多列datagridview中使用cellendedit和multi oledb命令 vb.net

我尝试了下面的代码,它不会在 datagridview 中产生任何内容,如果我只使用一个带有一个 oledb 命令的 datagridview 列,那么它就会出现在 datagridview 中。

我有下面的代码,但这仍然是错误的。

请指导我

谢谢

Public Class Form1
    Dim dr1 As OleDbDataReader
    Dim dr2 As OleDbDataReader
    Dim dr3 As OleDbDataReader
    Public Function GetConnectionString2() As String
        Dim strCon As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TRIAL.accdb;Persist Security Info=False;"
        Return strCon
    End Function
    Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
        If DataGridView1.Columns(e.ColumnIndex) Is DataGridView1.Columns("CODEPRODUCT") AndAlso DataGridView1.Columns(e.ColumnIndex) Is DataGridView1.Columns("SIZEPRODUCT") Then
            Using _conn As New OleDbConnection(GetConnectionString2)
                Using cmd1 As New OleDbCommand("select * from [PRODUCT] where CODEPRODUCT='" & DataGridView1.Rows(e.RowIndex).Cells("CODEPRODUCT").Value.ToString() & "'", _conn)
                    Using cmd2 As New OleDbCommand("select * from [SIZEPRODUCT] where SIZEPRODUCT='" & DataGridView1.Rows(e.RowIndex).Cells("SIZEPRODUCT").Value.ToString() & "'", _conn)
                        Using cmd3 As New OleDbCommand("select * from [COLORCODE] where COLORCODE='" & DataGridView1.Rows(e.RowIndex).Cells("COLORCODE").Value.ToString() & "'", _conn)
                            Try
                                _conn.Open()
                                dr1 = cmd1.ExecuteReader
                                dr2 = cmd2.ExecuteReader
                                dr3 = cmd2.ExecuteReader
                                dr1.Read()
                                dr2.Read()
                                dr3.Read()
                                If dr1.HasRows AndAlso dr2.HasRows AndAlso dr3.HasRows Then
                                    DataGridView1.Rows(e.RowIndex).Cells("DESCRIPTION").Value = dr1.Item("DESCRIPTION")
                                    DataGridView1.Rows(e.RowIndex).Cells("CATEGORY").Value = dr2.Item("CATEGORY")
                                    DataGridView1.Rows(e.RowIndex).Cells("COLORNAME").Value = dr3.Item("COLORNAME")
                                Else
                                    MsgBox("Not found")
                                End If
                            Catch ex As Exception
                                MessageBox.Show(ex.Message)
                            End Try
                        End Using
                    End Using
                End Using
            End Using
        End If
    End Sub
End Class

更新代码

Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
        Using _conn As New OleDbConnection(GetConnectionString2)
If DataGridView1.Columns(e.ColumnIndex) Is DataGridView1.Columns("CODEPRODUCT") OrElse DataGridView1.Columns(e.ColumnIndex) Is DataGridView1.Columns("SIZEPRODUCT") OrElse DataGridView1.Columns(e.ColumnIndex) Is DataGridView1.Columns("COLORCODE") Then
                Using cmd1 As New OleDbCommand("select * from [PRODUCT] where CODEPRODUCT='" & DataGridView1.Rows(e.RowIndex).Cells("CODEPRODUCT").Value.ToString() & "'", _conn)
                    'Using cmd2 As New OleDbCommand("select * from [SIZEPRODUCT] where SIZEPRODUCT='" & DataGridView1.Rows(e.RowIndex).Cells("SIZEPRODUCT").Value.ToString() & "'", _conn)
                    'Using cmd3 As New OleDbCommand("select * from [COLORCODE] where COLORCODE='" & cstr(DataGridView1.Rows(e.RowIndex).Cells("COLORCODE").Value).ToString() & "'", _conn)
                    Try
                        _conn.Open()
                        dr1 = cmd1.ExecuteReader
                        'dr2 = cmd2.ExecuteReader
                        'dr3 = cmd3.ExecuteReader
                        If dr1.Read OrElse dr2.Read OrElse dr3.Read Then
                            DataGridView1.Rows(e.RowIndex).Cells("DESCRIPTION").Value = dr1.Item("DESCRIPTION")
                            ''DataGridView1.Rows(e.RowIndex).Cells("CATEGORY").Value = dr2.Item("CATEGORY")
                            'DataGridView1.Rows(e.RowIndex).Cells("COLORNAME").Value = dr3.Item("COLORNAME")
                        Else
                            MsgBox("Not found")
                        End If
                    Catch ex As Exception
                        MessageBox.Show(ex.Message)
                    End Try
                End Using
                'End Using
                ''End Using
            End If
        End Using
    End Sub

screenshot DATAGRIDVIEW

vb.net datagridview oledb oledbcommand executereader

评论

0赞 jmcilhinney 11/7/2023
OT,你不需要嵌套所有这些块。您可以使用单个语句,只需在变量声明之间添加逗号即可。这将使您的代码更具可读性。仅当需要在嵌套块之间放置代码时,才需要嵌套块。UsingUsing
0赞 jmcilhinney 11/7/2023
你为什么在打电话后测试?两者兼而有之是没有意义的。 将返回相同的值,您需要调用它,因此只需在块中使用即可。此外,您应该关闭所有数据读取器。理想情况下,你会用一个块来做到这一点。HasRowsReadReadHasRowsReadIfUsing
0赞 jmcilhinney 11/7/2023
当您只需要一列时,为什么要在查询中使用?不要检索您知道不需要的数据。如果您只需要一个值,则应调用 ,而不是 。SELECT *ExecuteScalarExecuteReader
0赞 jmcilhinney 11/7/2023
至于问题,你需要调试你的代码。您是开发人员,因此请使用您的开发工具。你不是用户,所以你不会像用户那样只是观看 UI。使用断点正确调试代码,您可能能够自己解决问题。如果没有,至少你可以告诉我们实际发生了什么,以及它与你的期望有何不同。
0赞 jmcilhinney 11/7/2023
最后,不要使用字符串连接将值插入到 SQL 代码中。了解如何使用参数并使代码更好、更安全。

答:

1赞 dr.null 11/8/2023 #1

如果这里的想法是仅在用户输入/选择三个表的所有必需和正确标识符时运行三个查询,那么您可以只执行一个查询而不是三个查询来从三个表中选择必填字段。

假设未绑定网格,鱼腥表和字段名称正确,参数值为 类型。你可以写如下:String

Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    Dim dgv = DirectCast(sender, DataGridView)
    Dim KeyCols = {"CodeProduct", "SizeProduct", "ColorCode"}
    Dim ValueCols = {"Description", "Category", "ColorName"}

    If e.RowIndex >= 0 AndAlso KeyCols.Any(Function(col) col = dgv.Columns(e.ColumnIndex).Name) Then
        Dim dict = dgv.Rows(e.RowIndex).Cells.OfType(Of DataGridViewTextBoxCell).
        Where(Function(cell) KeyCols.Any(Function(col) col = cell.OwningColumn.Name)).
        ToDictionary(Function(cell) cell.OwningColumn.Name, Function(cell) cell.Value)

        If dict.Values.Any(Function(v) v Is Nothing OrElse String.IsNullOrEmpty(v.ToString())) Then
            Return
        End If

        Dim sql =
        <sql>
            SELECT Product.Description, SizeProduct.Category, ColorCode.ColorName
            FROM Product, SizeProduct, ColorCode
            WHERE Product.CodeProduct = ?
            AND SizeProduct.SizeProduct = ?
            AND ColorCode.ColorCode = ?
        </sql>.Value

        Using con = New OleDbConnection("..."), cmd = New OleDbCommand(sql, con)
            cmd.Parameters.AddRange(
            dict.Select(Function(kvp) New OleDbParameter("?", OleDbType.VarWChar) With {
                .Value = kvp.Value
            }).ToArray())

            con.Open()

            Using rdr = cmd.ExecuteReader()
                If rdr.Read() Then
                    For Each col In ValueCols
                        dgv(col, e.RowIndex).Value = rdr(col)
                    Next
                Else
                    MessageBox.Show("one or more wrong identifiers.")
                End If
            End Using
        End Using
    End If
End Sub

请注意,当所有传递的 、 和 标识符都有效时,此查询将返回一条读记录。如前所述,另一种方法是在网格中更改相关 id/代码时为每个表运行单独的查询。CodeProductSizeProductColorCode

Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    If e.RowIndex < 0 OrElse e.RowIndex < 0 Then Return
    Dim dgv = DirectCast(sender, DataGridView)
    Dim row = dgv.Rows(e.RowIndex)
    Dim arrQueries() = {
        New With {
            .KeyCell = row.Cells("CodeProduct"),
            .ValueCell = row.Cells("Description"),
            .Table = "Product"},
        New With {
            .KeyCell = row.Cells("SizeProduct"),
            .ValueCell = row.Cells("Category"),
            .Table = "SizeProduct"},
        New With {
            .KeyCell = row.Cells("ColorCode"),
            .ValueCell = row.Cells("ColorName"),
            .Table = "ColorCode"}
    }

    If Not arrQueries.Any(
        Function(q) q.KeyCell.OwningColumn Is dgv.Columns(e.ColumnIndex)) Then
        Return
    End If

    Using con = New OleDbConnection("..."), cmd = con.CreateCommand()
        con.Open()
        For Each q In arrQueries
            If q.KeyCell.Value IsNot Nothing AndAlso
                q.KeyCell.Value IsNot DBNull.Value AndAlso
                Not String.IsNullOrEmpty(q.KeyCell.Value.ToString()) Then
                cmd.CommandText = String.Format(
                    "SELECT {0} FROM {1} WHERE {2} = ?",
                    q.ValueCell.OwningColumn.DataPropertyName,
                    q.Table,
                    q.KeyCell.OwningColumn.DataPropertyName)
                cmd.Parameters.Clear()
                cmd.Parameters.Add("?", OleDbType.VarWChar).Value = q.KeyCell.Value
                q.ValueCell.Value = cmd.ExecuteScalar()
            Else
                q.ValueCell.Value = Nothing
            End If
        Next
    End Using
End Sub

评论

1赞 siwa86 11/9/2023
谢谢你的回答,但我有一个错误,这个行代码和dgv(kvp.Key, e.RowIndex).Value = rdr(kvp.Key)An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Data.dll Additional information: CODEPRODUCT
0赞 dr.null 11/9/2023
@siwa86 对,bug修复。立即尝试并仔细检查名称。
0赞 siwa86 11/25/2023
感谢您的更新。对不起,我回复晚了,因为以前我的笔记本电脑损坏了。在标识符有效之前,它是否可以保留在 DataGridView 行中?
1赞 siwa86 11/26/2023
感谢您对第二个选项的回复,但我试过 ValueCell 没有出现,如果有问题,请指导您。
1赞 siwa86 11/27/2023
if q.valuecell is DBnull.value then q.keycell.value = nothing你的意思是这种方式意味着用户输入了错误的密钥。