我一直在测量代码执行时间,以衡量在本地执行脚本和在服务器上执行脚本之间的差异。有一次我忘了禁用screen updating
,很庆幸我在更详细地考虑它之前对闪光灯不敏感:
当我第一次开始使用时,VBA
我总是认为它只是被使用过,所以它不会吓到最终用户认为他们的 PC 即将崩溃。screen updating
当我开始阅读更多关于提高代码效率的内容时,我明白了它的用途,但是对代码执行时间有多大影响呢?
我一直在测量代码执行时间,以衡量在本地执行脚本和在服务器上执行脚本之间的差异。有一次我忘了禁用screen updating
,很庆幸我在更详细地考虑它之前对闪光灯不敏感:
当我第一次开始使用时,VBA
我总是认为它只是被使用过,所以它不会吓到最终用户认为他们的 PC 即将崩溃。screen updating
当我开始阅读更多关于提高代码效率的内容时,我明白了它的用途,但是对代码执行时间有多大影响呢?
如果代码与 Excel 交互的方式导致屏幕内容发生更改,则关闭屏幕更新只会影响执行时间。屏幕变化量越大,影响就越大。其他发布的答案恰当地证明了这一点。
其他可以影响执行时间的应用程序设置是计算和事件处理。使用此代码模板作为起点(错误处理程序确保在子结束时重新打开这些属性,即使它出错)
Sub YourSub()
On Error GoTo EH
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
' Code here
CleanUp:
On Error Resume Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Exit Sub
EH:
' Do error handling
Resume CleanUp
End Sub
存在可以提供更大的执行速度改进的其他技术。
最有用的包括
Select
,Activate
并且ActiveCell/Sheet/Workbook
尽可能地。而是声明和分配变量并引用它们。Range.SpecialCells
,Range.Find
和Range.AutoFilter
来限制引用的单元格的数量。SO上有很多这些技术的例子。
如果您想查看一个相当激烈的示例来说明为什么ScreenUpdating
重要,请运行以下代码。在 Excel 2011 中,我在没有ScreenUpdating = false
! 这是一个巨大的时间差异。
Sub testScreenUpdating()
Dim i As Integer
Dim numbSwitches As Integer
Dim results As String
'swap between sheets this number of times
numbSwitches = 1000
'keep track of time
Dim startTime As Double
startTime = Time
'swap between sheets 1/2 (need both sheets or this will crash)
For i = 1 To numbSwitches
Sheets(1 + (i Mod 2)).Select
Next i
'get results
results = "Screen Updating not disabled: " & Format(Time - startTime, "hh:mm:ss") & " seconds"
startTime = Time
'scenario 2 - screenupdating disabled
Application.ScreenUpdating = False
'swap between sheets 1/2 (need both sheets or this will crash)
For i = 1 To numbSwitches
Sheets(1 + (i Mod 2)).Select
Next i
Application.ScreenUpdating = True
'get results for part two
results = results & vbCrLf & "Screen Updating IS disabled: " & Format(Time - startTime, "hh:mm:ss") & " seconds"
'show results
MsgBox results
End Sub
此外,虽然我们讨论的是提高效率的方法,但另一个关键点是Select
、Selection
和Activate
很少(如果有的话)必要。当您录制宏时,它总是会使用这些宏,但是在极少数情况下您需要在代码中实际使用它们。同样,Active
标题中的任何内容(例如ActiveCell
)通常都表明您的代码将变慢,因为您可能正在选择单元格。
您几乎总是可以专门参考单元格/工作表并避免选择。例如:
msgbox (Worksheets(1).Range("A1").value)
无论您当前是否在第一个工作表上,都可以使用。一个常见的新 VBA 错误是执行以下操作:
Worksheets(1).Select
msgbox (Range("A1").value)
这是一个不需要的步骤。
这增加了代码运行时的大量时间。
首先,我一直在使用 Richie (UK) Post #7 Here编写的脚本
它只是迭代一个循环,改变一个单元格中 i 的值。我稍微改变了它,所以它循环了 10,000 次,我为样本量执行了 10 次。
屏幕更新对我的代码执行速度有何影响?
Screen Updating
这些是禁用和启用时的执行长度:
Disabled Enabled
0.61909653 2.105066913
0.619555829 2.106865363
0.620805767 2.106866315
0.625528325 2.102403315
0.625319976 2.0991179
0.621287448 2.105103142
0.621540236 2.101392665
0.624537531 2.106866716
0.620401789 2.109004449
如您所见,在Screen Updating
未禁用时执行代码所需的时间几乎是 3.5 倍。
这两个代码都是使用 VB 编辑器中的“运行”按钮执行的,而不是“观看”电子表格。
代码开头和结尾的 2 行简单的代码:
Application.ScreenUpdating = False
Application.ScreenUpdating = True
但是,它们会对您的执行效率产生很大影响!
注意:显然Screen Updating
这里的许多人都知道 的优点,但这可能对初学者有好处,我发现查看数字很有趣!
关于屏幕更新,有一件重要的事情需要了解,我在之前的任何答案中都没有看到。从我自己的测试中,我发现关闭和打开屏幕更新大约需要 15 毫秒(通过 Excel 互操作在 C# 中测试)。如果您将执行任何花费更少时间的事情,请记住这一点。毕竟不要在某个循环中多次打开/关闭屏幕更新。那将是真正的性能杀手。
如果你想快速使用 C++,还有一个注意事项(你可能不想听到)。它通常比 VBA 快 5 到 10 倍(不要在这里抓住我,这取决于您的实际操作)。
我知道这是一个旧线程,但是:
ScreenUpdating = true
,但请记住将其设置回其旧值。ScreenUpdating
。