当不相关的单元格被删除时,需要停止UDF的重新计算

我注意到,我删除单元格时,我的UDF重新计算。 这会在删除整个列时造成大量延迟,因为UDF会针对所使用的每个单元格进行调用。因此,如果您使用的是1000个UDFS,那么删除列或单元格将调用它1000次。

举个例子,把下面的UDF放到一个模块中,然后用工作表调用一堆= HelloWorld()

Function HelloWorld() HelloWorld = "HelloWorld" Debug.Print Now() End Function 

然后删除一行。 如果你的经验和我的一样,你会看到每调用一次就会调用一次。

任何人有任何想法,这种行为是否可以停止? 我也有兴趣为什么它应该被调用。 看起来像Excel的依赖树中的一个缺陷给我,但可能有一个很好的理由。

编辑:经过实验,我发现了更多触发UDFS的操作:

  1. 对ListObject(即Excel表)跨越大小(但不包括行)的数进行的任何更改。 即使UDF本身不在相关的ListObject中,或者实际上也不在任何 ListObject中。
    1. 在工作表中的任何位置添加新的单元格或列(但不包括行)。

请注意,手动计算模式不是几个方面的选项。

首先,鉴于这是一个应用程序级别的设置,它只是performance出太大的风险,即有人会使用任何一个电子表格的输出,而没有意识到他们处于手动计算模式。

其次,我实际上并没有devise特定的电子表格,而是写了一本关于非开发人员如何使用良好编写的现成代码(如UDF)来做本来不可能的事情的书。 例子包括dynamic连接或分割文本,或Charles Williams在https://fastexcel.wordpress.com/2011/07/22/developing-faster-lookups-part-2-how-to- build-a-faster-vba-lookup / (是的,我给了他们很多警告,通常一个基于本地公式的解决scheme将胜过UDF,但正如你从上面提到的线程中看到的那样,可以performance良好)。

我不知道用户如何使用这些。

在没有编程解决scheme的情况下,看起来我只需在本书中指出,如果用户使用资源密集型UDFS,添加或删除单元格或调整ListObjects的大小时,用户可能会遇到显着的延迟。 即使这些UDF被有效地写入。

不幸的是,我不相信当“不相关的”单元被删除时,可以防止重新计算UDF。 原因是传递给UDF的参数实际上是一个Range对象(不只是单元格内的值)。 删除“无关”的单元格实际上可以修改Range

例如,用户可以编写这种UDF:

 Function func1(rng) func1 = rng.Address & " (" & Format(Now, "hh:mm:ss") & ")" End Function 

诚然,这不是编写UDF的常用(并推荐)方法。 它通常应该取决于内容(价值)而不是容器(范围)。

这里我只是返回参数的地址。 我还附加了一个时间戳,以便在重新计算UDF时发出信号。 如果删除工作表上的任何列,则重新计算具有此UDF的所有单元格。 但是,如果您插入一列,而不是保持右侧(这个新列)右侧的单元格和错误的值(单元格地址)。 结果与插入/删除行相同。 奇怪的是,插入一个单元格会强制重新计算所有的UDF。

我试图去除Range上的“依赖”。 但是,即使UDF的参数被inputas double (而不是像我的示例中那样将其保留为Variant),行为也是一样的。

正如你所解释的那样,删除一列将强制重新计算UDF。 这是有道理的,因为UDF 可以依赖于Range参数。 对于UDF来说这是一个聪明的devise是另一回事。

插入或删除行或列或单元格将始终在自动模式下触发重新计算。 (您可以通过将= NOW()添加到空白工作簿并插入或删除东西来检查)

问题应该是什么(意外的)情况下标记一个单元格为脏,以便它被重新调用。 在http://www.decisionmodels.com/calcsecretsi.htm有一个(可能不完整的)这样的列表

看起来我需要添加一些关于VBA UDF的话(还没有testing过XLL UDF
– 由于它们以与VBA UDF不同的方式注册,因此可能会有所不同)