如何在Excel VBA中更好地管理内存以防止宏减速?

Sou*_*ire 1 excel performance vba excel-vba

背景

我继承了相当多的Excel VBA代码,这些代码很不稳定且运行缓慢.该代码将用户输入模拟成数千次,然后生成输出文件以发送给其他一些用户.到目前为止,我通过消除复制/粘贴,通过在数组内工作而不是直接访问工作表和单元格,删除不必要的代码,以及通过将许多易失性公式重新处理成更好的东西,在性能上取得了很大的进步.

在我的更改之前,运行此报告来模拟用户输入每个用户大约需要65秒(并且大约有4,300个用户).那是279,500秒(大约77.6小时).这是假设一个恒定的速度,宏开始的速度相同.事实并非如此.实际上,宏在一夜之间处理时显着减慢,到每个用户花费超过120秒的程度.

问题

在我的代码清理和性能改进之后,我得到了宏,每个用户大约10秒开始,这是一个很好的速度.我让这个宏在昨晚一夜之间运行,今天早上来看看它现在每个用户大约需要90秒,所以我在一夜之间遇到了很大的性能下降.

我的问题是:如果随着时间的推移宏运行,我如何防止这种减速?

研究

我并非没有想法.目前,我的想法是,我需要关闭并重新打开Excel工作簿,因为它们陷入垃圾陷入困境.我的一个想法是使用本机VB.NET应用程序打开Excel工作簿并运行宏.每500个左右的用户,我可以在工作簿的单元格中的某处写入相关变量,保存并关闭工作簿,然后重新打开它以从我离开的地方继续.这对我来说似乎并不优雅.此外,可能很难说服其他人我需要引入"新"技术(VB.NET).人们对此很奇怪,并且更喜欢原生的VBA解决方案.

有没有更好的方法来管理Excel,这样我就不必创建一个新的VB.NET应用程序并进行保存/关闭/打开?

我想补充说,没有特定的违规代码,随着时间的推移,它只会减慢速度(仍然有效!).

Sam*_*Sam 9

一些基本的东西可以帮助,我相信你已经尝试过最多:

  • Application.Calculation = xlCalculationManual
  • Application.ScreenUpdating = False
  • Application.EnableEvents = False

关于上述内容的注释,总是假设您的代码将失败并确保使用适当的错误处理程序将这些设置重置为其默认值


  • 用于DoEvents将控制权一次又一次地返回处理器,可能需要完成一些需要完成的流程以释放资源.
  • 尽可能使用直接布尔比较.

代替:

If someVar > 5 Then
    boolVar = True
Else
    boolVar = False
End If
Run Code Online (Sandbox Code Playgroud)

考虑使用

boolVar = someVariable > 5
Run Code Online (Sandbox Code Playgroud)
  • 如果必须使用If/Else语法,请查看Select Case语句是否更合适.
  • 使用用户定义函数(UDF)而不是重复代码
  • 尽可能避免循环,在使用范围时,几乎总有另一种方法(例如,考虑自动过滤).
  • 使用工作表函数(如果已存在)(例如WorksheetFunction.SumIf()) - 不要重新发明轮子!
  • 查找任何类似的事例.Select并将其删除,您可以直接访问对象的属性和方法而无需选择它.
  • 使用Application.Goto的,而不是.Activate在可能的情况.
  • 当不再需要时从内存中释放对象,例如
    Set myObjectVar = Nothing
  • vbNullString而不是""