遍历 ListObject 中的行以删除它们非常慢

Looping through rows in a ListObject to delete them is very slow

我有一个包含 ~500 行的 ListObject table,我在命名范围内也有 4 个值。

500 行可能有 30 个重复(随机)出现的唯一值,我想删除所有值不在指定范围内的行。

我有以下有效的方法,但它 运行 比预期的要慢(大约 2 分钟):

Sub removeAccounts()

Dim tbl As ListObject
Dim i As Integer

Set tbl = ThisWorkbook.Sheets("TheSheet").ListObjects("TheTable")

i = tbl.ListRows.Count


While i > 0
  If Application.WorksheetFunction.CountIf(Range("Included_Rows"), tbl.ListRows(i).Range.Cells(1).Value) = 0 Then
    tbl.ListRows(i).Delete
  End If
  i = i - 1
Wend

End Sub

我不确定是对工作表函数的依赖还是只是循环遍历正在减慢速度的行。

有没有办法过滤列表对象并丢弃其余的?

我正在考虑在上面添加一个进度条,以便用户可以看到正在发生的事情...

试试这个代码:

Sub removeAccounts()

 Dim tbl As ListObject
 Dim i As Long
 Dim uRng As Range

 Application.ScreenUpdating = False
 Application.EnableEvents = False
 Application.Calculation = xlCalculationManual


 Set tbl = ThisWorkbook.Sheets("TheSheet").ListObjects("TheTable")

 i = tbl.ListRows.Count


 While i > 0
   If Application.WorksheetFunction.CountIf(Range("Included_Rows"), tbl.ListRows(i).Range.Cells(1).Value) = 0 Then

      'tbl.ListRows(i).Delete
      If uRng Is Nothing Then
       Set uRng = tbl.ListRows(i).Range
      Else
       Set uRng = Union(uRng, tbl.ListRows(i).Range)
      End If
   End If
   i = i - 1
 Wend

  If Not uRng Is Nothing Then uRng.Delete xlUp

 Application.ScreenUpdating = True
 Application.EnableEvents = True
 Application.Calculation = xlCalculationAutomatic

 End Sub

你的问题不在于循环遍历单元格。事实上,您正试图从 table 中删除许多不连续的行;每一个都需要对 ListObject table 进行内部重新排序和重组。您可以做的任何一次删除所有行的操作都会有所帮助,如果您可以将它们作为一个块删除,那就更好了。此外,您可能会重复和冗余地重新计算整列公式。

你应该更快地找到下面的 scootch。

Sub removeAccounts()

    Dim i As Long

    Debug.Print Timer
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    With ThisWorkbook.Sheets("TheSheet")
        With .ListObjects("TheTable")
            '.Range.Columns(2).Delete
            .Range.Columns(2).Insert
            With .DataBodyRange.Cells(1, 2).Resize(.DataBodyRange.Rows.Count, 1)
                .FormulaR1C1 = "=isnumber(match(RC[-1], Included_Rows, 0))"
                .Calculate
            End With
            .Range.Cells.Sort Key1:=.Range.Columns(2), Order1:=xlDescending, _
                              Orientation:=xlTopToBottom, Header:=xlYes
            With .DataBodyRange
                i = Application.Match(False, .Columns(2), 0)
                Application.DisplayAlerts = False
                .Cells(i, 1).Resize(.Rows.Count - i + 1, .Columns.Count).Delete
                Application.DisplayAlerts = True
            End With
            .Range.Columns(2).Delete
        End With
    End With

    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    Debug.Print Timer

End Sub

I 运行 这针对 500 行样本数据 (A-Z),A-D 在 Included_Rows 命名为 运行ge。耗时0.02秒

试试这个:

Dim Tbl As ListObject
Set Tbl = Sheets(indx).ListObjects(Tabla)

With Tbl

If .ListRows.Count >= 1 Then .DataBodyRange.Delete

End With

使用这样的代码删除列表对象中除第一行以外的所有行。通过删除整行,它还适当地调整了 table 的大小。 tblData 是指向现有 table/listobject.

的 ListObject 变量
tblData.DataBodyRange.Offset(1, 0).EntireRow.Delete

当然,您不能在 table 的左侧或右侧放置数据,因为它也会被删除。但这比循环快得多。