如果UDF公式失败,excel vba会保留原始值

在单个单元格中,我有一个引用UDF的分配公式:

=getValueFromWorkbook("OtherWorkbook", 10) 

getValueFromWorkbook UDF粗略地做了像…

 Function getValueFromWorkbook(workbookName As String, identifier As Integer) As Variant ' some magic is done to get the `worksheetName` and `cellRange` ' but for simplicity, we'll just stub them here... Dim worksheetName As String: worksheetName = "SomeWorkSheet" Dim cellRange As String: cellRange = "A1" getValueFromWorkbook = Workbooks("" & workbookName & ".xlsx").Worksheets(worksheetName).Range(cellRange).Value End Function 

这很好,只要OtherWorkbook.xlsx是一个开放的工作簿,单元格获得正确的价值,世界是快乐的。

现在,如果closuresOtherWorkbook.xlsx工作簿,事情将继续发挥作用,并且单元格值仍将反映出来。

但是,如果我删除一行或执行其他一些导致Excel重新计算所有单元格值的操作,则UDF将失败(因为所引用的工作簿不再打开),从而导致可怕的#VALUE!

理想情况下,我想保留原始(陈旧)的价值,而不是返回一个错误,但我还没有想出一个办法做到这一点呢。

我试过了…

 Function getValueFromWorkbook(...) As Variant ... On Error Resume Next getValueFromWorkbook = ... If Err.Number <> 0 Then Err.Clear getValueFromWorkbook = Application.Caller.Value End If End Function 

但是这会导致循环引用错误:

公式中的单元格引用是指公式的结果,创build一个循环引用。

但是,如果我将Application.Caller.Value更改为Application.Caller.Text ,这有点作用,但它返回为文本,我失去了原始值的格式。

所以,长话短说,有没有办法保留原来的链接值,而不是返回一个垃圾#VALUE!

PS我很新的VBA所以可能有一些明显的我在这里失踪。

您可以简单地使用Application.Caller.Text而不是Application.Caller.Value来返回单元格的原始文本。 这样做的一个缺点就是单元格的值,无论types如何 ,都会被当作一个string。 根据其他单元格/公式(例如,如果您希望“OtherWorkbook”返回一个数字而不是string)引用Application.Caller单元格,则可能需要使用=VALUE()更新它们。

只要您不尝试更新实际的单元格中的值,这将工作。 一旦你进入一个单元格, Application.Caller就会变成一个循环引用,你将只返回0 ; 你应该可以删除其他行。

 Function getValueFromWorkbook(...) As Variant Dim Org As String Org = Application.Caller.Text ... On Error Resume Next getValueFromWorkbook = ... If Err.Number <> 0 Then Err.Clear getValueFromWorkbook = Org End If End Function 

怎么样这样的事情:

 ' Globally available variable to cache the external value. Public GlobalValue As Variant Function getValueFromWorkbook(workbookName As String, identifier As Integer) As Variant ' some magic is done to get the `worksheetName` and `cellRange` ' but for simplicity, we'll just stub them here... Dim worksheetName As String: worksheetName = "SomeWorkSheet" Dim cellRange As String: cellRange = "A1" Dim returnValue As Variant ' Attempt to get from the external sheet. ' This will fail if it isn't available. On Error Resume Next returnValue = Workbooks(workbookName & ".xlsx").Worksheets(worksheetName).Range(cellRange).Value If Err = 0 Then ' No error, we retrieved the value from the external file. ' Set it locally for use when this value isn't available. GlobalValue = returnValue Else ' Error - the external sheet wasn't available. ' Use the local value. returnValue = GlobalValue End If ' Done with error trapping. On Error GoTo 0 getValueFromWorkbook = returnValue End Function 

这个想法是你在本地caching值,并可以使用它作为你的workbookName不可用时的后备。