屏幕更新的效果

时间:2012-09-12 15:37:37

标签: excel vba excel-vba optimization

我一直在测量代码执行时间,以衡量在本地和我的服务器上执行脚本之间的差异。有一次,我忘了禁用screen updating,并且感谢我对闪光灯不敏感,然后再详细考虑一下:

当我第一次开始使用VBA时,我总是认为它只是被使用,因此它不会吓到最终用户认为他们的PC即将崩溃。当我开始阅读更多关于提高代码效率的内容时,我理解它的用途,但screen updating对代码执行时间有多大影响?

5 个答案:

答案 0 :(得分:33)

如果代码以导致屏幕内容更改的方式与Excel交互,则关闭屏幕更新只会对执行时间产生影响。屏幕变化量越大,影响越大。其他发布的答案恰当地证明了这一点。

可能对执行时间产生影响的其他应用程序设置是计算和事件处理。使用此代码模板作为起点(错误处理程序确保在sub的末尾重新打开这些属性,即使它出错)

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。而是声明并分配变量并引用它们。
  2. 引用大范围时,将Range数据复制到变量数组进行处理,并将结果复制回到之后的范围。
  3. 使用Range.SpecialCellsRange.FindRange.AutoFilter来限制引用的单元格数。
  4. 在SO上有很多这些技术的例子。

答案 1 :(得分:7)

如果您想查看ScreenUpdating重要原因的相当激烈的示例,请运行以下代码。在Excel 2011中,在没有ScreenUpdating = false的情况下运行此交换需要大约45倍的时间!这是巨大的时间差异。

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很少(如果有的话)必要。当您录制宏时,它将始终使用这些宏,但是当您需要在代码中实际使用它们时,情况非常少。同样,标题中Active的任何内容(例如ActiveCell)通常都表示您的代码较慢,因为您可能正在选择单元格。

您几乎总能专门引用单元格/工作表并避免选择。例如:

msgbox (Worksheets(1).Range("A1").value) 
无论您当前是否在第一张工作表上,

都能正常运行。一个常见的新VBA错误是做更多的事情:

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

这是一个不需要的步骤。

这为代码运行时增加了大量时间。

答案 2 :(得分:3)

首先,我一直在使用Richie(英国)发布的#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编辑器中的“运行”按钮进行的​​,而不是“观察”电子表格。

代码开头和结尾的两行简单:

Application.ScreenUpdating = False
Application.ScreenUpdating = True

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

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

答案 3 :(得分:1)

有一个重要的事情需要了解屏幕更新,我在之前的任何答案中都没有看到。根据我自己的测试,我发现关闭和打开屏幕更新需要大约15毫秒(通过Excel Interop在C#中测试)。如果你要执行任何花费更少时间的事情,请记住这一点。毕竟在某些循环中不要多次打开/关闭屏幕更新。那将是真正的性能杀手。

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

答案 4 :(得分:1)

我知道这是一个老线程,但是:

  1. 设置ScreenUpdating = true,但请记住将其设置回旧值。
  2. 更改工作簿也会重置ScreenUpdating