"И" и "Или" проблемы в заявлении IF

Я пытаюсь использовать "И" и "Или" в выражении If. У меня, вероятно, неправильный синтаксис.

результат возвращается false, когда данные должны сделать его истинным. Вот код:

ElseIf (origNum = "006260006" Or origNum = "30062600006") And creditOrDebit = "D" Then

'do things here

End If

-Когда я отлаживаю и прихожу к этой строке, он перебирает его и не входит.

-origNum фактически равен "006260006" и creditOrDebit = "D".

-so Я предполагаю, что мой оператор "Or" не работает.

- Надеюсь, это очень простой вопрос. Спасибо!

Ответ 1

Проблема, вероятно, в другом месте. Попробуйте этот код, например:

Sub test()

  origNum = "006260006"
  creditOrDebit = "D"

  If (origNum = "006260006" Or origNum = "30062600006") And creditOrDebit = "D" Then
    MsgBox "OK"
  End If

End Sub

И вы увидите, что ваш Or работает так, как ожидалось. Вы уверены, что ваш оператор ElseIf выполняется (он не будет выполнен, если какой-либо из if/elseif before имеет значение true)?

Ответ 2

Это не ответ, но слишком длинный для комментария.

В ответ на ответы JP/комментарии я проверил следующий тест, чтобы сравнить производительность двух методов. Объектом Profiler является пользовательский класс, но в итоге он использует функцию kernel32, которая достаточно точна (Private Declare Sub GetLocalTime Lib "kernel32" (lpSystemTime As SYSTEMTIME)).

Sub test()

  Dim origNum As String
  Dim creditOrDebit As String
  Dim b As Boolean
  Dim p As Profiler
  Dim i As Long

  Set p = New_Profiler

  origNum = "30062600006"
  creditOrDebit = "D"

  p.startTimer ("nested_ifs")

  For i = 1 To 1000000

    If creditOrDebit = "D" Then
      If origNum = "006260006" Then
        b = True
      ElseIf origNum = "30062600006" Then
        b = True
      End If
    End If

  Next i

  p.stopTimer ("nested_ifs")
  p.startTimer ("or_and")

  For i = 1 To 1000000

    If (origNum = "006260006" Or origNum = "30062600006") And creditOrDebit = "D" Then
      b = True
    End If

  Next i

  p.stopTimer ("or_and")

  p.printReport

End Sub

Результаты 5 прогонов (в мс для 1 м петель):

20-Jun-2012 19:28:25
nested_ifs (x1): 156 - Last Run: 156 - Средний пробег: 156
or_and (x1): 125 - Последний прогон: 125 - Средний пробег: 125

20-Jun-2012 19:28:26
nested_ifs (x1): 156 - Last Run: 156 - Средний пробег: 156
or_and (x1): 125 - Последний прогон: 125 - Средний пробег: 125

20-Jun-2012 19:28:27
nested_ifs (x1): 140 - Last Run: 140 - Средний пробег: 140
or_and (x1): 125 - Последний прогон: 125 - Средний пробег: 125

20-Jun-2012 19:28:28
nested_ifs (x1): 140 - Last Run: 140 - Средний пробег: 140
or_and (x1): 141 - Последний прогон: 141 - Средний пробег: 141

20-Jun-2012 19:28:29
nested_ifs (x1): 156 - Last Run: 156 - Средний пробег: 156
or_and (x1): 125 - Последний прогон: 125 - Средний пробег: 125

Примечание

Если creditOrDebit не "D", JP-код работает быстрее (около 60 мс против 125 мс для кода и/или кода).

Ответ 3

Мне нравится assylias ', но я бы реорганизовал его следующим образом:

Sub test()

Dim origNum As String
Dim creditOrDebit As String

origNum = "30062600006"
creditOrDebit = "D"

If creditOrDebit = "D" Then
  If origNum = "006260006" Then
    MsgBox "OK"
  ElseIf origNum = "30062600006" Then
    MsgBox "OK"
  End If
End If

End Sub

Это может сэкономить вам несколько циклов процессора, поскольку, если creditOrDebit - <> "D", нет смысла проверять значение origNum.

Обновление:

Я использовал следующую процедуру, чтобы проверить мою теорию о том, что моя процедура выполняется быстрее:

Public Declare Function timeGetTime Lib "winmm.dll" () As Long

Sub DoTests2()

  Dim startTime1 As Long
  Dim endTime1 As Long
  Dim startTime2 As Long
  Dim endTime2 As Long
  Dim i As Long
  Dim msg As String

  Const numberOfLoops As Long = 10000
  Const origNum As String = "006260006"
  Const creditOrDebit As String = "D"

  startTime1 = timeGetTime
  For i = 1 To numberOfLoops
    If creditOrDebit = "D" Then
      If origNum = "006260006" Then
        ' do something here
        Debug.Print "OK"
      ElseIf origNum = "30062600006" Then
        ' do something here
        Debug.Print "OK"
      End If
    End If
  Next i
  endTime1 = timeGetTime

  startTime2 = timeGetTime
  For i = 1 To numberOfLoops
    If (origNum = "006260006" Or origNum = "30062600006") And _
      creditOrDebit = "D" Then
      ' do something here
      Debug.Print "OK"
    End If
  Next i
  endTime2 = timeGetTime

  msg = "number of iterations: " & numberOfLoops & vbNewLine
  msg = msg & "JP proc: " & Format$((endTime1 - startTime1), "#,###") & _
       " ms" & vbNewLine
  msg = msg & "assylias proc: " & Format$((endTime2 - startTime2), "#,###") & _
       " ms"

  MsgBox msg

End Sub

У меня должен быть медленный компьютер, потому что 1,000,000 итераций нигде не приближались к ~ 200 мс, как в тесте assylias. Я должен был ограничить итерации до 10 000 - эй, у меня есть другие дела:)

После выполнения описанной выше процедуры 10 раз моя процедура выполняется только в 20% случаев. Однако, когда он медленнее, он только поверхностно медленнее. Тем не менее, assylias указал, что creditOrDebit <>"D", моя процедура по крайней мере в два раза быстрее. Я смог разумно проверить его на 100 миллионов итераций.

И именно поэтому я реорганизовал его - чтобы закоротить логику так, чтобы origNum не нужно оценивать, когда creditOrDebit <> "D".

В этот момент все остальное зависит от электронной таблицы OP. Если creditOrDebit, вероятно, будет равным D, используйте процедуру assylias ', потому что она будет работать быстрее. Но если creditOrDebit имеет широкий диапазон возможных значений, а D больше не будет целевым значением, моя процедура будет использовать это, чтобы предотвратить ненужную оценку другой переменной.