簡體   English   中英

VBA中的循環參考錯誤?

[英]Circular Reference Error in VBA?

我正在嘗試在Excel中編寫一個函數來計算默認概率。 我有一個包含3列數據的電子表格。 我希望能夠突出顯示一組數據,並讓該函數返回基於我突出顯示的數據的值。

該函數從電子表格中讀取數據,然后使用該數據執行迭代過程(牛頓法)。 我正在嘗試使代碼引用電子表格中所選數據的第一行,即第一個“ i”。 然后對於第二個i,我希望它引用第二行,依此類推。 到目前為止,我已經知道了:

iNumRows = Table.Rows.Count

maturity = Worksheets("KMV-Merton").Range("B2").Value
For i = 1 To iNumRows
    equity(i) = SelectedRange.Cells("1").Offset(i - 1, 0).Value
    debt(i) = SelectedRange.Cells("2").Offset(i - 1, 0).Value
    riskFree(i) = SelectedRange.Cells("3").Offset(i - 1, 0).Value
Next i

但這會導致電子表格上出現循環引用錯誤。 我究竟做錯了什么?

完整的代碼如下,以防錯誤在其他地方。

Option Explicit
    Private Const mMax = 10000
    Public maturity As Double
    Private equity(1 To mMax) As Double
    Private debt(1 To mMax) As Double
    Private riskFree(1 To mMax) As Double
    Private iptr As Integer
    Public sigmaAssetLast As Double



Function VarunModel(Table As Range, Optional EndCondition As Integer = 0) As Variant
    Dim iNumCols As Integer, iNumRows As Integer
    Dim i As Integer

    Dim SelectedRange As Range
    Set SelectedRange = Selection

    iNumCols = Table.Columns.Count
    iNumRows = Table.Rows.Count

    maturity = Worksheets("KMV-Merton").Range("B2").Value
    For i = 1 To iNumRows
        equity(i) = SelectedRange.Cells("1").Offset(i - 1, 0).Value
        debt(i) = SelectedRange.Cells("2").Offset(i - 1, 0).Value
        riskFree(i) = SelectedRange.Cells("3").Offset(i - 1, 0).Value
    Next i

    Dim equityReturn As Variant: ReDim equityReturn(2 To iNumRows)
    Dim sigmaEquity As Double
    Dim asset() As Double: ReDim asset(1 To iNumRows)
    Dim assetReturn As Variant: ReDim assetReturn(2 To iNumRows)
    Dim sigmaAsset As Double, meanAsset As Double
    Dim x(1 To 1) As Double, n As Integer, prec As Double, precFlag As Boolean, maxDev As Double

    For i = 2 To iNumRows: equityReturn(i) = Log(equity(i) / equity(i - 1)): Next i
        sigmaEquity = WorksheetFunction.StDev(equityReturn) * Sqr(260)
        sigmaAsset = sigmaEquity * equity(iNumRows) / (equity(iNumRows) + debt(iNumRows))
    NextItr: sigmaAssetLast = sigmaAsset

    For iptr = 1 To iNumRows
        x(1) = equity(iptr) + debt(iptr)
        n = 1
        prec = 0.00000001
        Call NewtonRaphson(n, prec, x, precFlag, maxDev)
        asset(iptr) = x(1)
    Next iptr

    For i = 2 To iNumRows: assetReturn(i) = Log(asset(i) / asset(i - 1)): Next i

    sigmaAsset = WorksheetFunction.StDev(assetReturn) * Sqr(260)
    meanAsset = WorksheetFunction.Average(assetReturn) * 260
    If (Abs(sigmaAssetLast - sigmaAsset) > prec) Then GoTo NextItr

    Dim disToDef As Double: disToDef = (Log(asset(iNumRows) / debt(iNumRows)) + (meanAsset - sigmaAsset ^ 2 / 2) * maturity) / (sigmaAsset * Sqr(maturity))
    Dim defProb As Double: defProb = WorksheetFunction.NormSDist(-disToDef)

    VarunModel = defProb        
End Function

不要在功能中使用Selection 使用它會導致在您在工作表中輸入公式的那一刻,單元格便會引用自身。 這是您的循環參考。

您需要刪除這兩行。

Dim SelectedRange As Range
Set SelectedRange = Selection

相反,您需要包括SelectedRange作為公式的參數。

Function VarunModel(ByVal Table As Range, ByVal SelectedRange As Range, Optional ByVal EndCondition As Integer = 0) As Variant

然后在單元格中輸入這樣的公式。

=VarunModel(A3:C18,A5:C6)

第二個參數是您的“選定”范圍。 關鍵是它不再完全取決於選擇。 相反,您可以明確告訴它要用於計算的范圍。

這可能不是您想要的行為,但是您需要避免在函數中使用Selection

如果您確實要在代碼中使用Selection ,則需要創建一個Sub來調用函數。 您將需要在代碼中指定輸出范圍。

在工作表上創建一個按鈕以運行此代碼:

Sub outputVarunValue()
    Dim Table As Range
    Dim OutputCell As Range

    'need range name "TableRange"
    Set Table = Worksheets("KMV-Merton").Range("TableRange")

    'need single cell with range name "OutputCell"
    Set OutputCell = Worksheets("KMV-Merton").Range("OutputCell")

    'use the Selection as an argument
    OutputCell.Value = VarunModel(Table, Selection)

End Sub

請參閱我的其他答案,以了解如何修改函數以接受Selection作為參數。

此外,如果要避免將函數用作工作表上的公式,則可以將函數聲明為私有。

Private Function VarunModel(ByVal Table As Range, ByVal SelectedRange As Range, Optional ByVal EndCondition As Integer = 0) As Variant

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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