在VBA中使用ByVal

时间:2014-05-12 15:35:47

标签: vba pass-by-value lvalue byval

在我必须编写的插值方案中,我需要一个最小和最大函数,因此我快速编写了从插值函数中调用的函数Min和Max。它看起来像这样:

Function interpolateVol(Strike As Double, Maturity As Double, coupon As Variant)
Dim i, k, j As Long
Dim timeIndex, strikeIndex As Long
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
Dim w1, w2 As Double

If coupon = "1M" Then
    j = 3
ElseIf coupon = "3M" Then
    j = 4
ElseIf coupon = "6M" Then
    j = 5
End If

' we set i = 1 as the maturities do not matter for
' picking up the time index
If Maturity <= volatilityCube(1, 1, 2) Then
    timeIndex = 1
ElseIf Maturity > volatilityCube(noMaturities, 1, 2) Then
    timeIndex = noMaturities
Else
    i = 1
    While volatilityCube(i, 1, 2) < Maturity
        i = i + 1
    Wend
    timeIndex = i   ' volatilityCube(timeIndex-1,2) < Maturity <= volatilityCube(timeIndex,2)
End If

' we set k = 1 as the strikes do not matter for
' picking up the strike index
If Strike <= volatilityCube(1, 1, 1) Then
    strikeIndex = 1
ElseIf Strike > volatilityCube(1, noStrikes, 1) Then
    strikeIndex = noStrikes
Else
    k = 1
    While volatilityCube(1, k, 1) < Strike
        k = k + 1
    Wend
    strikeIndex = k  ' volatilityCube(strikeIndex-1,1) < Strike <= volatilityCube(strikeIndex,1)
End If

' first we interpolate on the tenors
' as a result we will have two interpolated values:
' one for timeIndex, another for timeIndex + 1
w1 = (Maturity - volatilityCube(timeIndex - 1, 1, 2)) / _
     (volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
w2 = (volatilityCube(timeIndex, 1, 2) - Maturity) / _
     (volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
vol_minus1 = w1 * volatilityCube(timeIndex - 1, strikeIndex - 1, j) + _
            w2 * volatilityCube(timeIndex, strikeIndex - 1, j)

vol_zero = w1 * volatilityCube(timeIndex - 1, strikeIndex, j) + _
            w2 * volatilityCube(timeIndex, strikeIndex, j)

' Now we have two vols interpolated in time, each for another strike.
' These two vols need to be interpolated in strikes:
volmin = Min(vol_minus1, vol_zero)
volmax = Max(vol_minus1, vol_zero)
w1 = (Strike - volatilityCube(1, strikeIndex - 1, 1)) / _
     (volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
w2 = (volatilityCube(1, strikeIndex, 1) - Strike) / _
     (volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
vol = w1 * volmin + w2 * volmax

interpolateVol = vol

End Function

Function Min(number1 As Double, number2 As Double) As Double
    Dim var As Double

    If (number1 < number2) Then
        var = number1
    Else
        var = number2
    End If

    Min = var
End Function

Function Max(number1 As Double, number2 As Double) As Double
    Max = number1 + number2 - Min(number1, number2)
End Function

但是,运行代码会提示“byref参数类型不匹配”错误。事实证明,我必须通过将ByVal添加到函数参数来明确表示我传递值而不是引用:

Function Min(ByVal number1 As Double, ByVal number2 As Double) As Double
        Dim var As Double

        If (number1 < number2) Then
            var = number1
        Else
            var = number2
        End If

        Min = var
    End Function

    Function Max(ByVal number1 As Double, ByVal number2 As Double) As Double
        Max = number1 + number2 - Min(number1, number2)
    End Function

现在我有两个问题:

  • 我发现我需要通过值显式传递令人惊讶。在C ++中,函数变量默认通过值传递。我应该得出结论,VBA通过引用传递变量作为默认值吗?
  • 为什么将Byval添加到函数参数中会有帮助?我没有看到类型之间的关系(假设错误)和传递值和/或引用....

非常感谢提前。

2 个答案:

答案 0 :(得分:3)

尝试更改interpolateVol的这一部分:

Dim vol_minus1, vol_zero, volmin, volmax, vol As Double

对此:

Dim vol_minus1 As Double, vol_zero As Double, volmin As Double, volmax As Double, vol As Double

问题在于,在原始版本中,只有vol被声明为Double,因为它紧挨着Double这个词。其他四个声明没有应用Double,因此它们被声明为Excel VBA默认类型,即Variant。这可能令人困惑,因为VBA与您可能习惯使用的其他语言不同,例如C,你可以说double vol_minus1, vol_zero, volmin, volmax, vol;

之类的东西

答案 1 :(得分:1)

该错误与ByRefByVal无关;它只是声明ab或两者的类型不正确。例如,如果您这样做:

Public Sub interpolate()
    Dim a As String
    Dim b As String
    a = 1
    b = 2
    x = Min(a, b)
End Sub

你会得到那个错误,但如果你这样做,你就不会:

Public Sub interpolate()
    Dim a As Double
    Dim b As Double
    a = 1
    b = 2
    x = Min(a, b)
End Sub

两者之间的区别在于,在第二个中,ab具有Min函数所期望的类型。

它甚至在该错误中使用术语ByRef的原因是它只是试图更具体地帮助您找出它所引用的参数。这就像说“看着黑狗”,而不仅仅是“看着狗。”