调整Excel VBA函数以访问VBA

时间:2016-06-13 14:31:37

标签: excel vba ms-access

我正在重新访问Excel VBA中的一些旧代码并尝试将其转换为Access VBA。

此代码采用一系列数字(" Zeros")并计算一个简单的加权平均值,权重为" Lambda"。此计算和此代码工作正常,并已验证为正确。

Excel代码如下。

Option Explicit


Function EWMA(Zeros As Range, Lambda As Double, MarkDate As Date, MaturityDate As Date) As Double

    Dim vZeros() As Variant
    Dim Price1 As Double, Price2 As Double
    Dim SumWtdRtn As Double
    Dim I As Long
    Dim m As Double

    Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double

vZeros = Zeros

m = Month(MaturityDate) - Month(MarkDate)

For I = 2 To UBound(vZeros, 1)

    Price1 = 1 / ((1 + vZeros(I - 1, 1)) ^ (m / 12))
    Price2 = 1 / ((1 + vZeros(I, 1)) ^ (m / 12))


    LogRtn = Log(Price1 / Price2)

    RtnSQ = LogRtn ^ 2

    WT = (1 - Lambda) * Lambda ^ (I - 2)

    WtdRtn = WT * RtnSQ

    SumWtdRtn = SumWtdRtn + WtdRtn

Next I

EWMA = SumWtdRtn ^ (1 / 2)

End Function

现在我尝试在Access VBA中重现这个相同的功能。此代码引用了一个表(" HolderTable"),其中包含与" Zeros"完全相同的数字。上述Excel代码中的范围。在Access中,这些标记为" InterpRate"。然后它应用与Excel代码完全相同的计算,但适用于Access语法。

访问代码如下:

Function EWMA(Lambda As Double) As Double

Dim Price1 As Double, Price2 As Double
Dim vInterpRate() As Variant
Dim SumWtdRtn As Double
Dim I As Long
Dim m As Double
Dim rec As Recordset


Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double

m = 3

Dim x As Integer

Set rec = CurrentDb.OpenRecordset("SELECT InterpRate FROM HolderTable")

x = 1

Do While rec.EOF = False

ReDim Preserve vInterpRate(x + 1)

vInterpRate(x) = rec("InterpRate")

x = x + 1

rec.MoveNext

Loop

For I = 1 To x

Price1 = 1 / ((1 + vInterpRate(I - 1)) ^ (m / 12))

Price2 = 1 / ((1 + vInterpRate(I)) ^ (m / 12))


  LogRtn = Log(Price2 / Price1)

  RtnSQ = LogRtn ^ 2

  WT = (1 - Lambda) * Lambda ^ (I - 2)

  WtdRtn = WT * RtnSQ

  SumWtdRtn = SumWtdRtn + WtdRtn

Next I

EWMA = SumWtdRtn ^ (1 / 2)

End Function

理想情况下,这些应该产生完全相同的数字。 " Zeros"范围和" interpRate"数字是相同的。我怀疑问题在于我如何在Access中定义我的数组,但我似乎无法修复它。这两个代码之间是否存在任何不一致之处?

作为参考,我附上了带有VBA代码的Excel电子表格。 http://www.filedropper.com/soewma_1

1 个答案:

答案 0 :(得分:1)

恕我直言最好的可读方式是从x = 0开始,并将x = x + 1放在每个循环的开头:

Set rec = CurrentDb.OpenRecordset("SELECT InterpRate FROM HolderTable")
x = 0
Do While rec.EOF = False
    x = x + 1
    ReDim Preserve vInterpRate(x)
    vInterpRate(x) = rec("InterpRate")
    rec.MoveNext
Loop

由于你访问vInterpRate(I - 1),你的第二个循环必须是

For I = 2 To x

而不是For I = 1 To x