当前位置:  开发笔记 > 编程语言 > 正文

VBA中的列比较错误

如何解决《VBA中的列比较错误》经验,为你挑选了2个好方法。

您好我正在编写一个宏来比较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列中.



1> BruceWayne..:

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

你需要时刻资格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"). 另外If x = y,根据@ ScottCraner的评论更新了语句.

另外我看到你有一些未声明的变量.我建议添加Option Explicit到开头(之前Sub Main())并声明所有变量.



2> Shai Rado..:

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

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

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

编辑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


当然,你可以完全摆脱`isMatch`,在当前的'isMatch = False`的位置放置`If Not isMatch Then`` ...``End If`块的内容.
推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有