2016-11-11 35 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