如何在Excel VBA中更好地pipe理内存以防止macros变慢?

背景

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

在进行更改之前,运行此报告以模拟用户input每个用户需要大约65秒(并且大约有4,300个用户)。 这出来了279,500秒(大约77.6小时)。 这是假定一个恒定的速度,macros观开始的速度相同。 事实并非如此。 实际上,这个macros在夜间和夜间进行处理的速度相当缓慢,而且每个用户的时间都超过了120秒。

问题

在我的代码清理和性能改进之后,我得到了每个用户10秒左右的启动macros,这是一个很好的速度。 我昨天晚上让macros观运行一夜,然后在今天上午看到现在每个用户需要花费大约90秒的时间,所以我在一夜之间performance了很大的性能下降。

我的问题是:如何防止macros随时间stream逝而发生减速?

研究

我不是没有想法。 目前,我的想法是,我需要closures和重新打开Excel工作簿,因为他们陷入了垃圾。 我有一个想法是也许使用本地VB.NET应用程序来打开Excel工作簿并运行macros。 每500名左右的用户,我可以在工作簿中的单元格某处写入相关的variables,保存并closures工作簿,然后重新打开它以提取我离开的位置。 这对我来说似乎不是很优雅。 另外,说服别人需要引入“新”技术(VB.NET)可能是困难的。 人们对此很奇怪,更喜欢本地的VBA解决scheme。

有没有更好的方法来pipe理Excel,以便我不必创build一个新的VB.NET应用程序,并执行保存/closures/打开?

我想补充一点,没有特定的违规代码,随着时间的推移,它只会变慢(仍然有效)。

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

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

上面的一个注释,总是与你的代码将失败,并确保一个适当的error handling程序,以重置这些设置回到他们的默认值


  • 使用DoEvents将控制权重新返回给处理器,可能会有一些需要完成的过程来释放资源。
  • 尽可能使用直接布尔比较。

代替:

 If someVar > 5 Then boolVar = True Else boolVar = False End If 

考虑使用

 boolVar = someVariable > 5 
  • 如果必须使用If / Else语法,请查看Select Case语句是否更合适。
  • 使用用户定义的函数(UDF)而不是重复代码
  • 总是尽量避免循环,在使用范围时,几乎总是有另一种方式(例如考虑AutoFilter)。
  • 使用工作表函数(如WorksheetFunction.SumIf() ) – 不要重新发明轮子!
  • 查找类似的东西的任何实例。select并摆脱,您可以直接访问对象的属性和方法,而无需select它。
  • 使用Application.Goto代替.Activate在可能的情况下。
  • 当内存不再需要的时候从内存释放对象,例如
    Set myObjectVar = Nothing
  • 使用vbNullString而不是""