Le point d'interrogation dans le titre n'est là que parce que je suis très réticent à appeler quoi que ce soit un bug du compilateur, mais dans ce cas, je serais surpris si quelqu'un pouvait expliquer ce comportement d'une autre manière.
Le code pour reproduire le problème est très, très simple. Dans un module standard, nous avons les éléments suivants:
Public Function CreateAndDestroyObject() As Long Dim oClass2 As cClass Set oClass2 = New cClass Set oClass2 = Nothing End Function Private Sub Class_Terminate() End Sub
et nous avons une classe ( cclass
) définie dans un module de classe nommé CClass, contenant les éléments suivants Code:
Sub CompilerBug() Dim oClass As cClass Set oClass = New cClass If Falsee(oClass.CreateAndDestroyObject) Then Debug.Print "This doesn't print, as it shouldn't." End If End Sub Public Function Falsee(lng As Variant) As Boolean Falsee = False End Function
Le code est assez explicite. L'instruction si est entrée malgré la fonction bien nommée false
renvoyant false
, peu importe l'entrée! Le même résultat peut être observé lorsque la fonction de la classe est remplacée par une propriété publique similaire GET
.
Aux fins de la reproduction, j'obtiens ce comportement dans mon bureau 365 Excel, 64bit, version 2011 (build 13426.20274) qui est la version actuelle à jour d'Excel. J'ai également testé ce code exact dans mon mot vba ide avec exactement les mêmes résultats.
"preuve":
2 Réponses :
Ce bug n'est pas présent sur 32 bits, mais il semble être présent dans des applications compatibles VBA 64 bits (j'ai essayé Excel, Word et autocad ).
Puisque la question couvre déjà ce qui se passe si l'objet ne se termine pas ou s'il n'y a pas class_termine
Événement, les exemples suivants utilisent tous un objet qui va sûrement sortir de la portée et nous supposons également qu'il existe un class_termine
qui est appelé:
Option Explicit #If Win64 Then Sub Bug() ' We don't really need a Clone method to reproduce the bug If Falsee(New cClass) Then Debug.Print "This does print, although it shouldn't!" End If ' If we add a logical operator and a second method call then the bug disappears: If Falsee(New cClass) Or Falsee(New cClass) Then Debug.Print "This doesn't print, as it shouldn't." End If ' It could be any other method. The order of the methods also doesn't matter If Falsee(New cClass) Or Sin(0) Then Debug.Print "This doesn't print, as it shouldn't." End If ' The above workaround does not work if we simply use a boolean value after the method call If Falsee(New cClass) Or False Then Debug.Print "This does print, although it shouldn't!" End If ' But it does work if we add the boolean before the method call: If False Or Falsee(New cClass) Then Debug.Print "This doesn't print, as it shouldn't." End If If True And Falsee(New cClass) Then Debug.Print "This doesn't print, as it shouldn't." End If End Sub Function Falsee(oClass As cClass) As Boolean Falsee = False End Function #End If
Intéressant, cela aggrave encore les choses! De plus, si vous laissez la fonction renvoyer autre chose, par exemple une chaîne, puis l'utilisez dans une comparaison, le bug apparaîtra: à l'intérieur de la fonction: falsee = "false"
et dans le if- Instruction: if falsee (new CClass) = "true" alors
-> si la déclaration sera entrée.
Remarque: Bien que les non-solutions ne soient pas généralement acceptés comme réponses, des réponses partielles qui fournissent des informations supplémentaires ou plus d'isoler ou de définir un problème, comme cela, sont les bienvenus si un La question n'a pas encore été résolue autrement: "Aidez-nous à trouver une solution en recherchant le problème, puis contribuez les résultats de vos recherches et tout ce que vous avez essayé en tant que réponse partielle. De cette façon, même si nous ne pouvons pas le comprendre , la prochaine personne a plus à continuer. " ( source )
C'est en effet un bug de la version 64 bits de VBA7. Voici un exemple plus petit:
Someclass.cls:
False True
main.bas:
False False
Ceci imprime p>
Function ReturnFalse(o As Object) As Boolean ReturnFalse = False End Function Sub test() Debug.Print ReturnFalse(New SomeClass) If ReturnFalse(New SomeClass) Then Debug.Print "True" Else Debug.Print "False" End If End Sub
sur VBA 32 bits et
Private Sub Class_Terminate() End Sub
sur VBA 64 bits
Je pouvais trouver un Rapport sur cette erreur dans un poste UserVoice de presque trois ans ( https://excel.uservoice.com/forums/304921-excel-for-windows-desktop-application/suggestions/35735881 -Member-Calls-on-User-Objects-Bi ), mais il n'y a pas eu de réaction depuis lors. De plus, il n'y a apparemment pas de moyen "réel" accessible par l'utilisateur de signaler les bogues VBA à Microsoft. Tout cela est très frustrant, car nous avons quelques projets VBA qui doivent être en train de porter à 64 bits en raison de leurs exigences de mémoire.
Dans Excel O365 32 bits, je ne suis pas en mesure de reproduire votre problème. Rien n'imprime, et en ligne de ligne, chaque ligne s'exécute.
@RonRastfeld Je l'ai également essayé sur la version 32 bits sur un autre PC, je ne peux pas non plus le reproduire là-bas. Je viens également de demander à un collègue qui dirige également la version 64 bits, il a pu le reproduire.
Très étrange. N'aurait pas pensé que la "bitness" ferait une différence sur quelque chose comme ça.
Pour de nombreuses raisons, je ne fais toujours pas confiance à Excel 64 bits. Je ne le recommande jamais.
Pas de compétence VBA, mais cela pourrait-il avoir quelque chose à voir avec le «faux» mal orthographié comme «faux»?
@Curiousrabbit no. J'ai également testé le code avec d'autres noms de fonction. En fait, dans le projet sur lequel je travaillais lorsque j'ai trouvé le bug, cela s'est produit avec plusieurs fonctions différentes.
Peut-être que je n'ai tout simplement pas pris assez de café un lundi matin, mais n'est-ce pas simplement un malentendu de la façon dont "
si function () {}
" évalue? Vous lui demandez d'évaluer une fonction ici, et la fonction s'exécute correctement, donc elle imprime la boîte de dialogue que vous avez écrite. Il ne vérifie pas si False évalue àfalse
, seulement s'il évalue avec succès . Vous pouvez y mettre une affectation variable aléatoire qui n'a rien à voir avec les vraies booléens et les faux et cela vous donnerait la même sortie.@Tylerh non. La façon dont les stades IF VBA sont censées fonctionner est la suivante: Si la condition évalue à
true
, l'instruction est entrée. Si la condition évalue àfalse
L'instruction passe au suivantelseif
,else
ouse terminer si
, selon la première éventualité . (Bien sûr, ignorer les stades if imbriquées entresi false alors
et la partie suivanteelseif
...) Cela n'a rien à voir avec la fonction évaluant «avec succès». Si la fonction ne réussit pas, le programme lancera une erreur si aucune gestion d'erreur n'est en place.