如何在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
而不是""