【问题标题】:VBA code optimizationVBA代码优化
【发布时间】:2014-07-24 13:44:04
【问题描述】:

我有一组 VBA 代码,它们非常适合大约 20 000 x 16 个单元格。 但是,我需要使用最多 80 000 x 16 个单元格的代码。

我发现了两种运行速度非常慢的代码:

    c = 2 'this is the first row where your data will output
    d = 2 'this is the first row where you want to check for data

    Application.ScreenUpdating = False


    Do Until Range("A" & c) = "" 'This will loop until column U is empty, set the column to whatever you want
                            'but it cannot have blanks in it, or it will stop looping. Choose a column that is
                            'always going to have data in it.

     ws1.Range("U" & d).FormulaR1C1 = "=RC[-20] & RIGHT(""0000"" & RC[-14], 6)"

     c = c + 1 'Advances a and b when there is a matching case
     d = d + 1

    Loop

    Application.ScreenUpdating = True

End Sub 

Sub OpenValue()    
    Dim l As Integer
    Dim k As Integer
    Dim m As Integer

    m = Sheets("Input").Range("AC:AC").End(xlDown).Row

    For l = 2 To m

    If Range("AC" & l) = "Delievered" Then
       Range("AD" & l) = 0

    ElseIf Range("AC" & l) = "Cancelled" Then
       Range("AD" & l) = 0

    Else
      Range("AD" & l) = Val(Range("Z" & l)) * Val(Range("J" & l))

         End If

    Next

End Sub

我能做些什么来优化它们......

【问题讨论】:

  • 使用Cells而不是Range,这样可以避免字符串连接(例如:Cells(l, 30)而不是Range("AD" & l)
  • 这应该在 CodeReview.SE 中,而不是 StackOverflow 中。
  • 问题属于代码审查

标签: excel vba


【解决方案1】:

@GSerg 提供的链接是减少脚本运行时间的绝佳方式。我发现自己在使用:

  • Application.ScreenUpdating 设置为 False
  • Application.Calculation 设置为 xlCalculationManual
  • Application.EnableEvents 设置为 False
  • Application.DisplayAlerts 设置为 False

我经常将它们组合成一个公共子例程。 @Garys-Student 提供了灵感:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT         : True or False (i.e. fast or slow)
'DESCRIPTION   : this sub turns off screen updating and alarms then
'                sets calculations to manual
'
Public Sub GoFast(OnOrOff As Boolean)
    Dim CalcMode As XlCalculation
    CalcMode = Application.Calculation
    With Application
        .ScreenUpdating = Not OnOrOff
        .EnableEvents = Not OnOrOff
        .DisplayAlerts = Not OnOrOff
        If OnOrOff Then
            .Calculation = xlCalculationManual
        Else
            .Calculation = CalcMode
        End If
    End With
End Sub

实际上,您现在可以添加单行:

Call GoFast(True)

在脚本的开头作为设置的一部分,然后添加:

Call GoFast(False)

作为拆解的一部分,在脚本的末尾。随意修改!

【讨论】:

    【解决方案2】:

    Do Until 可以替换为一个衬里:

    ws1.Range("A2", ws1.Range("A2").End(xlDown)).Offset(0,20).FormulaR1C1 = _
        "=RC[-20] & RIGHT(""0000"" & RC[-14], 6)"
    

    请注意,如果A3 为空,这将失败。如果您在第 1 行有标题,您可以将第二个 A2 更改为 A1

    对于另一个Sub,我不确定您是否对Val 做了一些特别的事情,但如果不是,您可以将其更改为类似的内容:

    Sub OpenValue()
    
        Dim r As Range
        Set r = Sheets("Input").Range("AD2:AD" & Sheets("Input").Range("AC1").End(xlDown).Row)
        With r
            .FormulaR1C1 = "=IF(OR(RC[-1]=""Delivered"",RC[-1]=""Cancelled""),0,RC10*RC26"
            'If you want these as values uncomment the following lines
            '.Calculate
            '.Copy
            '.PasteSpecial xlPasteValues
        End With
    End Sub
    

    如果需要,在周围撒上Application 的东西(Calculation、ScreenUpdating、DisplayAlerts、EnableEvents)。

    为什么会更快:

    简单地说,VBA 和 Excel 必须打开一个“通道”来相互通信,这需要一些时间。因此,循环遍历一个 Range 并一个接一个地添加公式对于大范围来说比一次性完成要慢得多,因为您只会打开一次“通道”。

    【讨论】:

      猜你喜欢
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      相关资源
      最近更新 更多