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

jef*_*eir 5 excel vba volatility udf

我注意到,每当我删除单元格时,我的UDF都会重新计算.这会在删除整个列时导致大量延迟,因为UDF会为其使用的每个单元调用.因此,如果您使用1000 UDFS,则删除列或单元将调用1000次.

举例来说,将以下UDF放在一个模块中,然后使用= HelloWorld()从工作表中多次调用它

Function HelloWorld()
HelloWorld = "HelloWorld"
Debug.Print Now()
End Function
Run Code Online (Sandbox Code Playgroud)

然后删除一行.如果您的体验与我的一样,您会看到每次使用都会调用一次.

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

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

  1. ListObject(即Excel表)跨越调整大小(但不是行)的数的任何更改.即使UDF本身不在ListObject中,或者实际上在任何 ListObject中也是如此.
    1. 在工作表中的任何位置添加新单元格或列(但不是行).

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

第一,鉴于它是一个应用程序级别的设置,它只会带来太大的风险,即有人会使用他们碰巧打开的任何一个电子表格的输出,而不会意识到它们处于手动计算模式.

其次,我实际上并没有设计一个特定的电子表格,而是正在编写一本关于非开发人员如何利用编写良好的现成代码(如UDF)来执行本来可能超出他们的事情的书.示例包括动态连接或拆分文本,或Charles Williams概述的完全匹配二进制搜索UDF,请参阅https://fastexcel.wordpress.com/2011/07/22/developing-faster-lookups-part-2-how-to- build-a-faster-vba-lookup / (是的,我给他们很多警告,通常一个基于公式的原生解决方案将胜过UDF.但正如你从上面引用的线程中看到的那样,仔细编写函数可以表现得很好).

我不知道用户将如何使用这些.

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

Cha*_*ams 5

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


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

看起来我需要添加一些关于VBA UDF的文字(尚未测试XLL UDF
- 它们可能表现不同,因为它们以不同的方式注册到VBA UDF)


bou*_*err 0

不幸的是,我不认为在删除“不相关”单元格时可以阻止重新计算 UDF。原因是传递给 UDF 的参数实际上是一个Range对象(而不仅仅是单元格内的值)。删除“不相关”的单元格实际上可以修改Range.

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

Function func1(rng)
    func1 = rng.Address & " (" & Format(Now, "hh:mm:ss") & ")"
End Function
Run Code Online (Sandbox Code Playgroud)

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

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

我试图删除对Range. 但即使输入了 UDF 的参数,行为也是相同的as double(而不是像我的示例中那样将其保留为变体)。

正如您所解释的,删除列将强制重新计算 UDF。这是有道理的,因为 UDF可以依赖于Range参数。这是否是 UDF 的明智设计是另一回事。