Excel VBA - Error in using 'For Each' loop and 'If' statement.
I have an excel workbook; which has two sheets:
The first sheet is: 'Jurisdictions' Which has three columns:
Country (Column B), State (Column C) and City (Column D)
This sheet has single entry for each city.
But, as each city is listed on separate row, the names of state and country(To which cities belong) can get repeated on multiple rows.
For Ex:
Col B | Col C | Col D |
--------------------------------
U.S. | New York | Buffalo |
U.S. | New York | Manhattan |
(These are my two rows)
I have another sheet: Sheet1;
Here also I have same three columns; (and 20 some other columns)
These three columns I shall validate with three columns in 'Jurisdictions' sheet. (Only few 'Jurisdictions' are listed in Sheet1; and those can be in any order and can be for any country)
The validation Rules are:
1) For Country
- Country name should be a single value only.
- Should match with name under 'Country' column in Jurisdiction sheet.
- Cases should be neglected (Uppercase/Lowercase)
2) State
- Can have one or Multiple values separated only with semicolon (To separate those values with semicolon I have written a different code and it works fine)
- The entry in this cell even can be 'All'
- All the state names should match with states listed under 'state' column of Jurisdiction sheet. (If multiple entries are listed; those should be first separated based on delimeter - semicolon and then to be compared)
- Cases should be neglected (Uppercase/Lowercase); Extra spaces before and after state names should be trimmed.
3) City
- Can have one or Multiple values separated only with semicolon.
- The entry in this cell can be 'All' also.
- All the city names should match with cities listed under 'City' column of Jurisdiction sheet. (If multiple entries are listed; those should be first separated based on delimeter - semicolon and then to be compared)
- Cases should be neglected (Uppercase/Lowercase); Extra spaces before and after state names should be trimmed.
I have the following code which validates Countries, States and Cities correctly. (linguistically - spelling.)
i.e.
Col B | Col C | Col D |
-----------------------------------------
U.S. | New York | Buffalo |
U.S. | New York | Manhattan; Buffalo |
India | Karnataka| Bangalore |
Also it validates the hierarchy correctly.
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
Now I have other requirements
- There can be multiple states listed in 'state' cell separated only with semicolon.
- If multiple states are listed under state; then the adjacent cell for City should( mandatorily) have value "All" only. (As if multiple states are listed then the above code can't validate the hierarchy correctly)
- State cell may have value as "All" (i.e All states; no state listed separately)
- If state cell has value "All" then the adjacent city cell should ( mandatorily) have value "All" only.
- There can be cases where a single state value is listed under State, but still adjacent city cell can have value "All"
To implement the above requirements I added following code
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
and...
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
The last code is little erroneous.
If the 'State' cell has a single state and adjacent 'City' cell has value "All" :it validates it correctly.
But; If 'State' cell has multiple states separated with a semicolon; and adjacent 'City' cell has value "All" then code do not validate it correctly.
Can anyone help me where I am wrong? and also how I can increase the performance of code...