易失性用户定义函数未按预期重新计算 (VBA/Excel)

Volatile User-Defined Function not recalculating as expected (VBA/Excel)

似乎 Application.Volatile 和 ActiveSheet.Calculate 不是我想的那样,我需要帮助创建一个函数,当相关数据发生变化时,它可以正确地重新计算。这是我现在要做的事情:

 Public Function Availability(EmpName As Range)
 Application.Volatile (True)
 ColLetter = Cletter(EmpName.Column)
 Set NameRange1 = Range("$" & ColLetter & ":$" & ColLetter & "$" & (Application.ActiveCell.Row - 1))
 Set SumRange1 = Range(Cletter(Application.ActiveCell.Column) & "1:" & Cletter(Application.ActiveCell.Column) & (Application.ActiveCell.Row - 1))
 Sum1 = Application.SumIfs(SumRange1, NameRange1, EmpName)
 Availability = Sum1
 End Function

正如您所看到的,它需要一个单元格并使用该单元格进行求和以提供条件和条件列,使用函数所在的列对实际数字求和(我知道这似乎就像重新发明轮子,但我只是提出了我的问题的最简单形式)。本质上,它对前一行执行这些计算。

CLetter 只是另一个将 Column# 转换为字母的小函数,因为我懒得调用 R1C1 并发现它更具可读性。

但是每当我更改条件或总和范围,而不是重新计算以考虑标识符或数字的变化时,它似乎忘记了受影响的行存在(即使我只是将其更改为 MATCH条件)或只是抛出一个#VALUE 错误。这可以通过单击“=Availability(A#)”函数并按回车键轻松修复,但我不想编写一个额外的宏来刷新所有这些单元格,因为它们将遍布整个传播sheet .切换波动率有一点帮助,但没有解决问题,也没有为以下 sheet 更改事件添加一些变体:

 Private Sub Worksheet_Change(ByVal Target As Range)
 ActiveSheet.Calculate
 End Sub

当然有一些方法可以让函数在任何单元格发生更改时刷新自身,而不仅仅是它自己的单元格。

首先确保您的计算在选项中设置为自动。如果您的计算设置为自动,则每次它所指的数据发生变化时都会发生变化。

问题的第二部分是您引用了活动单元格。如果您更改数据,您的活动单元格就是刚刚更改的单元格,而不是公式所在的单元格。使用 Application.Caller 指的是调用函数的单元格。

第三次使用Cells而不是调用另一个函数来查找列字母。单元格允许引用数字。

Public Function Availability(EmpName As Range)
Application.Volatile

Set NameRange1 = Range(Cells(1, EmpName.Column), Cells(Application.Caller.Row - 1, EmpName.Column))
Set SumRange1 = Range(Cells(1, Application.Caller.Column), Cells(Application.Caller.Row - 1, Application.Caller.Column))
Sum1 = Application.SumIfs(SumRange1, NameRange1, EmpName)
Availability = Sum1
End Function

恕我直言,使用 Application.Volatile 作为创可贴来忽略 Excel 的重新计算规则是错误的
- 为什么不正确地执行并通过所有范围UDF需要把UDF作为参数吗?
那么您将不需要应用程序 volatile 等,您的工作簿和 UDF 将计算得更干净。

由于计算已经是自动的,重点不是添加更多要定义的参数(即除了 sumif 的标准外,所有参数都是自动的)唯一必要的更改是将 Application.ActiveCell 变为Appplication.ThisCell。 Application.Caller 也可能有效,但这种方式似乎更确定。感谢蒂姆和斯科特的帮助!