J'essaie d'utiliser "Et" ou "Ou" dans une déclaration If. J'ai probablement ma syntaxe erronée.
le résultat revient faux lorsque les données doivent le rendre vrai. Voici le code:
ElseIf (origNum = "006260006" Or origNum = "30062600006") And creditOrDebit = "D" Then
'do things here
End If
-Quand je débogue et que je viens à cette ligne, elle saute dessus et n'entre pas.
-origNum est égal à "006260006" et creditOrDebit = "D".
-so je suppose que ma déclaration "Ou" ne fonctionne pas.
-Espérons que c'est une question facile et rapide. Merci!
Le problème est probablement ailleurs. Essayez ce code par exemple:
Sub test()
origNum = "006260006"
creditOrDebit = "D"
If (origNum = "006260006" Or origNum = "30062600006") And creditOrDebit = "D" Then
MsgBox "OK"
End If
End Sub
Et vous verrez que votre Or
fonctionne comme prévu. Êtes-vous sûr que votre instruction ElseIf
est exécutée (elle ne sera pas exécutée si l'un des if/elseif avant est vrai)?
Ce n'est pas une réponse, mais c'est trop long pour un commentaire.
En réponse à réponses/commentaires de JP , j'ai effectué le test suivant pour comparer les performances des 2 méthodes. L'objet Profiler
est une classe personnalisée - mais en résumé, il utilise une fonction kernel32 assez précise (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
Les résultats de 5 analyses (en ms pour des boucles de 1 m):
20 juin 2012 19:28:25
nested_ifs (x1): 156 - Dernier cycle: 156 - Cycle moyen: 156
or_and (x1): 125 - Dernier cycle: 125 - Cycle moyen: 12520 juin 2012 19:28:26
nested_ifs (x1): 156 - Dernier cycle: 156 - Cycle moyen: 156
or_and (x1): 125 - Dernier cycle: 125 - Cycle moyen: 12520 juin 2012 19:28:27
nested_ifs (x1): 140 - Dernier cycle: 140 - Cycle moyen: 140
or_and (x1): 125 - Dernier cycle: 125 - Cycle moyen: 12520 juin 2012 19:28:28
nested_ifs (x1): 140 - Dernier cycle: 140 - Cycle moyen: 140
or_and (x1): 141 - Dernier cycle: 141 - Cycle moyen: 14120 juin 2012 19:28:29
nested_ifs (x1): 156 - Dernier cycle: 156 - Cycle moyen: 156
or_and (x1): 125 - Dernier cycle: 125 - Cycle moyen: 125
Remarque
Si creditOrDebit
n'est pas "D"
, Le code de JP est plus rapide (environ 60 ms contre 125 ms pour le code ou/et).
J'aime assylias 'répondre, mais je voudrais le reformuler comme suit:
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
Cela pourrait vous faire économiser quelques cycles de traitement, car si creditOrDebit
est <> "D"
il est inutile de vérifier la valeur de origNum
.
J'ai utilisé la procédure suivante pour tester ma théorie selon laquelle ma procédure est plus rapide:
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
Je dois avoir un ordinateur lent parce que 1 000 000 itérations n’ont pris que 200 ms, comme avec le test assylias '. Je devais limiter les itérations à 10 000 - hé, j'ai autre chose à faire :)
Après avoir exécuté la procédure ci-dessus 10 fois, ma procédure est plus rapide seulement 20% du temps. Cependant, lorsqu'il est plus lent, il ne l'est que superficiellement. Comme assylias a souligné, cependant, quand creditOrDebit
est <>"D"
, ma procédure est au moins deux fois plus rapide. J'ai été en mesure de le tester raisonnablement à 100 millions d'itérations.
Et cela est la raison pour laquelle je l'ai refactoré - pour court-circuiter la logique de sorte que origNum
ne nécessite pas d'évaluation lorsque creditOrDebit <> "D"
.
À ce stade, le reste dépend de la feuille de calcul du PO. Si creditOrDebit
est susceptible d'être égal à D, utilisez la procédure assylias ', car elle fonctionnera généralement plus rapidement. Mais si creditOrDebit
a un large éventail de valeurs possibles et que D
n’est plus susceptible d’être la valeur cible, ma procédure l’utilisera pour éviter d’évaluer inutilement l’autre variable.