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

时间:2015-04-23 06:13:23

标签: excel vba volatility 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. 在工作表中的任何位置添加新单元格或列(但不是行)。
  2. 请注意,手动计算模式在多个方面都不是一个选项。

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

    其次,我实际上并没有设计一个特定的电子表格,而是正在编写一本关于非开发人员如何利用写得很好的现成代码(如UDF)来做其他事情的工作。 。示例包括动态连接或拆分文本,或查尔斯威廉姆斯在https://fastexcel.wordpress.com/2011/07/22/developing-faster-lookups-part-2-how-to-build-a-faster-vba-lookup/概述的完全匹配二进制搜索UDF(是的,我给他们很多警告,通常基于公式的原生解决方案将胜过UDF。但是正如你和#39;从上面引用的主题中看,精心编写的函数可以很好地执行。)

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

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

2 个答案:

答案 0 :(得分:5)

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


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

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

答案 1 :(得分:0)

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

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

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

不可否认,这不是编写UDF的常用(和推荐)方法。它通常应取决于内容(值)而不是容器(范围)。

我在这里只是返回参数的地址。我还附加一个时间戳来指示何时重新计算UDF。如果删除工作表上的任何列,则会重新计算具有此UDF的所有单元格。但是,如果插入一列,则不会保留右侧(此新列)的单元格,并使用错误的值(单元格地址)。插入/删除行的结果相同。奇怪的是,插入单个单元格会强制重新计算所有UDF。

我试图删除"依赖"在Range上。但即使UDF的参数被键入as double(而不是像我的例子中那样将其保留为Variant),行为也是相同的。

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