excel

时间:2018-01-05 15:07:20

标签: excel vba excel-vba

我遇到一个宏的一小部分问题。本质上,它应该做的是检查是否在列中找到值,如果它不是,那么它将继续通过其余代码:

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)中找到数据集中的值。

非常感谢任何帮助。

2 个答案:

答案 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

最后,正如您在上面的示例中所看到的,循环将在每次迭代时打印出iSearchValue(请谨慎使用,我强烈建议使用断点,尤其是大型断点工作表)。

在所有这些中,我们应该更容易找到问题(如果它还没有浮出水面)。