2016-11-11 32 views
1

我有一些数据显示在DataGridView和我的btnSave_Click事件中,我调用一个子例程来验证网格中的数据,然后将其保存到我的数据库中。获取DataGridView嵌套单元格的值For循环

我这样做的方式是对每一行使用一个循环,并在该循环内部使用另一个for循环,对于每一列。

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

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

In Row;博士和列; 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 

如何获取单元格的值到一个变量从这里通过审定发送?

+0

有些事件可以让你在你去的时候进行验证,这样你就可以告诉用户他们有错误*,而不是“在这个页面上有错误”。 CellValidating是其中之一,CellLeave也是一种可能性 – Plutonix

+0

@Plutonix不确定这是可能的。这是从Excel电子表格中选择的数据,并且'DataSource'是我在选择它后填充的'DataTable' – David

+0

在这种情况下,我肯定不会循环通过DGV,而是通过DataTable行。您可以添加一个列,指出哪些列通过,哪些列出错,并提供一些视觉提示 – Plutonix

回答

3

它将(几乎)迭代数据表中的行的速度总是快于根节点通过控制。还有一个在你的代码中的至少一个效率低下:

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 

结果:

enter image description here

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

即使没有正则表达式,您也可以测试特定位置的特殊字符(假设是固定模式)。例如,为了测试"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就越有用。

+0

我刚刚纠正了这个小小的逻辑。就这样,每当'bValid'为'False'时,就会将网格的第一行设置为false,即使它是第4行。否则就很好 – David