屏幕更新的效果

我一直在玩围绕测量代码执行时间来衡量执行我的脚本本地和我的服务器之间的差异。 有一次,我忘了禁用screen updating ,并感谢我对闪光灯不敏感之前,更详细地考虑它:

当我第一次开始使用VBA我总是认为它只是被使用,所以它不会吓着最终用户认为自己的电脑即将崩溃。 当我开始更多地阅读提高代码的效率时,我明白了这是什么原因,但screen updating对于代码执行时间有多大影响?

如果代码与Excel交互的方式导致屏幕内容更改,closures屏幕更新只会影响执行时间。 屏幕变化越大,影响就越大。 其他发布的答案恰当地certificate了这一点。

其他可以改变执行时间的应用程序设置是计算和事件处理。 使用这个代码模板作为出发点(error handling程序确保这些属性在子结尾处重新打开,即使它出错)

 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 GoTo CleanUp End Sub 

其他存在的技术可以在执行速度上提供更大的改进。

最有用的包括

  1. 尽可能避免SelectActivateActiveCell/Sheet/Workbook 。 而是声明和分配variables并引用这些variables。
  2. 当引用大范围时,将范围数据复制到变体数组进行处理,并将结果复制回到之后的范围。
  3. 使用Range.SpecialCellsRange.FindRange.AutoFilter来限制引用的单元格的数量。

SO上有很多这些技术的例子。

如果你想看到为什么ScreenUpdating很重要的一个相当激烈的例子,运行下面的代码。 在Excel 2011中,我需要大约45倍的时间来运行这个交换,而不需要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 

另外,虽然我们正在讨论提高效率的方法,但另一个关键点是SelectSelectionActivate很less(如果有的话)是必要的。 当你录制macros时,它总是会使用这些macros,但是当你需要在代码中实际使用它们的时候,很less有这样的情况。 同样,任何标题中的Active (例如ActiveCell )通常都会表示您的代码会较慢,因为您可能正在select单元格。

您几乎总是可以专门引用单元格/工作表,并避免select。 例如:

 msgbox (Worksheets(1).Range("A1").value) 

无论您目前是否在第一张工作表上都可以工作。 一个常见的新的VBA错误是做更多的事情:

 Worksheets(1).Select msgbox (Range("A1").value) 

这是一个不必要的步骤。

这增加了代码运行时间的时间。

首先,我一直在使用Richie(UK)Post#7 这里写的脚本

它只是遍历一个循环改变我在一个单元格中的值。 我已经改变了一点,所以它循环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编辑器中的运行button,而不是“观看”电子表格。

代码的开始和结束处有两行简单的代码:

 Application.ScreenUpdating = False Application.ScreenUpdating = True 

但是,它们会对执行效率产生很大的影响!

注意:很显然, Screen Updating的好处在很多人都知道,但这可能对初学者有好处,我觉得查看数字很有趣!

有一个重要的事情要了解屏幕更新,我没有看到任何以前的答案。 从我自己的testing中,我发现,closures屏幕更新大约需要15ms(通过Excel Interop在C#中testing)。 请记住,如果你会执行任何需要更less的时间。 毕竟在某些循环中不要多次开启/closures屏幕更新。 这将是真正的性能杀手。

还有一个注释(你可能不想听),如果你想快速使用C ++。 它通常比VBA快5到10倍(这里不要抓到我,这取决于你真正做了什么)。

我知道这是一个古老的线索,但是:

1)不要设置ScreenUpdating = true,但要记住并设置回它的旧值。 2)更改工作簿也将重置Screenupdating。