2016-06-16 3 views
0

Я пытаюсь выполнить условие IF-THEN-ELSE в Access VBA в пределах цикла for. Однако я не могу заставить его выполнить, что я делаю неправильно? Код выглядит следующим образом.Доступ к VBA Else without If

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 

Исполнительное это дает мне «Else Без Если» ошибка, которая сбивает с толку для меня, потому что есть Если - Тогда утверждение.

Для контекста здесь представлена ​​вся функция.

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

Поскольку вы вызвали цикл For внутри if, следующее должно быть в том же IF-блоке. Поэтому поставьте два 'Next I', один внутри If и другого внутри Else. И избавьтесь от одного после окончания if. –

+0

Когда 'm' ever> = 12? Вы объявляете его m = 3, и он никогда не изменяется. Следовательно, нет необходимости в том, чтобы/then/else блокировать. – Parfait

ответ

5

Вы довольно близко здесь, у вас есть только часть цикла или «Next I» в неправильном месте. Попытка:

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 
0

Пересмотрите с помощью набора записей, массив или петли, и вызовите функцию VBA непосредственно из запроса SQL, который является допустимым в Msaccess.exe (не через ODBC/OLEDB). Задача ваших потребностей состоит в необходимости искать одну строку с количеством строк, которое можно обрабатывать с помощью подзапросов. Ниже предполагается поле ID автонабора. Хотя запросы использовали производные таблицы (вложенные SELECT в статье FROM), такие производные таблицы могут быть сохранены как собственные SQL-хранимые запросы.

SQL Запрос (уведомление функции VBA, называется в линии со скалярным значением лямбда при 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 

Даже в любом случае вы можете запустить все это в SQL без VBA. Здесь 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 
+0

Какова точка if if <12, если вы задали m = 3 раньше? Я чувствую, что что-то упускаю. –

+0

Действительно, не было никакого смысла, поскольку ФП делал это только с очень комментариями, которые я поднял. Я держался для сравнения. Обратите внимание, что окончательный запрос принимает только m = 3. – Parfait

0

Я согласен с другими комментариями. m=3 во всех случаях, так зачем беспокоиться с if/else/end if. Однако, вот дополнительное наблюдение, которое должно получить 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