我的功能涉及一个范围,比如无风险的利率,并产生一系列折扣因子。问题似乎在循环中,有三个:
(a)在阵列上调用fn,
(b)指定阵列点,
(c)使用循环i作为fn参数。
是在每个数组周围使用循环的最佳方法(第i点),还是可以通过简单地调用函数来填充完整数组?
Function CreateDiscArray(RFR_array As Range)
Dim MyArray() As Variant
MyArray = RFR_array
Dim xDimRate As Integer
xDimRate = UBound(MyArray, 1)
Dim TempArray() As Variant
For i = 1 To xDimRate Step 1
TempArray(i, 1) = DiscFact(MyArray(i), i)
Next i
CreateDiscArray() = TempArray()
End Function
Function DiscFact(Rate, Tenor)
If Tenor < 1 Then DiscFact = (1 + Tenor * Rate)
If Tenor >= 1 Then DiscFact = (1 + Rate) ^ (-Tenor)
End Function
即。是否可以在没有循环的情况下调用:
CreateDiscArray = DiscFact(MyArray(,1), 1 to xDimRate)
答案 0 :(得分:4)
您的原始代码存在一些问题
您没有使用Option Explicit
,因此您不知道i
未声明。
您没有确定TempArray
的尺寸,因此您的代码无法分配给其索引。
您引用的myArray(i)
会因为有2个维度而失败,因此您必须使用myArray(i,1)
。
您正在使用i
计数器(基于1)作为男高音。这是一个糟糕的设计选择,因为你的男高音并不总是一致的长度,你可以期待有很多短期的男高音。此外,这是一个错误,因为i >= 1
总是是TRUE
因此,要使原始函数可行代码:
Option Explicit
Function CreateDiscArray(RFR_array As Range)
Dim MyArray() As Variant
MyArray = RFR_array.Value
Dim xDimRate As Integer
xDimRate = UBound(MyArray, 1)
ReDim TempArray(LBound(MyArray) To UBound(MyArray), LBound(MyArray, 2) To UBound(MyArray, 2)) As Variant
Dim i As Long
For i = 1 To xDimRate Step 1
TempArray(i, 1) = DiscFact(MyArray(i, 1), i)
Next i
CreateDiscArray = TempArray
End Function
Function DiscFact(Rate, Tenor)
'BUG: Tenor will always be >= 1
If Tenor < 1 Then DiscFact = (1 + Tenor * Rate)
If Tenor >= 1 Then DiscFact = (1 + Rate) ^ (-Tenor)
End Function
但那不是你的问题。正如其他人所指出的那样,VBA本身并不支持任何东西,但你使用的是Excel,所以你确实有一些选择:
首先,让我们通过在tenors
之外添加一系列rates
来修复Tenor错误。期待在A1:A3
,费率在B1:B3
。我们可以将C1:C3
中的数组公式用作=IF(A1:A3<1,1+A1:A3*B1:B3,(1+B1:B3)^(-A1:A3))
A | B | C
--+-----|------|-------------------------------------------------
1 | .5 | 99 | {=IF(A1:A3<1,1+A1:A3*B1:B3,(1+B1:B3)^(-A1:A3))}
2 | 1 | 97 |
3 | 2 | 95 |
并且,如果您将命名范围命名为Tenor和Rate,则可以将数组公式重新定义为=IF(Tenor<1,1+Tenor*Rate,(1+Rate)^(-Tenor))
如果您确实希望此解决方案位于VBA中,则需要更改功能签名以接受期限和费率范围,然后使用Application.Evaluate
以及构造的公式,获得一系列结果。
使用笨拙的解决方案,不关心工作表或工作簿:
Public Function DiscFactor(rates As Range, tenors As Range) As Variant
Dim Rate As String
Dim Tenor As String
Rate = rates.Address
Tenor = tenors.Address
DiscFactor = Application.Evaluate("=IF(" & Tenor & "<1,1+" & Tenor & "*" & Rate & ",(1+" & Rate & ")^(-" & Tenor & "))")
End Function