簡體   English   中英

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

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM