VBA中的列比较错误

时间:2017-01-19 18:04:16

标签: excel vba excel-vba

您好我正在编写一个宏来比较excel中不同工作表上的两列。 宏如下:

Sub Main()
Application.ScreenUpdating = False

    Dim stNow As Date
    stNow = Now

    Dim arr As Variant
    arr = Worksheets("Sheet2").Range("W3:W" & Range("W" & Rows.Count).End(xlUp).Row).Value

    Dim varr As Variant
    varr = Worksheets("Sheet3").Range("P3:P" & Range("P" & Rows.Count).End(xlUp).Row).Value

    Dim x, y, match As Boolean
    For Each x In arr
        match = False
        For Each y In varr
            If x = y Then match = True
        Next y
        If Not match Then
            Worksheets("Sheet1").Range("L" & Range("L" & Rows.Count).End(xlUp).Row + 1) = x
        End If
    Next

    Debug.Print DateDiff("s", stNow, Now)
Application.ScreenUpdating = True
End Sub

如果列在同一张纸上并且代码中没有纸张参考,则它可以完美地工作。但现在它只复制Sheet3列W中的第一个单元格,尽管此值已存在于Sheet3上的P列中。

2 个答案:

答案 0 :(得分:5)

正如您所注意到的,当没有工作表引用时,它可以正常工作。

您需要始终符合Range()Rows.Columns.的资格,否则它将使用ActiveSheet的任何内容。

以下内容适合您。

Sub Main()
Application.ScreenUpdating = False

Dim stNow   As Date
stNow = Now

Dim arr     As Variant
With Worksheets("Sheet2")
    arr = .Range("W3:W" & .Range("W" & .Rows.Count).End(xlUp).Row).Value
End With

Dim varr    As Variant
With Worksheets("Sheet3")
    varr = .Range("P3:P" & .Range("P" & .Rows.Count).End(xlUp).Row).Value
End With

Dim x, y, match As Boolean
For Each x In arr
    match = False
    For Each y In varr
        If x = y Then
            match = True
            Exit For
        End If
    Next y
    If Not match Then
        With Worksheets("Sheet1")
            .Range("L" & .Range("L" & .Rows.Count).End(xlUp).Row + 1) = x
        End With
    End If
Next

Debug.Print DateDiff("s", stNow, Now)
Application.ScreenUpdating = True
End Sub

注意:我添加了With语句以减少使用Worksheets("Sheetx").的重复性。另外,根据@ ScottCraner的评论更新了If x = y语句。

我也看到你有一些未声明的变量。我建议在{start Option Explicit之前添加Sub Main()并声明所有变量。

答案 1 :(得分:5)

按照@BruceWayne的回答,您可以替换代码的中间部分,而不是使用 2 x For循环扫描每个数组中的所有元素,您只能拥有1 For循环,另一个将使用Application.Match函数查找数组之间的匹配。

在比较大型数组时,这可以节省大量的代码运行时间。

注意:我已将match变量替换为isMatchmatch不是变量的最佳名称(因为有一个函数,同名)

修改1 :删除了isMatch变量,因为它不需要。

<强>子代码

Dim x
For Each x In arr
    If IsError(Application.Match(x, varr, 0)) Then '<-- no match between elements inside arrays
        With Worksheets("Sheet1")
            .Range("L" & .Range("L" & .Rows.Count).End(xlUp).Row + 1) = x
        End With
    Else '<-- there is a match between arrays
        ' do nothing , raise a "MsgBox"
    End If       
Next x