VBA中的循环引用错误?

我试图在Excel中编写函数来计算默认概率。 我有一个包含3列数据的电子表格。 我希望能够突出显示select的数据,并让函数返回一个基于我突出显示的数据的值。

该函数从电子表格读取数据,然后使用该数据执行迭代过程(牛顿法)。 我试图让代码引用电子表格上的第一行数据,第一个“我”。 然后对于第二个我,我想要它参考第二行,依此类推。 到目前为止,我有这样的:

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 

不要在你的function中使用Selection 。 使用它会导致单元格在工作表中input公式时立即引用它自己。 这是你的循环引用。

你需要删除这两行。

 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 

然后在单元格中input这样的公式。

 =VarunModel(A3:C18,A5:C6) 

第二个参数是你的“select”范围。 关键是它不再依赖于select。 相反,你明确地告诉它什么范围用于计算。

这可能不是你想要的行为,但你需要避免在你的函数中使用Selection

如果你真的想在你的代码中使用Selection ,你需要创build一个Sub来调用你的函数。 您需要在代码中指定输出范围。

在工作表上创build一个button来运行这个代码:

 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 

看看我的其他答案如何修改函数接受select作为参数。

此外,如果您希望避免将该函数用作工作表上的公式,则可以将其声明为“私有”。

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