Excel索引与偏移/间接 - 我不明白为什么偏移/间接在这种情况下更快

时间:2011-06-27 17:30:51

标签: excel vba optimization reference excel-formula

我有一个工作簿设置,其中第一个选项卡包含参数列表。每列是一组不同实例的参数。

然后我有一个实例的模板表,用户制作了这个模板的许多副本。模板所做的一件事是动态地从第一张表中提取参数。用户输入列号(1到n),并从第一个工作表中提取该列参数以在该实例上使用。然后,该实例使用这些参数运行了数十万行计算。

参数表

enter image description here

示例实例

enter image description here

我的问题似乎与波动性有关。对于大量实例,如果我使用offset或indirect来获取参数,则工作簿中任何单元格的任何更改都会导致在每个实例工作表上重新检索参数,因此每个工作表每次都会重新计算,每当进行更改时冻结工作簿约3秒钟。

我认为我可以通过使用索引减少这一点。每个工作表的参数引用包含该参数的第一个工作表上的行,并将要拉出的列编号作为索引参数。这解决了导致重新计算的任何变化的问题。现在只有参数范围的变化会导致重新计算,但由于某种原因,它会更糟糕。

现在,更改工作簿中的随机单元格不再导致整个事件在重新计算时冻结3秒,但更改参数范围中的相关单元格将导致每个工作表重新计算,大约需要10秒钟。为什么这种方法要慢得多。它应该在技术上与以前做同样的事情,只是在相关参数发生变化时。

有没有办法设置它,以便在更改前页上的参数时,只有受参数影响的工作表重新计算?

解决方案

我考虑过涉及VBA的复杂解决方案,因此复制模板实例会监视其“实例编号”单元格。当它被更改时,VBA代码可以将相应的参数复制到工作表并在此处硬拷贝值。我还需要VBA监控主参数表上的更改事件。当任何内容发生变化时,必须检查列号,迭代所有模板,并在引用该实例编号时重新复制值。我想避免使用这种解决方案,因为通常的原因是将VBA保持在等式之外,但如果没有办法让excel重新计算变得更加明智,那么可能是必要的。

2 个答案:

答案 0 :(得分:5)

这是一个旧的Excel宏技巧仍然有效:

  • 关闭自动重新计算
  • 选择要重新计算的所有单元格
  • 使用替换功能将=替换为=
  • 这只会迫使那些特定的细胞重新计算。

将此作为宏录制并定期执行非常容易。

答案 1 :(得分:5)

问题是由使用Index函数将Param#值填充到Instance表上引起的。

在任何实例行上更改Param 1Main的值时,该范围将标记为已更改。由于每个实例表都引用其参数1值查找的此范围,因此所有param 1值都标记为已更改。然后,在所有工作表上引用Iteration #的所有Param 1公式都会标记为已更改。

不知道这会对您的工作簿设计产生什么影响,但请考虑将索引查找更改为直接单元格引用。例如,在实例1单元格D3上:=Main!B2

在准备此答案时,我设置了一个带有工作簿事件的文本来报告工作表重新计算

Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
    MsgBox "Calc Sheet " & Sh.Name
End Sub

我使用Index,Offset和其他人对各种查找进行了一些实验,但找不到一个不会导致所有工作表重新计算的实验(不是详尽的搜索,因此其他人可能能够提供解决方案)。我发现的唯一一个没有导致所有工作表计算的是直接单元格引用

帮助设置维护实例表参数引用的VBA例程可能是有序的......