繁体   English   中英

在嵌套的For循环中获取DataGridView单元格值

[英]Get DataGridView cell value in nested For Loops

我在DataGridView上显示了一些数据,在我的btnSave_Click事件中,我调用了一个子例程来验证网格中的数据,然后将其保存到我的数据库中。

我这样做的方法是为每一行使用一个循环,在每个行中使用另一个for循环。

然后我需要比较它正在验证的单元格值中的每个字符(行dr,单元直流)。 但是,我无法解决使用行/列坐标来获取单元格中的值的方法。

这有点难以解释我的意思,但是在这段代码中,我在前2行设置For Loops ,然后在第3行,注意If IsDBNull(dc.TextInCell) - TextInCell是我需要替换的。

在排队; 博士和专栏; dc,我需要验证存储在该单元格中的值...

For Each dr As DataGridViewRow In dgvImport.Rows
   For Each dc As DataGridViewColumn In dgvImport.Columns
     If dc.HeaderText = "Product Code" Then
       If IsDBNull(dc.TextInCell) = True Or dc.TextInCell = Nothing Or dc.TextInCell = "" Then
          Me.Cursor = Cursors.Default
          MsgBox("Import failed. One or more required fields were not entered", MsgBoxStyle.OkOnly, "Error")
          Exit Sub
        End If
        For Each c As Char In dc.TextInCell
         If Not Char.IsLetterOrDigit(c) Then
          If Not Char.IsWhiteSpace(c) Then
           If c <> "&" AndAlso c <> "-" AndAlso c <> "(" AndAlso c <> ")" Then
             Me.Cursor = Cursors.Default
             MsgBox("Import failed. One or more cells contains an invalid character", MsgBoxStyle.OkOnly, "Error")
             Exit Sub
           End If
          End If
         End If
Next

如何从此处将单元格值转换为变量以通过验证发送?

它(几乎)总是更快地迭代数据表中的行而不是通过控件的根。 您的代码中至少还有一个效率低下:

For Each dr As DataGridViewRow In dgvImport.Rows
    For Each dc As DataGridViewColumn In dgvImport.Columns
        If dc.HeaderText = "Product Code" Then

您不需要为每一行找到目标列 - 它将在每行的相同索引处。

我不知道这些预期的模式是什么,但如果有一个定义的模式,如“N-LLL-AAA-NLN”(例如: 9-WDM-6K6-6ZC ),您可能需要查看RegEx以进行全面的模式测试。 例如,您的代码基本上只是在字符串中的任何位置测试一组有限的特殊字符; 如果有(不应该在任何之前)

你肯定需要摆弄实际的验证代码,但这要快很多倍:

'... code to fill the DT
' add a column to track if the row is valid
dtSample.Columns.Add(New DataColumn("IsValid", GetType(Boolean)))

Dim specialChars = "&-()"
Dim txt As String = ""
Dim bValid As Boolean
Dim prodIndex As Int32

' index of the target column using the column name
prodIndex = dtSample.Columns.IndexOf("ProductCode")  

For Each dr As DataRow In dtProduct.Rows
    ' get the text
    txt = dr.Field(Of String)(prodIndex)

    ' first check for nothing from DBNull
    bValid = String.IsNullOrEmpty(txt) = False
    ' if there is text data, check the content
    If bValid Then
        ' each char must be letter, digit or authorized special char
        For n As Int32 = 0 To txt.Length - 1
            If Char.IsLetterOrDigit(txt(n)) = False AndAlso
                        specialChars.Contains(txt(n)) = False Then
                bValid = False
                Exit For
            End If
        Next
    End If
    ' unabiguously set the column for each row
    dr("IsValid") = bValid
Next

dgv1.DataSource = dtSample
' hide our scratch column
dgv1.Columns("IsValid").Visible = False

结果:

在此输入图像描述

未显示RowPrePaint事件中的2-3行,以对IsValid为false的行着色。 更重要的是,它很快:处理75,000行125毫秒 ; 通过DGV挖掘并反复找到相同的列需要7-8秒。

即使没有RegEx,您也可以测试特定位置的特殊字符(假设固定模式)。 例如,要测试"A-78*X(2012)"

bValid = pcode(1) = "-"c AndAlso
         pcode(4) = "*"c AndAlso
         pcode(6) = "("c AndAlso
         pcode(11) = ")"c

您还可以按字符分割字符串,以便测试parts(3)是2010年和2015年之间的值或其他任何值,如果您想要执行该级别的测试。 你做的越多,RegEX就会越有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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