如果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
不可用时的后备。