不使用If访问VBA Else

时间:2016-06-16 15:44:10

标签: vba ms-access access-vba

我试图在For循环中的Access VBA中执行IF-THEN-ELSE条件。但是我似乎无法执行它,我做错了什么?代码如下。

If m < 12 Then

For I = 2 To x

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

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

  LogRtn = Log(Price1 / Price2)

  RtnSQ = LogRtn ^ 2

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

  WtdRtn = WT * RtnSQ

  SumWtdRtn = SumWtdRtn + WtdRtn

Else

For I = 2 To x

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

Price2 = Exp((vInterpRate(I)) * (m / 12))

End If

执行此操作会给我一个&#34; Else Without If&#34;错误,这让我感到困惑,因为有一个If - Then语句。

对于上下文,这是整个函数。

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 = 0

Do While rec.EOF = False

x = x + 1

ReDim Preserve vInterpRate(x)

vInterpRate(x) = rec("InterpRate")


rec.MoveNext

Loop

If m < 12 Then

For I = 2 To x


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

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

  LogRtn = Log(Price1 / Price2)

  RtnSQ = LogRtn ^ 2

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

  WtdRtn = WT * RtnSQ

  SumWtdRtn = SumWtdRtn + WtdRtn

Else

For I = 2 To x

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

Price2 = Exp((vInterpRate(I)) * (m / 12))

End If


Next I

EWMA = SumWtdRtn ^ (1 / 2)

End Function

3 个答案:

答案 0 :(得分:5)

你离这儿很近,你只有循环部分或者#34;接下来我&#34;部分在错误的地方。尝试:

If m < 12 Then
    For I = 2 To x
        Price1 = 1 / ((1 + vInterpRate(I - 1)) ^ (m / 12))
        Price2 = 1 / ((1 + vInterpRate(I)) ^ (m / 12))
        LogRtn = Log(Price1 / Price2)
        RtnSQ = LogRtn ^ 2
        WT = (1 - Lambda) * Lambda ^ (I - 2)
        WtdRtn = WT * RtnSQ
        SumWtdRtn = SumWtdRtn + WtdRtn
    Next I
Else
    For I = 2 To x
        Price1 = Exp((vInterpRate(I - 1)) * (m / 12))
        Price2 = Exp((vInterpRate(I)) * (m / 12))
    Next I
End If

答案 1 :(得分:0)

重新考虑使用记录集,数组或循环,并直接从MSAccess.exe(不是通过ODBC / OLEDB)允许的SQL查询中调用VBA函数。您需要的挑战是需要查看一行可以使用子查询处理行计数。下面假设一个自动编号ID字段。虽然查询使用派生表(SELECT子句中的嵌套FROM),但这样的派生表可以保存为自己的SQL存储查询。

SQL 查询(注意VBA函数在线调用标量Lambda值为0.015)

SELECT Sum(final.WtdRtn) ^ (1/2) As EWMA

FROM    
   (SELECT dT.CurrInterpRate, dT.LastInterpRate, dT.RowCount,
           EWMA(0.015, dT.CurrInterpRate, dT.LastInterpRate, dT.RowCount) As WtdRtn
    FROM    
        (SELECT HolderTable.ID, HolderTable.InterpRate As CurrInterpRate,

               (SELECT TOP 1 HolderTable.InterpRate FROM HolderTable sub 
                WHERE sub.ID < HolderTable.ID
                ORDER BY sub.ID DESC) As LastInterpRate,

               (SELECT Count(*) FROM HolderTable sub 
                WHERE sub.ID < HolderTable.ID) As RowCount

         FROM HolderTable
        ) As dT

   ) As final

VBA 函数(要保存在标准模块中而不是任何特定对象(表单/报表);注意在SQL中运行聚合时返回值的更改

Public Function EWMA(Lambda As Double, currRowIR As Double, _
                     lastRowIR As Double, rowCount As Long) As Double

    Dim Price1 As Double, Price2 As Double
    Dim SumWtdRtn As Double
    Dim m As Double: m = 3

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

    If m < 12 Then

          Price1 = 1 / ((1 + lastRowIR) ^ (m / 12))
          Price2 = 1 / ((1 + currRowIR) ^ (m / 12))
          LogRtn = Log(Price1 / Price2)
          RtnSQ = LogRtn ^ 2
          WT = (1 - Lambda) * Lambda ^ (rowCount)
          WtdRtn = WT * RtnSQ

    Else
          Price1 = Exp(lastRowIR * (m / 12))
          Price2 = Exp(currRowIR * (m / 12))
    End If

    EWMA = WtdRtn

End Function

即使如此,您也可以在没有VBA的情况下在SQL中运行它。这里, Lambda m 作为标量传递。当然没有数据,我无法完全测试:

SELECT Sum(final.WtdRtn) ^ (1/2) As EWMA

FROM    
    (SELECT 1 / ((1 + dT.lastRowIR) ^ (dT.m / 12)) As Price1, 
            1 / ((1 + dT.currRowIR) ^ (dT.m / 12)) As Price2,
            Log(Price1 / Price2) As LogRtn, LogRtn ^ 2 As RtnSQ, 
            (1 - dT.Lambda) * dT.Lambda ^ (dT.rowCount) As WT,
            WT * RtnSQ As WtdRtn
     FROM    
         (SELECT HolderTable.ID, HolderTable.InterpRate As currRowIR,

                 (SELECT TOP 1 HolderTable.InterpRate FROM HolderTable sub 
                  WHERE sub.ID < HolderTable.ID
                  ORDER BY sub.ID DESC) As lastRowIR,

                 (SELECT Count(*) FROM HolderTable sub 
                  WHERE sub.ID < HolderTable.ID) As rowCount

                 3 As m,

                 0.015 As Lambda

         FROM HolderTable
        ) As dT

    ) As final

答案 2 :(得分:0)

我同意其他评论。在所有情况下m=3,所以为什么要烦恼if / else / end if。但是,如果你选择使用if / end,如果你选择使用它,那么这里应该得到if / end。

您使用for I=2 to x的多个案例。据我所知,你只能使用它一次?

For I = 2 To x
If m < 12 Then
    Price1 = 1 / ((1 + vInterpRate(I - 1)) ^ (m / 12))
    Price2 = 1 / ((1 + vInterpRate(I)) ^ (m / 12))
    LogRtn = Log(Price1 / Price2)
    RtnSQ = LogRtn ^ 2
    WT = (1 - Lambda) * Lambda ^ (I - 2)
    WtdRtn = WT * RtnSQ
    SumWtdRtn = SumWtdRtn + WtdRtn
Else
    Price1 = Exp((vInterpRate(I - 1)) * (m / 12))
    Price2 = Exp((vInterpRate(I)) * (m / 12))

End If
Next I