【问题标题】:Storing Arrays in Access VBA在 Access VBA 中存储数组
【发布时间】:2020-07-13 20:21:48
【问题描述】:

我在 Access VBA 中编写了一个子例程,此处显示以供参考:Looping Through Dates in strSQL in Access VBA。如下:

Sub SampleReadCurve()

Dim rs As Recordset
Dim iRow As Long, iField As Long
Dim strSQL As String
Dim CurveID As Long
Dim MarkRunID As Long
Dim MaxOfMarkAsofDate As Date
Dim userdate As String

CurveID = 15

Dim I As Integer
Dim x As Date

userdate = InputBox("Please Enter the Date (mm/dd/yyyy)")

x = userdate

For I = 0 To 150

MaxOfMarkAsofDate = x - I


strSQL = "SELECT * FROM VolatilityOutput WHERE CurveID=" & CurveID & " AND MaxOfMarkAsofDate=#" & MaxOfMarkAsofDate & "# ORDER BY MaxOfMarkasOfDate, MaturityDate"

Set rs = CurrentDb.OpenRecordset(strSQL, Type:=dbOpenDynaset, Options:=dbSeeChanges)
If rs.RecordCount <> 0 Then

    rs.MoveFirst

    rs.MoveLast

    Dim BucketTermAmt As Long
    Dim BucketTermUnit As String
    Dim BucketDate As Date
    Dim MarkAsOfDate As Date
    Dim InterpRate As Double

    BucketTermAmt = 3
    BucketTermUnit = "m"
    BucketDate = DateAdd(BucketTermUnit, BucketTermAmt, MaxOfMarkAsofDate)
    InterpRate = CurveInterpolateRecordset(rs, BucketDate)
    Debug.Print BucketDate, InterpRate

End If

Next I


End Function

运行此子例程会计算 76 个数字的范围。我想取这 76 个数字,并在下面的函数中使用它们作为“ZeroCurveInput”。

Function EWMA(ZeroCurveInput As Range, Lambda As Double) As Double

    Dim vZeros() As Variant
    vZeros = ZeroCurveInput
    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 = ZeroCurveInput

m = BucketTermAmt

For I = 2 To UBound(vZeros, 1)

    Price1 = Exp(-vZeros(I - 1, 1) * (m / 12))

    Price2 = Exp(-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

我最初在 Excel VBA 中编写了这个函数,我正在尝试将它移植到 Access VBA。在 Excel 中,我只需将 76 个数字的列读取为范围并将其维度作为变量存储为数组,然后在函数中使用它。但是我不能使用 Access 中的 range 属性来做类似的事情,我不知道用什么来代替。

如何将数字存储为数组,然后将它们传递给函数?

【问题讨论】:

    标签: arrays excel ms-access vba


    【解决方案1】:

    您也可以简单地将 SampleReadCurve 中的数字写入表格,然后像遍历数组一样遍历表格。所以,你的 sub 会变成这个(顺便说一句,这行得通吗?你正在创建一个 Sub 并结束一个 Function...):

    Sub SampleReadCurve()
    
    Dim rs As Recordset
    Dim rs2 as Recordset
    Dim iRow As Long, iField As Long
    Dim strSQL As String
    Dim CurveID As Long
    Dim MarkRunID As Long
    Dim MaxOfMarkAsofDate As Date
    Dim userdate As String
    
    CurveID = 15
    
    Dim I As Integer
    Dim x As Date
    
    userdate = InputBox("Please Enter the Date (mm/dd/yyyy)")
    
    x = userdate
    
    For I = 0 To 150
    
    MaxOfMarkAsofDate = x - I
    
    
    strSQL = "SELECT * FROM VolatilityOutput WHERE CurveID=" & CurveID & " AND MaxOfMarkAsofDate=#" & MaxOfMarkAsofDate & "# ORDER BY MaxOfMarkasOfDate, MaturityDate"
    
    Set rs = CurrentDb.OpenRecordset(strSQL, Type:=dbOpenDynaset, Options:=dbSeeChanges)
    Set rs2 = CurrentDb.OpenRecordset("MyNewTable")
    
    If rs.RecordCount <> 0 Then
    
        rs.MoveFirst
    
        rs.MoveLast
    
        Dim BucketTermAmt As Long
        Dim BucketTermUnit As String
        Dim BucketDate As Date
        Dim MarkAsOfDate As Date
        Dim InterpRate As Double
    
        BucketTermAmt = 3
        BucketTermUnit = "m"
        BucketDate = DateAdd(BucketTermUnit, BucketTermAmt, MaxOfMarkAsofDate)
        InterpRate = CurveInterpolateRecordset(rs, BucketDate)
        Debug.Print BucketDate, InterpRate
        rs2.AddNew
        rs2("BucketDate") = BucketDate
        rs2("InterpRate") = InterpRate
        rs2.Update
    
    End If
    
    Next I
    
    
    End Function
    

    那么您的 EWMA 函数将如下所示:

    Function EWMA(Lambda As Double) As Double
    
        Dim Price1 As Double, Price2 As Double
        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 = BucketTermAmt
    
    Set rec = CurrentDB.OpenRecordset("SELECT InterpRate FROM MyNewTable")
    
    I = 2
    Do While rec.EOF = False
    
        Price1 = Exp(-rec("InterpRate")(I - 1, 1) * (m / 12))
        Price2 = Exp(-rec("InterpRate")(I, 1) * (m / 12))
        LogRtn = Log(Price1 / Price2)
        RtnSQ = LogRtn ^ 2
        WT = (1 - Lambda) * Lambda ^ (I - 2)
        WtdRtn = WT * RtnSQ
        SumWtdRtn = SumWtdRtn + WtdRtn
        I = I + 1
    
    Loop
    
    EWMA = SumWtdRtn ^ (1 / 2)
    
    End Function
    

    【讨论】:

    • 您好,感谢您的回复。它应该显示为“End Sub”,我在尝试不同的解决方案后忘记将其编辑回来。当我运行代码时,我收到 rs2("BucketDate") = BucketDate 和 rs2("InterpRate") = InterpRate 的运行时错误,提示“未找到项目”。这是否意味着它在上一行中没有正确写入表?
    • 您需要创建一个新表。随意调用它,但只需将上面代码中的“MyTableName”实例替换为表的实际名称。在表中创建2个字段; BucketDate 和 InterpRate。我忘记的一件事是,您需要清除代码顶部的表格,否则您每次运行时都会继续追加数据。因此,在 SampleReadCurve 顶部的某处,输入: DoCmd.RunSQL "DELETE * FROM MyTableName"
    • 啊完美,我明白了问题所在。谢谢。我不断收到类型不匹配错误,对于 Price1 = Exp(-rec("InterpRate")(I - 1, 1) * (m / 12)) 行。我是否需要将 Price1 标注为不同的变量?
    • 您实际上可能必须将 rec("InterpRate") 设置为等于一个变量。我没有测试代码,所以公式可能看不懂rec("InterpRate")。
    • 我必须将它设置为什么类型的变量,以便它可以访问数组的元素?
    【解决方案2】:

    有几种不同的方法可以做到这一点,包括按照您的建议使用数组。如果您只需要 76 个数字,则可以使用集合来执行此操作。该集合的优点是您无需提前知道其中有多少项目。

    这是一个使用集合的简单示例:

    Sub TestColl()
        Dim TestCollection As Collection
        Set TestCollection = CreateColl()
        LoopThruColl TestCollection
    End Sub
    Function CreateColl() As Collection
        Dim MyColl As Collection
        Set MyColl = New Collection
    
        Dim i As Integer
        For i = 1 To 5
            MyColl.Add i * 2
        Next i
        Set CreateColl = MyColl
    End Function
    Sub LoopThruColl(CollToLoop As Collection)
        Dim i As Integer
        For i = 2 To CollToLoop.Count
            Debug.Print i, CollToLoop.Item(i - 1), CollToLoop.Item(i)
        Next i
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      相关资源
      最近更新 更多