【问题标题】:I am using an if statement nested in a loop that is slowing down my code. What can I do to speed it up?我正在使用嵌套在循环中的 if 语句,这会减慢我的代码。我该怎么做才能加快速度?
【发布时间】:2017-06-19 14:28:56
【问题描述】:

我有一个嵌套在循环中的 if 语句,用于清理导入的数据。 if 语句评估活动单元格的值,然后如果活动单元格符合特定条件,则删除活动单元格的行。我想知道是否有另一种编码方式,因此它不会在每次迭代时都引用电子表格,从而使其运行速度比现在快。任何提示将不胜感激。我正在使用的代码如下:

Sub copy_RawAvgDem()

Dim wkb1 As Workbook
Dim sht1 As Worksheet
Dim wkb2 As Workbook
Dim sht2 As Worksheet

Set wkb1 = ThisWorkbook
Set wkb2 = Workbooks.Open("M:\FAST team\Inventory_Planning\2016_05_FG_Inv_targets.xlsx")
Set sht1 = wkb1.Sheets("RawAvgDem")
Set sht2 = wkb2.Sheets("Model")

sht2.ShowAllData
sht2.Cells.Copy
sht1.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode = False
wkb2.Close False

Worksheets("RawAvgDem").Activate
Range("AN2").Select

Do Until IsEmpty(ActiveCell.Value)
    If ActiveCell.Value = "MTO" Then
        Rows(ActiveCell.Row).EntireRow.Delete
    Else: ActiveCell.Offset(1, 0).Select
    End If
Loop

End Sub

【问题讨论】:

  • 当您打开 wkb2 而不是将数据读取到工作表时,将此数据读入数组,然后从数组中删除任何“行”,然后将数组输出到工作表上。调用工作表很昂贵(就运行时间而言),如果需要速度,应该避免
  • 附注:阅读stackoverflow.com/questions/10714251/… - 为什么不选择并激活。至于您的循环...尝试使用AutoFilter 过滤其中包含“MTO”的所有行并立即删除它们。

标签: vba excel loops if-statement


【解决方案1】:

提高性能的最佳方法是尽可能消除循环。正如 cmets 中所提到的,您可以根据适当的值过滤列 AN,然后一次性删除所有行,而不是循环遍历。在wkb2.Close 之后,您可以改为:

With Worksheets("RawAvgDem")
        .Range("$AN$2").AutoFilter Field:=Range("$AN$2").Column, Criteria1:="MTO"
        .Range(Range("$AN$3"), Range("$AN$3").End(xlDown)).EntireRow.Delete
        .Range("$AN$2").AutoFilter Field:=Range("$AN$2").Column
End With

这假设 A-AN 列中有数据。如果不是这种情况,您必须将Field 更新为适当的数字(这是基于过滤列数的相对数字)。作为参考,AN 是电子表格中的第 40 列(Range("$AN$2").Column 返回 40,因此静态 40 也可以在那里工作)。例如,如果您缺少 A 列中的数据,则该数字必须为 39。根据需要进行调整。

【讨论】:

    【解决方案2】:

    你不需要使用ActiveCell.Offset(1, 0).Select 来前进到下一行,用下面的循环替换你的循环:

    With Worksheets("RawAvgDem")
        Dim i As Long
    
        i = 2
        Do Until IsEmpty(.Range("AN" & i).Value)
            If .Range("AN" & i).Value = "MTO" Then
                .Rows(i).Delete
            Else
                i = i + 1
            End If
        Loop
    End With
    

    【讨论】:

    • 稍微扩展一下:一般来说,应始终避免使用SelectActivate
    • @Soulfire 没错,我只是想把 PO 集中在他应该进行更新的地方
    • 另外,我会用 i 向后做。您可能会错过要删除的行:比如说第 4 行和第 5 行要删除。但是删除第4行后,你转到第5行,但实际上你已经在第6行了,因为删除4会使5变成4
    • @PatrickLepelletier 实际上没有,因为你在推进行计数器 i,只有在不删除行时,再次检查代码逻辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 2015-07-04
    • 1970-01-01
    • 2013-10-21
    • 2012-08-19
    • 2016-07-13
    • 2021-12-14
    相关资源
    最近更新 更多