我试图在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
答案 0 :(得分:0)
请勿在您的功能中使用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
。
答案 1 :(得分:0)
如果您真的想在代码中使用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。
Private Function VarunModel(ByVal Table As Range, ByVal SelectedRange As Range, Optional ByVal EndCondition As Integer = 0) As Variant