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

易失性用户定义函数未按预期重新计算(VBA/Excel),vba,excel,volatile,udf,Vba,Excel,Volatile,Udf,看起来Application.Volatile和ActiveSheet.Calculate并不是我想象中的那样,我需要帮助创建一个在相关数据更改时正确重新计算的函数。我现在要做的是: Public Function Availability(EmpName As Range) Application.Volatile (True) ColLetter = Cletter(EmpName.Column) Set NameRange1 = Range("$" & ColLetter

看起来Application.Volatile和ActiveSheet.Calculate并不是我想象中的那样,我需要帮助创建一个在相关数据更改时正确重新计算的函数。我现在要做的是:

 Public Function Availability(EmpName As Range)
 Application.Volatile (True)
 ColLetter = Cletter(EmpName.Column)
 Set NameRange1 = Range("$" & ColLetter & "$1:$" & 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
如您所见,它使用一个单元格,并使用该单元格进行sumifs,以提供条件和条件列,使用函数所在的列对实际数字进行求和(我知道这看起来像是重新发明轮子,但我只是提出了问题的最简单形式)。它基本上在前一行的每一行上执行这些计算

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

但是,每当我更改标准或总和范围时,它似乎忘记了受影响的行存在(即使我只是更改它以匹配标准),或者只是抛出一个#值错误,而不是重新计算以说明标识符或数字的更改。通过点击“=Availability(A#)”函数并点击回车键可以很容易地解决这个问题,但我不希望在电子表格中出现这些单元格时,编写额外的宏来刷新所有这些单元格。切换波动率有一点帮助,但没有解决问题,也没有在下面的工作表更改事件中添加一些变体:

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

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

首先确保您的计算在选项中设置为自动。如果您的CALC设置为自动,则每次更改其引用的数据时,该选项都会更改


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

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

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

首先确保在选项中将计算设置为自动。如果您的CALC设置为自动,则每次更改其引用的数据时,该选项都会更改


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

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

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重新计算规则的bandaid是错误的
-为什么不正确地使用Application.Volatile并将UDF需要的所有范围作为参数传递给UDF
这样您就不需要应用程序volatile等,您的工作簿和自定义项计算起来会更清晰。

我认为使用application.volatile作为忽略Excel的重新计算规则的绷带是错误的。
为什么不正确地做,并将自定义项需要的所有范围作为参数传递给自定义项呢
这样,您就不需要应用程序volatile etc,您的工作簿和UDF的计算也会更加清晰。

因为计算已经是自动的,关键是不需要添加更多要定义的参数(即,除了sumif的标准外,所有参数都是自动的)唯一必要的更改是将Application.ActiveCell改为appapplication.ThisCell。调用方可能也工作过,但这种方式似乎更确定。谢谢你的帮助,蒂姆和斯科特

由于计算已经是自动的,并且重点不是添加更多要定义的参数(即,除了sumif的标准之外,所有参数都是自动的),所以唯一需要的更改是将Application.ActiveCell转换为appapplication.ThisCell。调用方可能也工作过,但这种方式似乎更确定。谢谢你的帮助,蒂姆和斯科特

部分问题是您正在引用活动单元格。如果更改数据,则活动单元格是刚刚更改的单元格,而不是公式所在的单元格。“每当工作表上的任何单元格中发生计算时,必须重新计算易失性函数。”-如果正在更改的单元格未被任何公式引用,则编辑不会触发任何计算。您可以尝试添加一个引用正在更改的单元格的“伪”公式-这应该足以触发重新计算。如果您是对的,Scott,我曾考虑过这可能是一个问题,但无法找到一种无参数的方法来查找函数调用所在的行和列,它需要(不是手动输入,我的意思是)。你知道我怎么能从函数内部引用“这个单元格”吗?可能是间接的?试试
工作表\u SelectionChange
应用程序如何。此单元格将执行您想要的操作,或
应用程序。调用方
Scott使用时,问题的一部分是您正在引用活动单元格。如果更改数据,则活动单元格是刚刚更改的单元格,而不是公式所在的单元格。“每当工作表上的任何单元格中发生计算时,必须重新计算易失性函数。”-如果正在更改的单元格未被任何公式引用,则编辑不会触发任何计算。您可以尝试添加一个引用正在更改的单元格的“伪”公式-这应该足以触发重新计算。如果您是对的,Scott,我曾考虑过这可能是一个问题,但无法找到一种无参数的方法来查找函数调用所在的行和列,它需要(不是手动输入,我的意思是)。你知道我怎么能从函数内部引用“这个单元格”吗?可能是间接的?试试
工作表\u selection change