在嵌套的For循环中获取DataGridView单元格值 [英] Get DataGridView cell value in nested For Loops

查看:228
本文介绍了在嵌套的For循环中获取DataGridView单元格值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 DataGridView 上显示了一些数据,在我的 btnSave_Click 事件中,我打电话在将数据保存到数据库之前,需要先验证该网格中的数据的子例程。

I've got some data displayed on a DataGridView, and in my btnSave_Clickevent, I'm calling a subroutine to validate the data in the grid before saving it into my database.

我这样做的方法是对每一行及其内部使用一个循环对每一列使用另一个for循环。

The way I'm doing it is by using a loop for each row and inside that loop using another for loop, for each column.

然后我需要比较要验证的单元格值中的每个字符(行博士,单元格dc)。但是,我无法找出使用行/列坐标获取单元格中值的方法。

I need to then compare each char in the cell value that it's validating (row dr, cell dc). However, I cannot work out the way to use the row/column co-ordinates to get the value in the cell.

很难解释我的意思,但是在这段代码中,我在前两行中设置了 For循环,然后在第三行中,注意了 If IsDBNull(dc.TextInCell) -TextInCell是我需要替换的。

It's a little hard to explain what I mean, but in this code I have the For Loops set up on the first 2 lines, then on the third line, notice If IsDBNull(dc.TextInCell) - TextInCell is what I need to replace.

行内;博士和专栏; dc,然后需要验证存储在该单元格中的值...

In Row; dr and Column; dc, I need to then validate the value stored in that cell...

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

如何从此处获取单元格值以通过验证将其发送?

How do I get the cell value into a variable from here to send it through the validation?

推荐答案

(几乎)总是比遍历控件要快得多。您的代码中至少还有一个效率低的地方:

It will (almost) always be faster to iterate the rows in the datatable than to root thru the control. There is also at least one inefficiency in your code:

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

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

You dont need to find the target column for each row - it will be at the same index for each row.

我不知道它们的预期模式是什么,但是如果存在已定义的模式,例如 N-LLL-AAA-NLN(例如: 9-WDM-6K6-6ZC ),则可能需要查看 <一个href = https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx rel = nofollow noreferrer> RegEx 进行全面的模式测试。例如,您的代码基本上只是测试字符串中有限的一组特殊字符 anywhere ;如果有应该不在任何之前)

I dont know what the expected pattern is for these, but if there is a defined pattern like "N-LLL-AAA-NLN" (e.g: 9-WDM-6K6-6ZC) you might want to look into RegEx for comprehensive pattern testing. For instance your code is basically just testing for a limited set of special characters anywhere in the string; if there is a ( shouldn't it be before any )?

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

You will surely need to fiddle with the actual validation code, but this is many times faster:

'... 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 的行。 code>是错误的。更重要的是,它速度很快: 125毫秒可处理75,000行;通过DGV进行挖掘并一遍又一遍地找到同一列需要花费7-8秒钟的时间。

Not shown is 2-3 lines in the RowPrePaint event to color the rows where IsValid is false. More importantly, it is fast: 125 milliseconds to process 75,000 rows; digging thru the DGV and finding the same column over and over takes 7-8 secs.

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

Even without RegEx, you can test for special characters at specific locations (assuming a fixed pattern). For instance, to test "A-78*X(2012)":

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

您也可以将字符串除以这些字符,以测试<如果您要执行该级别的测试,则code> parts(3)是介于2010年至2015年之间的值。您所做的越多,RegEX就越有用。

You could also split the string by those characters in order to test that parts(3) is a value between 2010 and 2015 or whatever, if you wanted to perform that level of testing. The more of that you do, the more useful RegEX would be.

这篇关于在嵌套的For循环中获取DataGridView单元格值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆