加快搜索和删除宏

时间:2012-01-04 05:03:26

标签: excel excel-vba vba

我有一个包含三列的列表。第一列包含名称,另外两列包含数字。宏取名字(A1),然后在列A中搜索另一个名称。

当它找到它时,它会删除整行。然后转到A2并执行相同的操作。它适用于大约500个条目,但使用3000个条目会大大减慢它。有没有办法加速这段代码?

Sub Button1_DeleteRow()

Dim i As Integer
Dim j As Integer    
Dim Value As Variant
Dim toCompare As Variant

For i = 1 To 3000      
    Value = Cells(i, 1)
    For j = (i + 1) To 3000
        toCompare = Cells(j, 1)
        If (StrComp(Value, toCompare, vbTextCompare) = 0) Then
           Rows(j).EntireRow.Delete
        End If
      Next j  
Next i

End Sub 

4 个答案:

答案 0 :(得分:4)

如果您正在运行xl07 / 10,那么您可以使用Remove Duplicates一行执行此操作。如果您运行03,那么使用AutoFilter的解决方案将是最有效的(如果您使用的是旧版本,我可以提供此解决方案)

删除重复项

  1. 手动

    • 选择A列
    • 数据....删除重复项
    • 展开选择
    • 仅选择A列以查找
    • 上的重复项
  2. 代码

    ActiveSheet.Range("$A$1:$A$3000").EntireRow.RemoveDuplicates Columns:=1, Header:=xlNo

  3. before only A after

答案 1 :(得分:3)

要补充@ brettdj的答案,如果您运行的是Excel 2003,可以使用AdvancedFilter执行此操作,如下所示:

Range("A1:A11").AdvancedFilter Action:=xlFilterInPlace, Unique:=True

注意:AdvancedFilter假定范围的第一行(本例中的A行)包含列标题,并且不会在过滤中包含该行。

手动执行此操作:数据>过滤器>高级过滤器...>仅限唯一记录

答案 2 :(得分:2)

使用Bretts技术是一个很好的答案:但要回答你的问题,为什么需要这么长时间:
- 您的宏逐个获得超过400万个单元格的值。这很慢 - 我没有看到你的宏关闭了屏幕更新和自动计算:每次删除一行时,屏幕将刷新,Excel将重新计算。如果你没有关掉这些,那就很慢了 此代码运行速度要快得多

Option Explicit
Sub Button1_DeleteRow()
Dim i As Long
Dim j As Long
Dim vArr As Variant
Dim iComp As Long
Dim Deletes(1 To 3000) As Boolean
Application.ScreenUpdating = False
iComp = Application.Calculation
Application.Calculation = xlCalculationManual
vArr = Range("a1:A3000")
For i = 1 To 3000
    For j = (i + 1) To 3000
        If (StrComp(vArr(i, 1), vArr(j, 1), vbTextCompare) = 0) Then
           Deletes(j) = True
        End If
      Next j
Next i
For j = 3000 To 1 Step -1
If Deletes(j) Then Rows(j).EntireRow.Delete
Next j
Application.ScreenUpdating = True
Application.Calculation = iComp
End Sub

答案 3 :(得分:0)

对A列上的数据进行排序会使得在一次传递中识别和删除重复项变得微不足道


在回应下面的评论时,我将解释为什么排序是一种有用的技术。

通过将A列按顺序排序,重复删除只需要比较A列中的相邻条目。然后您可以在找到它们时删除重复的行,或者标记它们以便以后删除。

这个过程实际上应该不那么繁琐,因为你只需要对列表进行排序(并且排序,内置,往往非常快)然后通过列表删除/执行一次传递(而不是4498500)在你去的时候标记(显然你需要随后的清理通行证,如果你去标记)。

关于更改列表顺序的问题,首先添加一个额外的列(例如列D),并使D2包含值2(即只是行号)。稍后快速填写,每行都有编号。排序和删除/标记后,恢复原始订单只需要在D列上重新排序,然后可以将其删除。

当我必须在复制品上执行某些操作或其他操作时,我使用此方法。换句话说,列A具有重复值,但列B和C中的值是有意义的(例如,我可能想要从与列A的特定值相关的所有条目中对这些值求和)。但是,在许多情况下,使用SQL来实现相同的结果会更容易