"И" и "Или" проблемы в заявлении 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
больше не будет целевым значением, моя процедура будет использовать это, чтобы предотвратить ненужную оценку другой переменной.