Excel – 用户定义的函数即使在不活动时也被调用

我有一个用户定义的函数在Excel中。 该函数在顶部包含Application.Volatile,并且效果很好。

我现在遇到的问题是,当我打开工作簿(让它称为工作簿1)和另一个工作簿(称为工作簿2)时,每次对工作簿2进行更改时,工作簿1中调用此方法的所有单元UDF获得#VALUE! 错误。 为什么发生这种情况?

我希望我提供了足够的信息。 如果不是,请让我知道。 谢谢大卫

嗨,大家好,谢谢你的帮助。 对不起,这是…这是代码:

Function getTotalReceived(valCell As Range) As Variant Application.Volatile If ActiveWorkbook.Name <> "SALES.xlsm" Then Return Dim receivedWs As Worksheet, reportWs As Worksheet Dim items As Range Set reportWs = Worksheets("Report") Set receivedWs = Worksheets("Received") Dim myItem As String, index As Long myItem = valCell.Value Set items = receivedWs.Range("A:A") index = Application.Match(myItem, items, 0) If IsError(index) Then Debug.Print ("Error: " & myItem) Debug.Print (Err.Description) GoTo QuitIt End If Dim lCol As Long, Qty As Double, mySumRange As Range Set mySumRange = receivedWs.Range(index & ":" & index) Qty = WorksheetFunction.Sum(mySumRange) QuitIt: getTotalReceived = Qty End Function 

 Function getTotalReceived(valCell As Range) As Variant Application.Volatile Dim index, v, Qty v = valCell.Value 'do you really need this here? If ActiveWorkbook.Name <> ThisWorkbook.Name Then Exit Function If Len(v) > 0 Then index = Application.Match(v, _ ThisWorkbook.Sheets("Report").Range("A:A"), 0) If Not IsError(index) Then Qty = Application.Sum(ThisWorkbook.Sheets("Received").Rows(index)) Else Qty = "no match" End If Else Qty = "" End If getTotalReceived = Qty End Function 

您的问题是在您的UDF中使用ActiveWorkbookActiveWorksheetActiveCell或其他Active_____对象。 注意Application.Volitile是一个应用程序级属性。 每当您切换图纸,书籍,单元格,图表等时,对应的“活动”对象都会改变。

作为适当的UDF编码实践的一个例子,我把这个简短的例子放在一起:

 Function appCallerTest() As String Dim callerWorkbook As Workbook Dim callerWorksheet As Worksheet Dim callerRange As Range Application.Volatile True Set callerRange = Application.Caller Set callerWorksheet = callerRange.Worksheet Set callerWorkbook = callerWorksheet.Parent appCallerTest = "This formula is in cell: " & callerRange.Address(False, False) & _ " in the sheet: " & callerWorksheet.Name & _ " in the workbook: " & callerWorkbook.Name End Function 

你的function实际上有2个错误。 第一个是由Mascaro先生部分解决 – 你需要使用传递给该函数的Range引用来parsing它所来自的工作簿。 您可以通过向下钻取父属性来完成此操作。

第二个问题是,您正在testing以查看Application.Match是否使用IsError函数返回了有效的index 。 这不是在做你认为正在做的事情 – IsError检查是否另一个单元格的函数返回了一个错误,而不是前一行。 事实上,如果Application.Match产生一个错误,它在你的函数中,所以你必须处理它。 我相信你需要捕捉的错误是types不匹配(错误13)。

这应该解决这两个问题:

 Function getTotalReceived(valCell As Range) As Variant Application.Volatile Dim book As Workbook Set book = valCell.Parent.Parent If book.Name <> "SALES.xlsm" Then Exit Function Dim receivedWs As Worksheet, reportWs As Worksheet Dim items As Range Set reportWs = book.Worksheets("Report") Set receivedWs = book.Worksheets("Received") Dim myItem As String, index As Long myItem = valCell.Value Set items = receivedWs.Range("A:A") On Error Resume Next index = Application.Match(myItem, items, 0) If Err.Number = 13 Then GoTo QuitIt On Error GoTo 0 Dim lCol As Long, Qty As Double, mySumRange As Range Set mySumRange = receivedWs.Range(index & ":" & index) Qty = WorksheetFunction.Sum(mySumRange) QuitIt: getTotalReceived = Qty End Function