两种条件下去除行的最有效方法

时间:2014-07-31 20:52:56

标签: excel performance vba loops

我要做的是在两个单独的列中删除电子表格中值为0的行,因为这表示该行中没有有用的数据。虽然可以使用For loop If/Then条件,但我发现这是令人难以置信的慢,因为我的数据集有大约51,000行,并且实际上需要花费数小时(如果不是几天)来运行。

经过一番搜索,我发现了一种替代方法,我相信它更快,目前正在使用:

Public Sub deleteRows()
     ' source: http://www.ozgrid.com/forum/showthread.php?t=64364
    Dim lastRow As Long
    Dim n As Long
    Dim RT As Date
    RT = Time

    With ActiveSheet
        lastRow = .Cells(.Rows.Count, 2).End(xlUp).Row
    End With

    For n = lastRow To 2 Step -1
        If (Trim(ActiveSheet.Cells(n, 3).Value) = 0) And (Trim(ActiveSheet.Cells(n, 6).Value) = 0) Then
            ActiveSheet.Cells(n, 1).EntireRow.Delete
        End If
    Next n
    MsgBox Format(Time - RT, "hh:mm:ss")
End Sub

但是,我只运行了1000个单元格的测试,运行时间为402秒,这表示以相同的速率运行所有数据需要5.584小时。

有没有办法加快这个过程?我错过了一些明显的东西吗?

*编辑:此代码作为另一个代码的子部分运行,其中ScreenUpdating = False在代码的开头声明。

2 个答案:

答案 0 :(得分:2)

不,它实际上需要更长的时间。如果你删除一行,它下面的每一行都会单独向上移动,如果你删除的行下面有更多的行,这显然需要更长的时间。

以下是一些简单的方法:

  1. 使用AutoFilter过滤不需要的行,然后删除可见的单元格。

  2. 使用AutoFilter过滤要保留的行并将其复制到新工作簿。

  3. 首先对值进行排序,以便所有不需要的行都位于底部。你已经完全从下到上删除了,所以你只需要在你的循环前插入一个排序。

答案 1 :(得分:1)

这是一种使用自动过滤器的方法:

Public Sub deleteRows()
    Dim lastRow As Long
    Dim rng As Range
    Dim start

    start = Timer
    With ActiveSheet
        .AutoFilterMode = False
        lastRow = .Cells(.Rows.Count, 2).End(xlUp).Row
        '~~> Set the range of interest, no need to include the entire data range
        Set rng = .Range("B2:F" & lastRow)
        rng.AutoFilter 2, 0 '~~> filter zeros on C column
        rng.AutoFilter 5, 0 '~~> filter zeros on F column
        '~~> Delete the entire row of the remaining visible cells
        rng.Offset(1, 0).Resize(rng.Rows.Count - 1) _
            .SpecialCells(xlCellTypeVisible).EntireRow.Delete
        .AutoFilterMode = False
    End With
    Debug.Print (Timer - start) * 1000 '~~> in ms
End Sub

对样本数据进行测试和测试(Cell B2:L52802) 在我的机器上删除了11699.22毫秒或大约11.7秒 我认为这比你估计的5个小时要快得多(特定的快1700倍)。