更有效的删除行的方法

时间:2017-06-19 09:41:44

标签: excel excel-vba vba

我有一些代码可以删除不在指定的行号列表中的行。它按预期运作。

 For lRow = numRowsInBBS To 1 Step -1

    lMatch = 0
    On Error Resume Next
    lMatch = Application.Match(lRow, ws.Range("AE4:AE" & numRows).Value, 0&)
    On Error GoTo 0

    If Not CBool(lMatch) Then
      wsImport.Cells(lRow, 1).EntireRow.Delete
    End If
  Next
End Sub

然而,这需要大量的时间。要在150行上执行此操作需要几分钟的处理时间。我的文档可能是1000行。

基本上我想删除指定工作表上的所有行,除了AE4:AE??中指定的行号(这是由numRows计算)在另一个工作表上。

数据范围不连续,AE4:AE??可以将数字3,4,5,33,66,101,110列为要保留的行。所有其他行都将被删除。

有没有更好的方法来实现我的目标?

我听说autofilter要快得多,但是我不知道如何在这里应用它,因为我没有匹配字符串或单元格中的任何内容,只是行号。

编辑: 根据建议,我尝试了自动过滤方式:

Dim rowsToKeep() As Variant: rowsToKeep = ws.Range("AE4:AE" & numRows)
Dim allRows As Range: Set allRows = Range("ZZ1:ZZ" & numRowsInBBS)

With wsImport
.Range(allRows.Address).Formula = "=row()"
.Range(allRows.Address).AutoFilter Field:=1, Criteria1:=rowsToKeep, Operator:=xlFilterValues
.Range(allRows.Address).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.Range(allRows.Address).AutoFilter Field:=1
End With

我想: 将范围AE4:AE??中的数据设置为数组的数据 - 然后使用ZZ作为包含行号的辅助列 - 然后过滤掉我想要保留的行 - 然后删除所有可见行 - 然后显示已过滤的行

但是,过滤器隐藏了所有内容,这表明rowsToKeep出现了问题,而另一张上的是AE4:AE??确实包含值。

1 个答案:

答案 0 :(得分:2)

尝试此操作(未经测试

删除循环中的行总是会变慢。下面的代码所做的是它存储需要在一个范围对象中删除的行,然后在一次性循环中删除它们。

Dim delRng As Range

For lRow = 1 To numRowsInBBS
    On Error Resume Next
    lMatch = Application.Match(lRow, ws.Range("AE4:AE" & numRows).Value, 0&)
    On Error GoTo 0

    If Not CBool(lMatch) Then
        If delRng Is Nothing Then
            Set delRng = wsImport.Rows(lRow)
        Else
            Set delRng = Union(delRng, wsImport.Rows(lRow))
        End If
    End If
Next

If Not delRng Is Nothing Then delRng.Delete

使用CountIf未经测试

Dim delRng As Range

For lrow = 1 To numRowsInBBS
    If Application.WorksheetFunction.CountIf(ws.Range("AE4:AE" & numRows), lrow) > 0 Then
        If delRng Is Nothing Then
            Set delRng = wsImport.Rows(lrow)
        Else
            Set delRng = Union(delRng, wsImport.Rows(lrow))
        End If
    End If
Next

If Not delRng Is Nothing Then delRng.Delete