vba - 非 volatile UDF总是重新计算

标签 vba excel-2010 user-defined-functions volatile

我正在尝试制作非 volatile UDF,但似乎不可能。因此,这是我非常简单的test-UDF:

Option Explicit
Dim i As Integer

Sub Main()

i = 0
[A1] = "zyy"
MsgBox i

End Sub

Function Test(rng As Range)
Application.Volatile (False)

Test = rng.Value
i = i + 1

End Function

我得到了一个空的工作表,该工作表使用了此函数几次,并且每次我调用Main()并使用UDF更改工作表上的任何单元格时,它们都将重新计算。如何使这个(任何)UDF非 volatile ? Application.Volatile(False)应该具有这种效果,但显然不起作用。

编辑:如果我手动更改单元格,则其工作原理与预期的一样,仅当我通过VBA更改单元格时,它才会重新计算。这是正常行为还是可以更改?

最佳答案

我正在发布一个新的答案,而不是试图挽救我以前的答案,即使我认为他们指向的是同一件事,也最好重新开始。

背景:

以前,我已经测试过您的代码,并且如果您仅从该语句中省略False,结果将完全符合我的预期。我从未见过任何理由明确地执行Application.Volatile (False),因为这等同于完全省略该语句。

  • 如果省略,则该函数是非 volatile 的,UDF仅在引用更改时(即,其他非引用单元格更改时,而不是)求值。
  • 如果作为Application.Volatile(或Application.Volatile (True))包含在内,则UDF会变得不稳定,并且对工作表的任何更改
    将强制进行重新评估。

  • 继续调查

    您评论说,您仍然观察到其他情况。因此,我对代码进行了一些更改,然后再次进行了测试。突然发生了奇怪的事情。无论我对Application.Volatile函数进行了什么操作,对工作表的任何更改都将重新评估UDF。

    这没有任何意义,所以我开始进行谷歌搜索并进行更多测试。

    在测试中,我创建了三个函数。
  • 第一个明确地是Volatile:
  • 第二个是,而不是volatile
  • 第三个省略任何波动性陈述。

  • 我将每个公式的一个实例放在工作表上。每个都引用了不同的范围。

    我通过手动更改工作表并通过命名子例程来测试了每一个。我使用了Print语句并监视了VBE中的“即时”窗口,以确认在所有情况下,这些函数仅按预期进行了评估(或未评估)。第一个始终评估,而第2个和第3个仅在引用范围更改时评估。
    Function f_appvol(rng As Range)
    
    Application.Volatile
    Debug.Print "f_appvol"
    
    f_appvol = rng.Value
    End Function
    
    Function f_appNOTvol(rng As Range)
    Application.Volatile (False)
    Debug.Print "f_appNOTvol"
    
    f_appNOTvol = rng.Value
    End Function
    
    Function f_omit(rng As Range)
    
    Debug.Print "f_omit"
    f_omit = rng.Value
    
    End Function
    

    然后变得很奇怪...

    我开始在这些函数中进行更改,并且它们开始表现得很奇怪。

    具体来说,我很幸运,并注意到,如果我将非 volatile 函数更改为 volatile 函数,那么所有函数便开始表现为好像是 volatile 的,即使是f_omit。我相信这可能是您遇到的情况。

    通过某种方式,我们设法“混淆”了Excel

    我保存了工作簿,然后再次尝试...恢复正常!

    然后,我在volatile语句中更改了参数,然后再次发生了奇怪的行为。

    这似乎是一个错误

    我没有看到in the documentation暗示这是正常/预期的行为,并且从调试的角度来看,它肯定不是理想的行为。这种事情会让您沮丧地拔头发!

    我正在使用Excel 2010,Win 7 64b。

    分辨率

    错误的原因似乎正在改变UDF的波动性。

    为了恢复预期的行为,似乎有必要保存工作簿。再次,我认为这不是正常现象,但这似乎可以解决您的问题(或者至少是我在对您的问题进行故障排除时能够复制的非常相似的问题)。

    关于可能的相关注释

    here所述,似乎至少有一个与波动相关的错误。我链接到它的主要原因是,该作者反射(reflect)了我自己的观点:没有理由进行Application.Volatile (False),因为这是(或应该是)UDF的“正常”状态。

    I have to admit that I had never seen the point of using Application.Volatile False since thats supposed to be what you get if you omit the Application.Volatile statement altogether.

    关于vba - 非 volatile UDF总是重新计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24353506/

    相关文章:

    vba - 不使用.activate/.select 编写程序。编程语言

    Excel VBA循环遍历单元格并替换它们的值

    excel - 根据金额条件过滤数据透视表中的总计

    apache-flink - Apache Flink 1.14.0 - 无法通过 Java 中的 SQL DDL 使用 python UDF

    python - 强制 python 脚本不等待 vba 宏终止

    excel - 列中的每个新值自动乘以 X

    ms-access - 如何摆脱VBA安全警告

    excel - VBA:粘贴具有不同名称的图表

    arrays - Excel:将数组传递给用户定义函数 (VBA)

    sql - 带有 OUT 参数的 PostgreSQL 函数和带有 TABLE 结果的 PostgreSQL 函数之间有任何形式上的区别吗?