[英]Error in using 'For Each' loop and 'If' statement in excel vba
Excel VBA - Error in using 'For Each' loop and 'If' statement. Excel VBA-使用“ For Each”循环和“ If”语句时出错。
I have an excel workbook; 我有一本Excel工作簿; which has two sheets: 有两张纸:
The first sheet is: 'Jurisdictions' Which has three columns: 第一页是“司法管辖区”,其中包含三列:
Country (Column B), State (Column C) and City (Column D) 国家(B栏),州(C栏)和城市(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; 我还有另一张纸:Sheet1;
Here also I have same three columns; 这里我也有相同的三列; (and 20 some other columns) (以及其他20列)
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) (Sheet1中仅列出了很少的“管辖区”;这些管辖区可以按任何顺序排列,并且可以适用于任何国家/地区)
The validation Rules are: 验证规则是:
1) For Country 1)国家
2) State 2)状态
3) City 3)城市
I have the following code which validates Countries, States and Cities correctly. 我有以下代码可以正确验证国家,州和城市。 (linguistically - spelling.) (从语言上讲-拼写。)
ie 即
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 现在我还有其他要求
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... 以及如何提高代码的性能...
Looking at your code, it seems you are making this really really complicated, where it does not really have to be. 查看您的代码,看来您正在使它真的变得非常复杂,而实际上并不一定要这样做。
If I gather this correctly, users will be entering data in your excelworkbook and you want to make sure they do this correctly, following some rules. 如果我正确收集了这些信息,则用户将在excelworkbook中输入数据,并且您要确保他们遵循某些规则正确地执行了操作。 If they break the rules you will color the cell red. 如果他们违反了规则,您将单元格涂成红色。
The easier and faster way to do this is use the conditional formatting built in to excel. 更简单,更快捷的方法是使用Excel内置的条件格式。 This will also allow you to split your code, and only check data that has actually changed: so no need to loop through all the cells. 这也将允许您拆分代码,并且仅检查实际已更改的数据:因此无需遍历所有单元格。
Quick example: 快速示例:
To add this rule you select the first cell of column C, and you choose "Conditional Formatting" from the Home tab in Excel;s ribbon. 要添加此规则,请选择C列的第一个单元格,然后从Excel功能区的“主页”选项卡中选择“条件格式”。 Then you create a new rule, and choose to use a formula to determine which cells to format. 然后,您创建一个新规则,并选择使用公式来确定要格式化的单元格。 The formula you need is "=NOT(ISERROR(FIND(";";B1)))" Then you set the format to red Fill and save the rule. 您需要的公式是“ = NOT(ISERROR(FIND(“;”; B1)))”然后将格式设置为红色填充并保存规则。
This rule will now work for the first row, in order to make it work for the entire column, you can go to manage rules and adjust the "applies to" field to $C:$C or you can copy the formatting to the cells you want to use. 现在,此规则将适用于第一行,为了使其适用于整个列,您可以去管理规则并将“适用于”字段调整为$ C:$ C,也可以将格式复制到单元格中您要使用。
You can create a Conditional formatting rule for every rule you have on your workbook. 您可以为工作簿上的每个规则创建条件格式设置规则。 You can also code functions for specific rules that you can not express easily in Excel's native funtions. 您还可以为无法在Excel的本机功能中轻松表达的特定规则编写函数代码。
This will make your checks simple and easier to maintain, but it will also make your user feedback instantanious: as soon as they enter a value, the rules are applied. 这将使您的检查变得简单且易于维护,但也将使您的用户反馈迅速:一旦输入值,规则就会被应用。
First, let me state that the approach in my previous answer can easily be applied to a workbook containing data, and is the best way forward. 首先,让我指出,我先前的答案中的方法可以轻松地应用于包含数据的工作簿,并且是最好的方法。
But as you ask for input on your code, maybe you should look at the second part of your else. 但是,当您要求输入代码时,也许您应该看一下其他代码的第二部分。 If State has multiple states, and the state can be found on the jurisdictions tab, your code will go to the following else block: 如果州有多个州,并且可以在“管辖区”选项卡上找到州,则您的代码将转到以下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
This block does nothing with the "All" value. 该块对“ All”值不执行任何操作。
Also, this line confuses me (more than once): 另外,这一行使我感到困惑(不止一次):
c.Interior.Color = c.Interior.Color
Other tips you might enjoy: 您可能会喜欢的其他技巧:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.