Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA中的循环参考错误?_Vba_Excel - Fatal编程技术网

VBA中的循环参考错误?

VBA中的循环参考错误?,vba,excel,Vba,Excel,我试图在Excel中编写一个函数来计算违约概率。我有一个包含3列数据的电子表格。我希望能够突出显示选定的数据,并让函数返回一个基于我突出显示的数据的值 该函数从电子表格中读取数据,然后使用数据执行迭代过程(牛顿法)。我试图让代码引用电子表格中选定数据的第一行,即第一个“I”。然后对于第二行,我希望它指向第二行,依此类推。到目前为止,我得到了这个: iNumRows = Table.Rows.Count maturity = Worksheets("KMV-Merton").Range("B2"

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

该函数从电子表格中读取数据,然后使用数据执行迭代过程(牛顿法)。我试图让代码引用电子表格中选定数据的第一行,即第一个“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

不要在函数中使用
选择
。使用它会使单元格在您在工作表中输入公式时立即引用自身。这是你的循环参考

您需要删除这两行

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
。使用它会使单元格在您在工作表中输入公式时立即引用自身。这是你的循环参考

您需要删除这两行

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)
第二个参数是“选定”范围。关键是它不再依赖于选择。相反,您可以明确地告诉它用于计算的范围


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

如果您确实想在代码中使用
选择
,则需要创建一个子函数来调用函数。您需要在代码中指定输出范围

在工作表上创建一个按钮以运行此代码:

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
请参阅我的另一个答案,了解如何修改函数以接受选择作为参数

如果希望避免将函数用作工作表上的公式,也可以将函数声明为Private

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

如果确实要在代码中使用
选择
,则需要创建一个子函数来调用函数。您需要在代码中指定输出范围

在工作表上创建一个按钮以运行此代码:

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
请参阅我的另一个答案,了解如何修改函数以接受选择作为参数

如果希望避免将函数用作工作表上的公式,也可以将函数声明为Private

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

股权(i)这是在哪里定义的?对不起,我遗漏了代码的前一部分,其中定义了:期权显式私募股权mMax=10000公开到期日,作为双重私募股权(1:mMax)作为双重私人债务(1:mMax)作为双重私人无风险(1:mMax)作为双专用iptr作为整数公共SIGMASSETLAST作为双专用iptr,不要介意您的循环引用。选择范围时,无法强制函数重新计算。您必须将范围指定为函数的参数。对不起,我是VBA的初学者。“i”不是由Table.Rows.Count定义的,并将Table作为范围吗?如何将范围指定为函数的参数?谢谢你的帮助。我包括了两个答案,因为有两种方法可以解决你的问题。1) 您可以使用sub中的
选项使用按钮调用sub;或者2)您可以使用工作表上的功能,而无需使用
选择
。无论哪种方式,您都需要从函数中删除
选择项
,并将范围作为参数传递。股本(i)这是在哪里定义的?抱歉,我遗漏了代码中定义它的前一部分:Option Explicit Private Const mMax=10000公共到期日作为双重私人股本(1到mMax)作为双重私人债务(1到mMax)作为双专用无风险(1到mMax)作为双专用iptr作为整数公共SIGMASSETLAST作为双专用不要介意您的循环引用。选择范围时,无法强制函数重新计算。您必须将范围指定为函数的参数。对不起,我是VBA的初学者。“i”不是由Table.Rows.Count定义的,并将Table作为范围吗?如何将范围指定为函数的参数?谢谢你的帮助。我包括了两个答案,因为有两种方法可以解决你的问题。1) 您可以使用sub中的
选项使用按钮调用sub;或者2)您可以使用工作表上的功能,而无需使用
选择
。无论哪种方式,您都需要从函数中删除
选择项
,并将范围作为参数传递。股本(i)这是在哪里定义的?抱歉,我遗漏了代码中定义它的前一部分:Option Explicit Private Const mMax=10000公共到期日作为双重私人股本(1到mMax)作为双重私人债务(1到mMax)作为双专用无风险(1到mMax)作为双专用iptr作为整数公共SIGMASSETLAST作为双专用不要介意您的循环引用。选择范围时,无法强制函数重新计算。您必须将范围指定为函数的参数。对不起,我是VBA的初学者。“i”不是由Table.Rows.Count定义的,并将Table作为范围吗?如何将范围指定为函数的参数?谢谢你的帮助。我包括了两个答案,因为有两种方法可以解决你的问题。1) 您可以使用sub中的
选项使用按钮调用sub;或者你可以