XL 2016 Pourquoi Evaluate s'exécute toujours 2 fois ?

Lu76Fer

XLDnaute Occasionnel
Bonjour,

J'ai testé sur différente version d'excel et le résultat est le même :
VB:
Function TestEval() As Boolean
    Debug.Print "TEST EN COURS ..."
    TestEval = True
End Function

Sub TestAppel()
Dim b As Boolean
    b = Evaluate("TestEval()")
    'b = [TestEval()] 'Même résultat
End Sub
Résultat :
TEST EN COURS ...
TEST EN COURS ...

Qui aurait des explications ou un lien pour m'éclairer ?
 

Lu76Fer

XLDnaute Occasionnel
re
bonsoir
il n'y a pas d'effet kisskool qui tienne
en faisant comme tu fais tu l'apelle deux fois tout simplement
1 fois dans l'appel lui meme et une fois l'instance de la fonction elle même
la fois1 c'est entre les parenthese
la fois 2 c'est le return de B
Bonsoir PatrickToulon,
Je ne vois pas mais voici un exemple simplifié et même résultat, cela s'affiche 2 fois :
VB:
Function TestEval2() As Boolean
    Debug.Print "TEST EN COURS ..."
End Function

Sub TestAppel2()
    Evaluate ("TestEval2()")
End Sub
Il n'y a que si on appel la fonction depuis une feuille =TestEval2() que la fonction ne s'exécute qu'une seule fois.
 

Lu76Fer

XLDnaute Occasionnel
Je vois une solution et difficile d'utiliser Evaluate directement sans que celui-ci ne s'exécute deux fois de suite.
VB:
Function TestEval() As Boolean
    Debug.Print "TEST EN COURS ..."
    TestEval = True
End Function

Sub TestAppel2()
Dim b As Variant
    Range("A1") = "=TestEval()"
    DoEvents
    b = Range("A1")
    Range("A1") = ""
End Sub
Dommage que cette fonction ne réagisse pas mieux ... Elle est disponible après tout, pourquoi l'avoir laissé à disposition des utilisateurs si on ne peut pas l'utiliser librement ?
Personnellement, je vois juste un bug de plus.
 

Katido

XLDnaute Occasionnel
Bonjour,

Evaluate n'est effectivement pas fait pour ça, mais par exemple pour faire :
debug.Print Evaluate("3 * 5")
ce qui donne bien 15

Ou encore :
Public Sub Appel()
Debug.Print Evaluate("3 * Increment(5)")
End Sub

Public Function Increment(i%)
Test = i + 1
End Function
ce qui donne bien 18.

Je n'aurais jamais imaginé faire un print dans une fonction appelée avec Evaluate, mais quand on lance Evaluate("Test()" depuis la fenêtre d'exécution avec :
Public Function Test()
Debug.Print "aaa"
End Function
le double print est quand même déroutant.
 

patricktoulon

XLDnaute Barbatruc
re
non ce n'est pas déroutant c'est normal
evaluate fait l'operation pour l'evaluer
comme c'est une fonction a l'interieur du bin du classeur elle est donc evaluer et executer
vba te renvoie donc a un event propagation

event propagation
lorsque la fonction est lancé par evaluate
elle est appelée DANS EVALUATE et donc par conséquent dans vba
evaluate est issue des bonne vielle macro 4 qui ne fait pas partie de vba

en fait pour la faire courte
la fonction remonte jusqu'au premier parent c'est à dire au niveau module

et oui comme cette fonction est sensé faire un calcul (ou autre ) il faut bien qu'elle soit executé pour que son return renvoie le STRING DU RETURN
CAR EVALUATE EVALUE UN STRING ELLE EVALUE PAS LA FONCTION ELLE MËME

c'est pigé?

pour vous faire bien comprendre la notion de macro 4 et vba
il vous suffit de déclencher une erreur dans la la fonction
et de demamander msgbox evaluate("nom de la fonction()")
vous verrez non seulement vous n'aurez pas de message d'erreur dans la fonction mais vous n'aurez rien non plus au resultat de evaluate c'est à dire pas de msgbox
j'ajoute une ligne dans la fonction "aa"(qui ne veut rien dire et qui va me declecncher devrait me déclencher une erreur
vous verrez il ne se passe rien
VB:
Function TestEval2() As Boolean
  aa
  Debug.Print "TEST EN COURS ..."
End Function

Sub TestAppelevaluate()
    MsgBox Evaluate("TestEval2()")
End Sub

Sub TestAppelenormal()
    MsgBox TestEval2()
End Sub

j'espère que cet exemple va vous aider à comprendre
tester les deux appels ;) ;)
 
Dernière édition:

Lu76Fer

XLDnaute Occasionnel
Bonjour,

Evaluate n'est effectivement pas fait pour ça, mais par exemple pour faire :

ce qui donne bien 15

Ou encore :

ce qui donne bien 18.

Je n'aurais jamais imaginé faire un print dans une fonction appelée avec Evaluate, mais quand on lance Evaluate("Test()" depuis la fenêtre d'exécution avec :

le double print est quand même déroutant.
Oui cela reste déroutant même si il est vrai que c'est de l'interprétation PatrickToulon (CAR EVALUATE EVALUE UN STRING ELLE EVALUE PAS LA FONCTION ELLE MËME) et les erreurs ne sont pas remontées.
Dans mon cas je désire simplement lancer une fonction dont je ne connais pas forcément le nom et j'ai trouvé une autre solution du coup en évitant d'exécuter le code au premier passage :
VB:
Private Setting As Boolean

Function TestEval3() As Boolean
    If Setting Then Setting = False: Exit Function
    Debug.Print "TEST EN COURS ..."
    TestEval3 = True
End Function

Sub TestAppel3()
Dim b As Boolean
    Setting = True
    b = Evaluate("TestEval3()")
    Debug.Print "Hello World !! Retour = " & b
End Sub
J'ai dû rajouter la variable de module Setting mais j'obtiens le résultat voulu, le code ne s'exécute qu'une fois. Le retour est bien récupérer, et la séquence d'instruction est exécuté dans l'ordre.
 

Katido

XLDnaute Occasionnel
Re,
Si, c'est déroutant car même s'il n'y a rien à évaluer ni à retourner, elle est "exécutée" 2 fois.

Voici un programme tout simple :
Public z as Integer

Public Sub Test()
z = z + 1
End Sub
Chaque fois qu'on lance Evaluate "Test()" dans la fenêtre d'exécution, la valeur de z est incrémentée 2 fois (on obtient 2, 4, 6, etc.)

En fait, la fonction n'est pas exécutée de façon standard.

On peut ajouter une instruction Stop, ça ne lui fait rien (elle marche encore 2 fois)
S'il y a une erreur (par exemple division par 0), elle n'est exécutée qu'une fois !!!

Renvoie z+2 à chaque Evaluate :
Public z As Integer, y As Integer

Public Sub Test()
z = z + 1
y = 1
End Sub

Renvoie z+2 à chaque Evaluate :
Public z As Integer, y As Integer

Public Sub Test()
Stop
z = z + 1
y = 1
End Sub

Renvoie z+1 à chaque Evaluate :
Public z As Integer, y As Integer

Public Sub Test()
z = z + 1
y = 1 / 0
End Sub

Il n'y a aucune raison de faire un Evaluate dans ce cas où il n'y a rien à ramener, mais ce fonctionnement n'est quand même pas très catholique.
Donc n'utiliser Evaluate que pour évaluer une chaine.
 

Lu76Fer

XLDnaute Occasionnel
Re,
Si, c'est déroutant car même s'il n'y a rien à évaluer ni à retourner, elle est "exécutée" 2 fois.

Voici un programme tout simple :

Chaque fois qu'on lance Evaluate "Test()" dans la fenêtre d'exécution, la valeur de z est incrémentée 2 fois (on obtient 2, 4, 6, etc.)

En fait, la fonction n'est pas exécutée de façon standard.

On peut ajouter une instruction Stop, ça ne lui fait rien (elle marche encore 2 fois)
S'il y a une erreur (par exemple division par 0), elle n'est exécutée qu'une fois !!!

Renvoie z+2 à chaque Evaluate :


Renvoie z+2 à chaque Evaluate :


Renvoie z+1 à chaque Evaluate :


Il n'y a aucune raison de faire un Evaluate dans ce cas où il n'y a rien à ramener, mais ce fonctionnement n'est quand même pas très catholique.
Donc n'utiliser Evaluate que pour évaluer une chaine.
Oui en cas d'erreur le code est interrompu ! Il est vrai que cela reste plutôt casse-gueule surtout qu'on a pas de retour d'erreur. Mais bon c'est bien de savoir qu'elles sont les possibilités techniques ;) .

Merci à tous de votre participation à la discussion.
 

Discussions similaires

Statistiques des forums

Discussions
315 111
Messages
2 116 340
Membres
112 720
dernier inscrit
henri marc michel