[英]excel vba preserve original value if UDF formula fails
在单个单元格中,我有一个引用 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
是一个打开的工作簿,单元格就会获得正确的值,世界就会快乐。
现在,如果我关闭OtherWorkbook.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
但这会导致循环引用错误:
公式中的单元格引用引用公式的结果,从而创建循环引用。
但是,如果我将Application.Caller.Value
更改为Application.Caller.Text
,这有点有效,但它以文本形式返回并且我丢失了原始值格式。
因此,长话短说,有没有办法保留原始链接值而不是返回垃圾#VALUE!
?
PS 我对 VBA 还很陌生,所以我在这里可能遗漏了一些明显的东西。
您可以简单地使用Application.Caller.Text
而不是Application.Caller.Value
来返回单元格的原始文本。 这样做的一个缺点是单元格的值,无论类型如何,都将被转换为字符串。 根据引用Application.Caller
单元格的其他单元格/公式(即,如果您希望“OtherWorkbook”返回数字而不是字符串),您可能必须使用=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
这个想法是您在本地缓存该值,并可以在您的workbookName
不可用时将其用作后备。
我找到了一种方法:
假设您将用户定义的函数UDF放入单元格A1 中,并且在某些条件下希望它保留以前的值而不重新计算。 然后在这种情况下使此函数返回任何错误值: UDF = CVErr(xlErrNull)
并按以下方式修改您的A1公式: =IFERROR(UDF(...); A1)
这可能会产生循环引用警告 - 您可以通过在文件 -> 选项 -> 公式中启用循环引用并使用此设置保存文件来摆脱它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.