用户在Excel中定义的函数和速度问题

我有一个使用几乎所有UDF的Excel模型。 有说120列,400多行。 计算是垂直进行的,然后进行水平方向—即首先完成第一列的所有计算,然后第一列的最后输出是第二列的input等。在每一列中,我称之为六个或七个UDF调用其他UDF。 UDF经常输出一个数组。

每个UDF的input是一些variables,一些范围variables,一些双打。 在访问内容之前,范围variables在内部被转换为数组。

我的问题是,我可以build立没有UDF的Excel模型,当我运行模拟时,我可以在X小时内完成所有的计算。 当我使用UDF时,仿真时间是3X小时或更长。 (为了回答这个显而易见的问题,是的,我需要和UDF一起工作,因为如果我想对模型做一些小的修改(比如说添加另一个资产types(这是一个财务模型)),重build模型需要将近一天的时间没有UDF来适应新的法律/金融结构,UDF需要大约20分钟来适应不同的财务结构。)

在任何情况下,我已closures屏幕更新,没有复制和粘贴的function,Varianttypes的使用是最小的,所有的数据都包含在一张表中,我将所有范围typesvariables数组之前,获取内容。

除了让一台速度更快的计算机或等价物使VBA代码/ Excel文件运行得更快之外,我还能做些什么? 请让我知道这是否需要更多的澄清。

谢谢!

一般技巧夫妇。

  1. 采取你的function,并找出瓶颈真正的地方。 看到这个问题在Excel中使用计时器 。 我确定那里有VBA分析器…但是你可能不需要那么远。 (注意:先用一个数据单元做这个…)

  2. 想想你的devise… 400×120的数据单元不是很多。 而这需要花费数小时,这一定是痛苦的。 ( 在过去我已经破解了一千分之一的VLOOKUPS()返回 ),反正可能而不是有一堆的UDFs为什么没有一个简单的子程序, for..each通过范围,做什么你需要它做。 48,000个细胞可能需要几秒钟,也可能只有几分钟。 然后,您可以将子例程与用户的button或菜单项相关联。

出于兴趣,我快速浏览了选项2,并创build了MyUDF(),使用子DoMyUDF()来调用它,使得对于我来说工作速度快10倍,而不是在每个单元中都有UDF。

 Option Explicit Function MyUDF(myVar As Variant) As Variant MyUDF = myVar * 10 End Function Sub DoMyUDF() Dim r As Range Dim c As Variant Dim t As Single t = Timer If TypeName(Selection) <> "Range" Then Exit Sub End If Set r = Selection.Cells Application.DisplayStatusBar = True For Each c In r c.Value = MyUDF(c.Value) Application.StatusBar = "DoMyUDF(): " & Format(Timer - t, "#0.0000ms") Next Debug.Print "DoMyUDF(): " & Format(Timer - t, "#0.0000ms") End Sub 

如果你用你的UDFreplaceMyUDF() ,这可能只会节省你4.5分钟…但是可能还有一些其他的经济体可以build立。特别是如果你一遍又一遍地重复相同的计算。

你有没有考虑用一个macros来替代UDF(每个输出单元调用一次),macros可以在循环中的一系列单元上运行?

UDF设置/拆卸非常缓慢,每个UDF调用与其他UDF(例如,从重叠input中读取)共同执行的任何操作都变得非常费力。

我已经能够提高性能10-50倍这样做 – 有一个情况不到一个月前涉及电子表格4000-30000 UDF调用,取而代之的是一个单一的macros,在几个命名范围上运行。

Excel处理UDF的方式有一个缓慢的错误。 每次计算UDF时,Excel将刷新VBE标题栏(可以看到它闪烁)。 对于大量的UDF,这是非常缓慢的。 手动计算模式中的旁路非常简单:只需使用Application.Calculate(您可以使用OnKey捕捉F9等)从VBA启动计算。

有关更多详细信息,请参阅http://www.decisionmodels.com/calcsecretsj.htm

控制和最小化重新计算

 wks.EnableCalculation = False 

要么

 Application.Calculation = xlCalculationManual 

另外,尽量减lessVBA和工作簿之间的交stream。 一次读取和写入一个单元格到一个数组会更快

 MyArray = range("B2:B20000") 

而不是逐个单元格(对于每个…)。

请确保您从VBA开始重新计算,而不是从电子表格开始,请参阅http://msdn.microsoft.com/zh-cn/library/aa730921.aspx#Office2007excelPerf_Overview以及有关更快的VBA用户定义函数的部分&#x3002; 这就是Application.Calculate比在电子表格中按F9快得多(在我的testing用例中是100次)。