在宏执行期间关闭属性

在任何编程语言中,最好的做法是**避免过早优化。**但是,如果测试显示你的代码运行速度太慢,则可以通过在运行时关闭某些应用程序的属性来获得一些速度。将此代码添加到标准模块:

Public Sub SpeedUp( _
    SpeedUpOn As Boolean, _
    Optional xlCalc as XlCalculation = xlCalculationAutomatic _
)
    With Application
        If SpeedUpOn Then
            .ScreenUpdating = False
            .Calculation = xlCalculationManual
            .EnableEvents = False
            .DisplayStatusBar = False 'in case you are not showing any messages
            ActiveSheet.DisplayPageBreaks = False 'note this is a sheet-level setting
        Else
            .ScreenUpdating = True
            .Calculation = xlCalc
            .EnableEvents = True
            .DisplayStatusBar = True
            ActiveSheet.DisplayPageBreaks = True
        End If
    End With
End Sub

有关 Office 博客的更多信息 - Excel VBA 性能编码最佳实践

只需在宏的开头和结尾调用它:

Public Sub SomeMacro
    'store the initial "calculation" state
    Dim xlCalc As XlCalculation
    xlCalc = Application.Calculation

    SpeedUp True

    'code here ...

    'by giving the second argument the initial "calculation" state is restored
    'otherwise it is set to 'xlCalculationAutomatic'
    SpeedUp False, xlCalc
End Sub

虽然这些可以在很大程度上被视为常规 Public Sub 程序的增强,但对于改变一个或多个工作表上的值的 Worksheet_ChangeWorkbook_SheetChange 私有事件宏,禁止使用 Application.EnableEvents = False 禁用事件处理。无法禁用事件触发器将导致事件宏在值更改时以递归方式运行,并且可能导致冻结工作簿。记得在离开事件宏之前重新打开事件,可能是通过安全退出错误处理程序。

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A:A")) Is Nothing Then
        On Error GoTo bm_Safe_Exit
        Application.EnableEvents = False
        
        'code that may change a value on the worksheet goes here
        
    End If
bm_Safe_Exit:
    Application.EnableEvents = True
End Sub

需要注意的是: 禁用这些设置会缩短运行时间,但它们可能会使调试应用程序变得更加困难。如果你的代码无法正常运行,请注释掉 SpeedUp True 调用,直到找出问题为止。

如果你正在写入工作表中的单元格,然后从工作表函数中读回计算结果,则这一点尤为重要,因为 xlCalculationManual 会阻止计算工作簿。要在不禁用 SpeedUp 的情况下解决此问题,你可能需要包含 Application.Calculate 以在特定点运行计算。

注意: 由于这些是 Application 本身的属性,因此你需要确保在宏退出之前再次启用它们。这使得使用错误处理程序并避免多个退出点(即 EndUnload Me)尤为重要。

有错误处理:

Public Sub SomeMacro()
    'store the initial "calculation" state
    Dim xlCalc As XlCalculation
    xlCalc = Application.Calculation

    On Error GoTo Handler
    SpeedUp True
    
    'code here ...
    i = 1 / 0
CleanExit:
    SpeedUp False, xlCalc
    Exit Sub
Handler:
    'handle error
    Resume CleanExit
End Sub