您好我正在编写一个宏来比较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列中。
答案 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
变量替换为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