【问题标题】:How to speed up this code to find and delete rows if a substring is found如果找到子字符串,如何加快此代码查找和删除行的速度
【发布时间】:2016-03-28 15:53:11
【问题描述】:

下面的代码按预期工作得很好,唯一的缺点是它很慢,因为我使用它来搜索子字符串的所有实例并删除整个工作簿的任何单元格中的整行。

目标很简单,如果在任何单元格字符串中找到输入的字符串,只需删除整行

Dim wo As Worksheet, ws As Worksheet
Dim I As Long, j As Long, m As Long
Dim toFind As String, testStr As String
Dim pos As Long
Dim lstRow As Long, cutRow As Long
Dim WS_Count As Integer
Dim Cell As Range

Option Compare Text
Option Explicit

Sub SearchDelete()

toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
toFind = Trim(toFind)
j = 0

If toFind = "" Then
    MsgBox "Empty String Entered.Exiting Sub Now."
    Exit Sub
Else
        WS_Count = ActiveWorkbook.Worksheets.Count

        'Begin the loop.
        For I = 1 To WS_Count

Label1:
                For Each Cell In Worksheets(I).UsedRange.Cells

                    If Trim(Cell.Text) <> "" Then
                        pos = 0
                        pos = InStr(1, Trim(Cell.Text), toFind, vbTextCompare)

                        If pos > 0 Then     'match Found'

                            cutRow = Cell.Row
                            Worksheets(I).Rows(cutRow).EntireRow.Delete
                            j = j + 1
                           GoTo Label1
                        Else: End If

                    Else: End If

                Next Cell
         Next I
End If

MsgBox "Total " & j & " Rows were deleted!"

End Sub

【问题讨论】:

  • 试试range.find?编辑:但这可能更适合代码审查。
  • 一个非常简单的提高速度的方法是在您的子目录的开头使用Application.ScreenUpdating = False,在您的子目录的末尾使用Application.ScreenUpdating = True。这只会在您的 sub 结束时更新屏幕,而不是在每次删除一行时更新。
  • @findwindow 我会这样做,但我不知道Range.Find 是否会返回找到的部分匹配的所有行号以及如何在循环中使用它?在这种情况下,任何实施示例都会对我有所帮助!
  • range.findnext
  • @newguy Range.Find 将找到您搜索的任何内容的第一个实例。 Range.FindNext 将返回下一个匹配的单元格并继续这样做,直到范围内没有更多单元格与搜索匹配,此时它将返回 Nothing

标签: performance vba excel search


【解决方案1】:

单个操作几乎总是比批量操作慢,Range.Delete method 也不例外。使用 Union method 收集匹配的行,然后执行删除 en masse 将显着加快操作速度。

暂时挂起某些应用程序环境处理程序也会有所帮助。删除行时不需要激活Application.ScreenUpdating;仅在您完成操作后。

Option Explicit
Option Compare Text

Sub searchDelete()
    Dim n As Long, w As Long
    Dim toFind As String, addr As String
    Dim fnd As Range, rng As Range

    toFind = InputBox("Enter the substring you want to search for.", "Welcome", "AAAA")
    toFind = Trim(toFind)

    If Not CBool(Len(toFind)) Then
        MsgBox "Empty String Entered.Exiting Sub Now."
        GoTo bm_Safe_Exit
    End If

    'appTGGL bTGGL:=False   'uncomment this line when you have finsihed debugging

    With ActiveWorkbook
        For w = 1 To .Worksheets.Count
            With .Worksheets(w)
                Set fnd = .Cells.Find(what:=toFind, lookat:=xlPart, _
                            after:=.Cells.SpecialCells(xlCellTypeLastCell))
                If Not fnd Is Nothing Then
                    Set rng = .Rows(fnd.Row)
                    n = n + 1
                    addr = fnd.Address
                    Do
                        If Intersect(fnd, rng) Is Nothing Then
                            n = n + 1
                            Set rng = Union(rng, .Rows(fnd.Row))
                        End If
                        Set fnd = .Cells.FindNext(after:=fnd)
                    Loop Until addr = fnd.Address
                    Debug.Print rng.Address(0, 0)
                    rng.Rows.EntireRow.Delete
                End If
            End With
        Next w
    End With

    Debug.Print "Total " & n & " rows were deleted!"

bm_Safe_Exit:
    appTGGL

End Sub

Public Sub appTGGL(Optional bTGGL As Boolean = True)
    Application.ScreenUpdating = bTGGL
    Application.EnableEvents = bTGGL
    Application.DisplayAlerts = bTGGL
    Application.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
    Debug.Print Timer
End Sub

【讨论】:

  • 伙计,现在你让我重新思考我的架构。如果您要搜索的字符串都紧密组合在一起(在 6000 行工作表中彼此相距 40 行),该怎么办。使用findnext 是否更快,或者您可以只使用find 然后从该行向前循环吗?
  • @findwindow - 我不确定如何肯定地确定包含子字符串的字符串被组合在一起,但假设它们随后缩小要查看的行会加快速度。然而,这导致简单地确定较小区域可能需要与简单地循环一样多或更多的计算的可能性。例如查找(正向)然后查找(反向)以确定进一步 FindNexts 的“缩小”范围是否比简单地查找和 FindNext 更快?如果没有更多的处理,它似乎是相同的。
  • 它本质上是一个按数字顺序排列的列表,每个 ID 都以块的形式组合在一起,所以一旦我找到第一次出现,我就知道其余的都在以下行中。它正是试图确定驱动架构的区域(范围)。它实际上更复杂,因为可能需要划分每个 ID 块。听起来我的架构已经足够好了^_^;谢谢
【解决方案2】:

您的问题的答案:"How to speed up this code to find and delete rows if a substring is found" 是 - 不要在找到并删除该行后从工作表顶部重复搜索!

【讨论】:

  • 是的,我知道为此我引入了Goto 语句,它基本上在删除后再次重复该过程。你知道如何将For Each Cell 循环向后循环吗?因为我没有。
猜你喜欢
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-21
相关资源
最近更新 更多