在宏执行期间关闭属性
在任何编程语言中,最好的做法是**避免过早优化。**但是,如果测试显示你的代码运行速度太慢,则可以通过在运行时关闭某些应用程序的属性来获得一些速度。将此代码添加到标准模块:
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_Change
和 Workbook_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
本身的属性,因此你需要确保在宏退出之前再次启用它们。这使得使用错误处理程序并避免多个退出点(即 End
或 Unload 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