Problème récurcivité EVALUATE
Bonjour a tous.213868
j'ai trouvé un soucis, qu'on a fini par clairement identifier / carractériser, mais sans explication ni solution.
a part recoder complètement Evaluate, je ne vois pas quoi faire.
voila ma fonction :
Sub Bouton_Cliquer() temp = InputBox("Formule, EN ANGLAIS (, au lieu de ;)", "ReadValue(A1,3)")
temp2 = Evaluate(CStr(temp))
MsgBox (temp3)
End Sub
Public Function ReadValue(valeur As Variant, Reference As Long) As Variant
'lis une des valeur d'une matrice textuelle
Dim Tableau() As String
Dim temp As Variant
If valeur = "" Then
ReadValue = ""
Exit Function
End If
'découpe la chaine en fonction des espaces " "
'le résultat de la fonction Split est stocké dans un tableau
'il faudra commencer par trier les données pour s'assurer qu'il n'y a pas de "coupe" entre guillemet (plus tard)
Tableau = Split(valeur, "|")
'boucle sur le tableau pour visualiser le résultat
Select Case Reference
Case Is <= 0
ReadValue = UBound(Tableau) + 1
'dans le cas négatif ou =0, retourne le NOMBRE de référence dispo
Case Else
If Reference > UBound(Tableau) + 1 Then Exit Function
temp = CStr(Tableau(Reference - 1))
'temp = ChangeLangueFormule(CStr(temp))
ReadValue = Evaluate(CStr(temp)) '<<<<======= c'est cette fonction qui plante.
'ReadValue = temp '<<<==== si on remplace par celle ci, ca marche/
'dans le cas positif, retourne le résultat de l'index
End Select
End Functionmettez ce code dans un module
le but est le suivant, si vous avez la cellule A1 où est écrit, par exemple :
12|24|Sum(D)|38
écrivez dans une cellule :
=ReadValue(A1, 1)
résultat : 12
=ReadValue(A1, 2)
résultat : 24
=ReadValue(A1, 4)
résultat : 38
le truc spécial, c'est
=ReadValue(A1, 3)
résultat : la somme de la colonne D
ok, si vous l'écrivez ainsi, en formule, tout marche, rien a redire.
toutefois, le soucis, c'est que dans mon code complet, je laisse l'utilisateur écrire lui même un texte "ReadValue"
pour reproduire le bug, donc, maintenant que vous avez vu que ma fonction ... fonctionne.
creez un bouton ou autre, et cette fois ci, utilisez la procédure bouton, pour entrer dans l'input box :
readvalue(A1,3)
en théorie, ca devrait marcher, et retourner la somme de D
=> ERREUR 2015 !
pourtant, c'est écrit en anglais, RAS.
essayez sur des valeurs sans formule, par exemple
readvalue(A1,1)
en théorie, ca devrait retourner 12
=> ERREUR 2015 Oo !!!
dans le doute, passez en commentaire la ligne du "evaluate" de ma fonction, pour mettre à la place celle au dessous.
code :
Sub Bouton_Cliquer() temp = InputBox("Formule, EN ANGLAIS (, au lieu de ;)", "ReadValue(A1,3)")
temp2 = Evaluate(CStr(temp))
MsgBox (temp3)
End Sub
Public Function ReadValue(valeur As Variant, Reference As Long) As Variant
'lis une des valeur d'une matrice textuelle
Dim Tableau() As String
Dim temp As Variant
If valeur = "" Then
ReadValue = ""
Exit Function
End If
'découpe la chaine en fonction des espaces " "
'le résultat de la fonction Split est stocké dans un tableau
'il faudra commencer par trier les données pour s'assurer qu'il n'y a pas de "coupe" entre guillemet (plus tard)
Tableau = Split(valeur, "|")
'boucle sur le tableau pour visualiser le résultat
Select Case Reference
Case Is <= 0
ReadValue = UBound(Tableau) + 1
'dans le cas négatif ou =0, retourne le NOMBRE de référence dispo
Case Else
If Reference > UBound(Tableau) + 1 Then Exit Function
temp = CStr(Tableau(Reference - 1))
'temp = ChangeLangueFormule(CStr(temp))
'ReadValue = Evaluate(CStr(temp)) '<<<<======= c'est cette fonction qui plante.
ReadValue = temp '<<<==== si on remplace par celle ci, ca marche/
'dans le cas positif, retourne le résultat de l'index
End Select
End Functionalors cette fois ci, les résultat :
readvalue(A1,1)
Retourne bien 12; cette fois ci, ca marche.
readvalue(A1,3)
Retourne "SUM(D)" mais sans l'appliquer. ca marche, mais c'est pas ce que je souhaite !
Conclusion :
impossible d'appliquer un EVALUATE depuis une fonction deja lancé par un EVALUATE.
comment contourner ce soucis ? comment appliquer mon évaluate au clic bouton pour obtenir le meme effet que si je l'avais entré dans une cellule en tant que formule ?
évidement, mon projet complet est bien plus complexe que ca, et donc, je dois avoir une fonction "universelle" de "readvalue" qui fonctionne et s'adapte à tout les cas.
ca fait 2 jours que je m'arrache les cheveux dessus, et je commence a sérieusement envisager de faire un traitement de chaine de carra pour décompiler en petit bout les formule pour les "callbyname" ... autrement dit ... recoder à la main evaluate. rien que ca.
si quelqu'un a la moindre solution, parce que là, je pete un cable.
en vous remerciant par avance.
cordialement.
Bonjour,
deux petit question :
- la valeur n°3 est toujours un "SUM"
- la valeur retourné est affecter a une case ou juste un variable tmp ?
bonjour
ca peut etre SUM, ou n'importe quoi. d'ou l'interet d'un "evaluate" qui peu permettre de calculer tout les cas possible.
le retour peut etre soit une variable (si appelé par un evaluate depuis ma macro), soit un résultat affiché dans une cellule si c'est l'utilisateur lui meme qui l'exploite.
j'ai compilé le tout dans un fichier pour que ca soit plus explicite
j'ai la version BRUTE et j'espere que quelqu'un vous donnera mieux ^^
je prend le SUM(D) comme exemple
voila ma proposition :
si c'est a mettre directement dans une cellule : récupere "sum(d)" comme vous l'avez deja fait et le concatener avec un = sa donne :
"=" & readvalue(A1,3)si c'est pour un variable : couper "sum(D)" en deux partie => "SUM" et "D" ensuite appliquer une simple addition si c'est SUM ou autre
ex :
dim f as String
dim v as String
f = "SUM"
v = "D" 'évidament pour vous sa sera un fonction qui recupere la chaine entre parenthèse
if f = "SUM" then 'utiliser select case sera mieux ici
Application.Sum(Range(v & 1 ).EntireColumn)
end if bonjour
la solution de passer par une cellule plutot que evaluate
donc ajouter en fin de readvalue
range("A1").value = "=sum(D:D)"
readvalue = range("A1").value
fonctionne. seulement, c'est le cas comme ca, ici, mais ca rends ma fonction non universelle, peu transposable. et de fait, dans l'usine a gaz dans laquelle elle est utilisé, c'est juste "mort". ca marche pas.
quand a la seconde, comme je ne sais pas si je vais avoir du sum, ou autre chose, ou meme des fonctions perso, il faudra s'adapter a chaque cas. comme les formule peuvent en plus etre imbriqué, c'est encore pire.
bref, ca revient a ce que j'envisage en esperant fortement ne pas avoir a le faire : recoder integralement "evaluate" moi meme a grand coup de traitement de chaine et de callbyname.
je cherche une solution plus elegante, ou une explication a mon soucis, voir un contournement efficace.
cordialement