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