[英]Error in using 'For Each' loop and 'If' statement in excel vba
Excel VBA-使用“ For Each”循環和“ If”語句時出錯。
我有一本Excel工作簿; 有兩張紙:
第一頁是“司法管轄區”,其中包含三列:
國家(B欄),州(C欄)和城市(D欄)
此工作表每個城市都有一個條目。
但是,由於每個城市都在單獨的行中列出,因此州和國家(城市所屬)的名稱可以在多行中重復。
例如:
Col B | Col C | Col D |
--------------------------------
U.S. | New York | Buffalo |
U.S. | New York | Manhattan |
(這是我的兩行)
我還有另一張紙:Sheet1;
這里我也有相同的三列; (以及其他20列)
我將使用“管轄權”表中的三列來驗證這三列。 (Sheet1中僅列出了很少的“管轄區”;這些管轄區可以按任何順序排列,並且可以適用於任何國家/地區)
驗證規則是:
1)國家
2)狀態
3)城市
我有以下代碼可以正確驗證國家,州和城市。 (從語言上講-拼寫。)
即
Col B | Col C | Col D |
-----------------------------------------
U.S. | New York | Buffalo |
U.S. | New York | Manhattan; Buffalo |
India | Karnataka| Bangalore |
此外,它還可以正確驗證層次結構。
Dim nLastRow As Long
Dim nLastRowSheet2 As Long
Dim rngFnder As Range
Dim strFndAddress As String
Dim stString As String
Dim stArray() As String
'Get the last row
'Dim lastRow As Integer
nLastRow = Sheets("Sheet1").Cells(Rows.Count, 2).End(xlUp).Row
nLastRowSheet2 = Sheets("Jurisdictions").Cells(Rows.Count, 2).End(xlUp).Row
Dim c As Range
Dim d As Range
Dim e As Variant
'Turn screen updating off to speed up macro code.
'User won't be able to see what the macro is doing, but it will run faster.
Application.ScreenUpdating = False
For Each c In Worksheets("Sheet1").Range("D2:D" & nLastRow)
stString = c
stArray() = Split(stString, ";")
For Each e In stArray()
e = Trim(e)
strFndAddress = ""
On Error Resume Next
Set rngFnder = Sheets("Jurisdictions").Range("D2:D" & nLastRowSheet2).Find(e)
If rngFnder Is Nothing And c <> "All" Then
c.Interior.Color = vbRed
Else
strFndAddress = rngFnder.Address
Do
If c.Offset(, -1) = rngFnder.Offset(, -1) And c.Offset(, -2) = rngFnder.Offset(, -2) Then
strFndAddress = ""
Exit Do
Else
Set rngFnder = Sheets("Jurisdictions").Range("D2:D" & nLastRowSheet2).FindNext(rngFnder)
End If
Loop While Not rngFnder Is Nothing And rngFnder.Address <> strFndAddress
End If
If rngFnder.Address = strFndAddress Then
c.Interior.Color = vbRed
End If
On Error GoTo 0
Set c = Nothing
strFndAddress = ""
Next
Next
現在我還有其他要求
為了實現上述要求,我添加了以下代碼
For Each c In Worksheets("Sheet1").Range("D2:D" & nLastRow)
If c.Offset(, -1) = "All" And c = "All" Then
c.Interior.Color = vbWhite
End If
Next
和...
For Each c In Worksheets("Sheet1").Range("D2:D" & nLastRow)
If c = "All" Then
stString = c.Offset(, -1)
stArray() = Split(stString, ";")
End If
For Each e In stArray()
e = Trim(e)
strFndAddress = ""
On Error Resume Next
Set rngFnder = Sheets("Jurisdictions").Range("C2:C" & nLastRowSheet2).Find(e)
If rngFnder Is Nothing And e <> "All" Then
'c.Interior.Color = c.Interior.Color (Do Nothing)
Else
strFndAddress = rngFnder.Address
Do
If c.Offset(, -2) = rngFnder.Offset(, -2) Then
strFndAddress = ""
c.Interior.Color = vbWhite
Exit Do
Else
Set rngFnder = Sheets("Jurisdictions").Range("C2:C" & nLastRowSheet2).FindNext(rngFnder)
End If
Loop While Not rngFnder Is Nothing And rngFnder.Address <> strFndAddress
End If
If rngFnder.Address = strFndAddress Then
'c.Interior.Color = c.Interior.Color (Do Nothing)
End If
On Error GoTo 0
Set c = Nothing
strFndAddress = ""
Next
Next
最后的代碼幾乎沒有錯誤。
如果“狀態”單元格具有單個狀態,而相鄰的“城市”單元格具有值“全部”:它將正確驗證它。
但; 如果“狀態”單元格具有以分號分隔的多個狀態; 並且相鄰的“城市”單元格的值為“全部”,則代碼無法正確驗證它。
誰能幫助我我錯了? 以及如何提高代碼的性能...
查看您的代碼,看來您正在使它真的變得非常復雜,而實際上並不一定要這樣做。
如果我正確收集了這些信息,則用戶將在excelworkbook中輸入數據,並且您要確保他們遵循某些規則正確地執行了操作。 如果他們違反了規則,您將單元格塗成紅色。
更簡單,更快捷的方法是使用Excel內置的條件格式。 這也將允許您拆分代碼,並且僅檢查實際已更改的數據:因此無需遍歷所有單元格。
快速示例:
要添加此規則,請選擇C列的第一個單元格,然后從Excel功能區的“主頁”選項卡中選擇“條件格式”。 然后,您創建一個新規則,並選擇使用公式來確定要格式化的單元格。 您需要的公式是“ = NOT(ISERROR(FIND(“;”; B1)))”然后將格式設置為紅色填充並保存規則。
現在,此規則將適用於第一行,為了使其適用於整個列,您可以去管理規則並將“適用於”字段調整為$ C:$ C,也可以將格式復制到單元格中您要使用。
您可以為工作簿上的每個規則創建條件格式設置規則。 您還可以為無法在Excel的本機功能中輕松表達的特定規則編寫函數代碼。
這將使您的檢查變得簡單且易於維護,但也將使您的用戶反饋迅速:一旦輸入值,規則就會被應用。
首先,讓我指出,我先前的答案中的方法可以輕松地應用於包含數據的工作簿,並且是最好的方法。
但是,當您要求輸入代碼時,也許您應該看一下其他代碼的第二部分。 如果州有多個州,並且可以在“管轄區”選項卡上找到州,則您的代碼將轉到以下else塊:
strFndAddress = rngFnder.Address
Do
If c.Offset(, -2) = rngFnder.Offset(, -2) Then
strFndAddress = ""
c.Interior.Color = vbWhite
Exit Do
Else
Set rngFnder = Sheets("Jurisdictions").Range("C2:C" & nLastRowSheet2).FindNext(rngFnder)
End If
Loop While Not rngFnder Is Nothing And rngFnder.Address <> strFndAddress
該塊對“ All”值不執行任何操作。
另外,這一行使我感到困惑(不止一次):
c.Interior.Color = c.Interior.Color
您可能會喜歡的其他技巧:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.