我遇到一个宏的一小部分问题。本质上,它应该做的是检查是否在列中找到值,如果它不是,那么它将继续通过其余代码:
Dim p As Long
Dim j As Long
Dim LastRow2 As Long
Dim LastRow3 As Long
Dim FindRow As Range
Dim a As Worksheet
Dim b As Worksheet
Dim c As Worksheet
Dim d As Worksheet
Set a = Workbooks("Item ID Comparison").Worksheets(1)
Set b = Workbooks("Item ID Comparison").Worksheets(2)
Set c = Workbooks("Item ID Comparison").Worksheets(3)
Set d = Workbooks("Prueba").Worksheets(1)
LastRow3 = d.Cells(Rows.Count, "F").End(xlUp).Row
For p = 2 to LastRow3
If b.Columns(6).Find(d.Cells(p, 6), lookat:=xlWhole) Is Nothing Then
Set FindRow = d.Columns(6).Find(a.Cells(p, 7))
j = FindRow.Row
If Not a.Columns(7).Find(d.Cells(p, 6), lookat:=xlWhole) Is Nothing Then
LastRow2 = c.Cells(Rows.Count, "A").End(xlUp).Row
c.Range("A" & LastRow2 + 1).Value = d.Cells(j, "A").Value
c.Range("B" & LastRow2 + 1).Value = d.Cells(j, "B").Value
c.Range("C" & LastRow2 + 1).Value = d.Cells(j, "C").Value
c.Range("D" & LastRow2 + 1).Value = d.Cells(j, "D").Value
c.Range("E" & LastRow2 + 1).Value = d.Cells(j, "E").Value
c.Range("F" & LastRow2 + 1).Value = d.Cells(j, "F").Value
c.Range("G" & LastRow2 + 1).Value = d.Cells(j, "G").Value
c.Range("H" & LastRow2 + 1).Value = d.Cells(j, "H").Value
c.Range("I" & LastRow2 + 1).Value = d.Cells(j, "I").Value
End If
End If
Next p
问题是excel似乎由于某种原因忽略了IF语句(实际上是在跟随第二个IF语句。我最终在b.columns(6)中找到数据集中的值。
非常感谢任何帮助。
答案 0 :(得分:1)
我认为这可能是您问题的根源:
For p = 2 to LastRow3
' Note that we are looking in Column(6) for a value we are finding in
' Cell(p, 6) which means that Column(6) will always contain the value
' (since we just took the value from column 6).
If b.Columns(6).Find(d.Cells(p, 6), lookat:=xlWhole) Is Nothing Then
Set FindRow = d.Columns(6).Find(a.Cells(p, 7))
j = FindRow.Row
If Not a.Columns(7).Find(d.Cells(p, 6), lookat:=xlWhole) Is Nothing Then
End If
End If
Next p
从本质上讲,您在Find
上使用的Columns(6)
值为Cells(p, 6)
。由于您要在同一列中查找从中获取值的值,因此总是为True
,但非常罕见的实例除外在将值传递给Find
并实际查找它(非常不太可能的情况)之间删除该值。
答案 1 :(得分:0)
忽略我的其他答案。我错过了你用两种不同的工作表来鉴定你的两个范围。让我们再试一次,这次虽然我们将使用我们的调试工具来看看我们是否能弄清楚发生了什么。
首先,我将提供一些经过编辑的代码,然后我们可以浏览它,看看我所做的更改是什么,以及查看调试如何帮助弄清楚发生了什么:
Sub Foo()
' Descriptive names make your variables easy to follow.
' It is also best to declare your variables AS CLOSE to their first use as possible.
' Since below this point we start using Prueba, and then we get into the loop, this is the ideal location.
With Application.Workbooks("Item ID Comparison")
Dim FirstComparison As Worksheet
Set FirstComparison = .Worksheets(1)
Dim SecondComparison As Worksheet
Set SecondComparison = .Worksheets(2)
Dim ThirdComparison As Worksheet
Set ThirdComparison = .Worksheets(3)
End With
Dim Prueba As Worksheet
Set Prueba = Application.Workbooks("Prueba").Worksheets(1)
' Note here that, previously, 'Rows' was not properly qualified to 'Prueba' and thus actually refers to 'ActiveSheet.Rows.Count'
'LastRow3 = d.Cells(Rows.Count, "F").End(xlUp).Row
Dim LastPruebaRow As Long
Prueba.Cells(Prueba.Rows.Count, "F").End(xlUp).Row
' By convention, we start with i and j as control variables
Dim i As Long
For i = 2 To LastPruebaRow
Dim SearchResult As Range
' Note here as well that I specifically call on the value of the cell, not the cell itself.
' While the default member of a 'Cell' is 'Value' it is far better to be explicit than to be implicit.
Set SearchResult = SecondComparison.Columns(6).Find(Prueba.Cells(i, 6).Value, lookat:=xlWhole)
' By separating out the concerns, you can look at the result of the find if it is successful, or use the immediate window
' to test different values of 'Find' until 'Not SearchResult Is Nothing'
If SearchResult Is Nothing Then
Dim FindRow As Range
' Again, specifically call on the 'Value' member
Set FindRow = Prueba.Columns(6).Find(FirstComparison.Cells(i, 7).Value)
Dim ResultRow As Long
ResultRow = FindRow.Row
' And again, get 'Value' from the cell.
If Not FirstComparison.Columns(7).Find(Prueba.Cells(i, 6).Value, lookat:=xlWhole) Is Nothing Then
' Note again that the row range is unqualified here, and actually is referring to 'ActiveSheet.Rows.Count'
' c.Cells(Rows.Count, "A").End(xlUp).Row
With ThirdComparison
' Since you are only ever using the index of the row + 1, just merge the two.
Dim LastComparisonRow As Long
LastComparisonRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
.Range("A" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "A").Value
.Range("B" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "B").Value
.Range("C" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "C").Value
.Range("D" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "D").Value
.Range("E" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "E").Value
.Range("F" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "F").Value
.Range("G" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "G").Value
.Range("H" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "H").Value
.Range("I" & LastComparisonRow).Value = Prueba.Cells(ResultRow, "I").Value
End With
End If
End If
Next i
End Sub
我认为值得指出的第一件事是,当所有内容都具有描述性名称时,更容易阅读您的代码正在做什么(至少对其他人而言)。我不需要花很长时间才能做到这一点,或者提出有意义的名称,但它使得遵循代码流更加容易。
同样,所有变量声明现在都在尽可能接近第一次使用时发生。我不需要查看顶部的Dim
块,知道LastPruebaRow
很长,它就在那里(并且更容易知道LastPruebaRow
超过LastRow3
})。
其次,当为for循环使用数值变量时,约定是以i
开头。因此:
For i = 1 to 10
For j = 2 to 20
For k = 3 to 30
Next
Next
Next
所以,等等,尽管如果你发现自己过去j
(通常是i
),你可能需要重构代码。
调整名称和声明后,事情就开始出现了。例如:
LastRow3 = d.Cells(Rows.Count, "F").End(xlUp).Row
实际上并没有返回Prueba
工作表的最后一行。相反,它正在返回:
ThirdComparisonSheet.Cells(ActiveSheet.Rows.Count, "F").End(xlUp).Row
您还有一些与其他代码不符的代码:
Set FindRow = Prueba.Columns(6).Find(FirstComparison.Cells(i, 7).Value)
注意其他人有lookat:=xlWhole
而这个没有?这可能是设计上的,所以我离开了它,但它突然出现在我身上。
我发现你的第一个条件是Nothing
:
' Note here as well that I specifically call on the value of the cell, not the cell itself.
' While the default member of a 'Cell' is 'Value' it is far better to be explicit than to be implicit.
Dim SearchValue as Variant
SearchValue = Prueba.Cells(i, 6).Value
Debug.Print "i :", i, "SearchValue :", SearchValue
Dim SearchResult As Range
Set SearchResult = SecondComparison.Columns(6).Find(SearchValue, lookat:=xlWhole)
If SearchResult Is Nothing Then
最后,正如您在上面的示例中所看到的,循环将在每次迭代时打印出i
和SearchValue
(请谨慎使用,我强烈建议使用断点,尤其是大型断点工作表)。
在所有这些中,我们应该更容易找到问题(如果它还没有浮出水面)。