web-dev-qa-db-fra.com

Est-ce que l'opérateur "Et" de VBA évalue le deuxième argument lorsque le premier est faux?

Function Foo(thiscell As Range) As Boolean
  Foo = thiscell.hasFormula And (InStr(1, UCase(Split(thiscell.formula, Chr(40))(0)), "bar") > 0)
End Function

Cette fonction permet de tester la présence d’une certaine sous-chaîne (barre, dans ce cas) avant le (.

Le cas qui me pose problème, c'est lorsque la cellule transmise à la fonction est vide, le thisCell.hasFormula est faux, mais l'instruction après le et est toujours en cours d'évaluation. Cela me donne un indice en erreur hors de portée au moment de l'exécution.

Est-ce que VBA continue à évaluer le deuxième argument de And, même si le premier était faux?

43
James

Ce que vous recherchez s'appelle "évaluation de court-circuit". 

VBA ne l'a pas.

Vous pouvez voir une approche qui est probablement adaptable à votre situation ici .

L’approche choisie a consisté à substituer un Select Case à If. Il existe également un exemple d'utilisation de Ifs imbriqué.

54
DOK

Comme indiqué par DOK : Non, VBA n’a pas d’évaluation de court-circuit.

Il est techniquement plus efficace d'utiliser 2 instructions If-then au lieu d'utiliser l'opérateur AND, mais à moins que vous ne le fassiez souvent, vous ne remarqueriez pas les économies réalisées, alors optez pour ce qui est plus lisible. Et si vous voulez être vraiment technique, VBA gère également plusieurs instructions If-then plus rapidement que celles Select Case.

VBA est bizarre :)

10
aevanko

VBA a un comportement semblable à un court-circuit . Normalement, Null se propage à travers des expressions, par exemple. 3 + Null est Null et True And Null est Null. Cependant:

? False And Null
False

Cela ressemble à un comportement de court-circuit - que se passe-t-il? Null ne se propage pas lorsque l'autre argument d'une conjonction (And) est False ou 0 - le résultat est simplement False ou 0. Peu importe que ce soit l'argument gauche ou droit. Il en va de même si l'autre argument d'une disjonction (Or) est True ou un entier différent de zéro (une valeur à virgule flottante sera arrondie à un entier à l'aide de cette règle ).

Donc, les effets secondaires et les erreurs ne peuvent pas être empêchés dans les arguments à And et Or, mais la propagation Null peut être "court-circuitée". Ce comportement semble être hérité de SQL .

2
Hugh Allen

La réponse est oui, VBA ne court-circuite pas l'évaluation.

Ce n'est pas juste une question de style; cela fait une grande différence dans une situation comme celle-ci:

If i <= UBound(Arr, 1) And j <= UBound(Arr, 2) And Arr(i, 1) <= UBound(Arr2, 1) Then
    Arr2(Arr(i, 1), j) = Arr(i, j)
End If

... ce qui est incorrect. Plus adéquatement:

If i <= UBound(Arr, 1) And j <= UBound(Arr, 2) Then
    If Arr(i, 1) <= UBound(Arr2, 1) Then
        Arr2(Arr(i, 1), j) = Arr(i, j)
    End If
End If

Ou si vous avez une aversion pour les ifs imbriqués:

If i > UBound(Arr, 1) Or j > UBound(Arr, 2) Then
    ' Do Nothing
ElseIf Arr(i, 1) > UBound(Arr2, 1) Then
    ' Do Nothing
Else
    Arr2(Arr(i, 1), j) = Arr(i, j)
End If
2
sopatt

Je pense que c'est la meilleure pratique:

sub my conditions()
        If Condition1=constraint1 then
         if Condition2=constraint2 then
          if condition3=constraint3 then
           ...
            ....
        end if
         end if
          end if
    else
      end if
           ....
    end if
end sub

Ainsi, vous ne passerez que par les conditions si et seulement si la condition i est remplie.

0
Moreno