Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1786 connectés 

  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] Le passage de parametre par référence ne marche pas???

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[VBA] Le passage de parametre par référence ne marche pas???

n°430509
Yoyo@
Posté le 17-06-2003 à 14:20:51  profilanswer
 

Salut !
 
Y a un truc que je comprends pas...
 
J'exécute le code suivant :
 
Dim i As Integer
i = 1979
RunTest (i)
MsgBox i
 
Private Sub RunTest(ByRef essai As Integer)
  essai = 2003
End Sub
 
Etant donné que je fais un passage de parametre par référence, j'aurais espéré que mon MsgBox affiche 2003, mais ce n'est aps le cas !
 
De plus, j'ai lu que le passage de paramètre se fait par défaut en VBA, donc a priori, je n'aurais meme pas eu à mettre de ByRef...
 
Où se trouve la vérité?

mood
Publicité
Posté le 17-06-2003 à 14:20:51  profilanswer
 

n°430587
drasche
Posté le 17-06-2003 à 14:44:41  profilanswer
 

enlève les parenthèses à ton appel de RunTest. Ou alors met un Call devant.


Message édité par drasche le 17-06-2003 à 14:45:51

---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
n°430678
Yoyo@
Posté le 17-06-2003 à 15:26:35  profilanswer
 

Arf, ca marche !!! Merci ;)
 
Je n'ai jamais vraiment compris pouruqoi elever les parenthèses fait parfois marcher les choses avec VBA... Ca me fait déja souvent le coup avec une MsgBox ! C'est quoi la diff entre avec et sans parenthèses?

n°430682
drasche
Posté le 17-06-2003 à 15:29:00  profilanswer
 

Yoyo@ a écrit :

Arf, ca marche !!! Merci ;)
 
Je n'ai jamais vraiment compris pouruqoi elever les parenthèses fait parfois marcher les choses avec VBA... Ca me fait déja souvent le coup avec une MsgBox ! C'est quoi la diff entre avec et sans parenthèses?


théoriquement, il n'y en a pas :D
 
mais perso je mets toujours un Call devant (qui force implicitement les parenthèses).  Je ne m'étais donc jamais aperçu de ce comportement bizarre jusqu'à ce qu'un collègue me soumette ce problème.


---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
n°430708
Yoyo@
Posté le 17-06-2003 à 15:47:43  profilanswer
 

drasche a écrit :


théoriquement, il n'y en a pas :D
 
mais perso je mets toujours un Call devant (qui force implicitement les parenthèses).  Je ne m'étais donc jamais aperçu de ce comportement bizarre jusqu'à ce qu'un collègue me soumette ce problème.


 
Ba nan, justement, tu viens de me dire que Call = pas de parenthese = vrai appel de fonction avec passage par référence !
 
Bref, c'est vrai que c'est chelou !
 
C'est pareil avec un msgbox :
 
msgbox ("Ca marche pas!", vbInformation, "Oh ben merde alors!" ) ne marchera pas, alors que ca marchera si tu enleves les parentheses !

n°430712
drasche
Posté le 17-06-2003 à 15:50:44  profilanswer
 

:non:
 
Call Msgbox("Ca marche pas!", vbInformation, "Oh ben merde alors!" )
 
ou  
 
msgbox "Ca marche pas!", vbInformation, "Oh ben merde alors!"
 
sont les deux styles d'appel corrects.  Il va de soit que pour une fonction dont tu veux récupérer la valeur, tu seras obligé de mettre les parenthèses.  Donc autant les mettre partout, c'est ce que je préconise toujours [:spamafote]


---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
n°431009
Yoyo@
Posté le 17-06-2003 à 19:19:40  profilanswer
 

Imaginons que je veuilles récupérer une valeur en retour de fonction, utilisant un passage par référence...
 
varRetour = fonction param1
 
ne marchera pas (il faut les parentheses je suppose s'il y a une valeure de retour)
 
varRetour = fonction(param1)
 
ne marchera pas (pas de passage par référence)!
 
Donc, il ne reste que :
 
varRetour = call fonction(param1)
 
Tu es sur que ca marchera ca???
 
Ca me parait louche !
 
Yoyo*

n°431028
drasche
Posté le 17-06-2003 à 19:27:10  profilanswer
 

hey non pour une fonction ya qu'une manière:
 
varRetour = MaFonction(param1)
 
sinon tu manges une erreur de compil (enfin si tu fais Ctrl-F5, ce que je fais systématiquement aussi ;))


---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
n°431195
MagicBuzz
Posté le 17-06-2003 à 21:08:38  profilanswer
 

Pour info, Call fait un appel assynchrone à la sub. Mais vu que les procédures VB ne supportent pas le mode assynchrone, elles tournent normalement en mode synchrone même dans un call.
 
Sinon, niveau théorique, au contraire, VB est bien plus propre que la plupart des autres langages au niveau de cette gestion de parenthèses ou non.
 
B-A-BA de l'algo :
 
Une procédure FAIT quelquechose.
Une fonction VAUT quelquechose.
 
A partir de là, il y a donc une différence radicale entre une SUB et une FONCTION (en ADA ou en PASCAL, le mot PROCEDURE est conservé)
 
M$, ayant fait le VB principalement pour les novices voulant faire simplement mais pas trop salement des petits programmes, a décidé de faire la différence entre des deux types de procédures directement au niveau de la syntaxe.
 
Le C quant-à lui, par exemple, a décidé qu'une procédure était une fonction qui ne renvoyait rien, ce qui, syntaxiquement parlant est beaucoup plus crade, puisqu'on ne fait pas de différence entre les deux, que ce soit à l'appel, mais surtout à la déclaration.
 
En VB, si tu as une ligne :
 
b(c)
 
ou
 
a = b c
 
Alors il y a un sérieux problème de conception dans le programme.
 
La première ligne va fonctionner, mais b étant une fonction, et une fonction étant sensée NE FAIRE AUCUN TRAITEMENT, UNIQUEMENT RENVOYER LE RESULTAT D'UN CALCUL, faire un appel à une fonction sans récupérer de variable en sortie est une hérésie, la ligne DOIT pouvoir être purement et simplement supprimée sans qu'il y ait le moindre problème.
 
La seconde va carrément planter, car une procédure ne renvoit rigoureusement rien.

n°431197
MagicBuzz
Posté le 17-06-2003 à 21:12:07  profilanswer
 

PS: une variable "byref" n'est pas retournée. Elle est modifiée dans le programme principal.
 
Exemple :
 

sub test(byref mavar as string)
    mavar = "Nouvelle valeur"
end sub


 
Puis dans le prog principal :
 

dim toto as string
toto = "Première valeur"
msgbox toto
test toto
msgbox toto


Message édité par MagicBuzz le 17-06-2003 à 21:12:24
mood
Publicité
Posté le 17-06-2003 à 21:12:07  profilanswer
 

n°431418
Yoyo@
Posté le 18-06-2003 à 00:34:03  profilanswer
 

Merci pour ces explications...
 
Donc, si je comprends bien, un appel sans parentheses correspond à un appel de procédure, alors qu'avec les parentheses, c'est un appl de fonction !
 
D'autre part, ce n'est pas possible de faire un appel de fonction et de récupérer une valeur tout en utilisant des références lors du passage de variable?
 
car passage par référence = faire qqchose = procédure
récupérer une valeur = fonction
 
=> incompatible??
 
Je ne suis pas sur d'avoir tout saisi in fact !

n°431430
MagicBuzz
Posté le 18-06-2003 à 00:57:05  profilanswer
 

sisi, "tout" est possible.
 
par contre, les variables byref sont à éviter au maximum.
 
c'est très sale, et c'est rapidement le bordel.
 
généralement, on le les utilise que lorsqu'on doit bosser sur un objet par exemple, ou lorsqu'on doit trier un tableau (ce serait con de faire un algo super optimisé si on doit créer un tableau local pour la fonction, le modifier, le récupérer, et enfin écrser l'ancien. autant modifier l'ancien directement ;)

n°431436
MagicBuzz
Posté le 18-06-2003 à 01:03:45  profilanswer
 

bah disons que dans l'absolu une procédure doit faire quelquechose.
 
par exemple, tu passes en paramètre un tableau, et ça s'affiche le tableau mis en forme à l'écran.
 
une fonction, elle, va faire plutôt un calcul.
 
par exemple, tu lui passe un tableau, et elle te retourne la valeur maximale contenue dans le tableau.
 
mais imagine par exemple une procédure qui doit ouvrir un fichier et écrire dedans.
la procédure peut ne pas aboutir parceque le fichier est en lecture seule ou non trouvé. a ce moment, deux solutions :
-> solution "propre" : tu raises une erreur. c'est le plus propre, mais le plus chiant aussi à gérer.
-> solution classique : tu fais une fonction  qui va faire l'oppération, et retourner un flag indiquant si elle a échoué ou non.
-> solution merdique (mais très utilisée quand on fait un objet) : tu fais une prodécure. au lieu de raiser une erreur tu met à jour une variable globale qui est en fait une propriété de l'objet. par exemple, la méthode "movenext" de ADO et la propriété "EOF", qui se met à true quand movenext échoue parcequ'elle a atteinds la fin du recordset et qu'elle a donc échouée.

n°431604
Yoyo@
Posté le 18-06-2003 à 10:03:23  profilanswer
 

Bah moi, dans mon cas, je voulais une fonction (mais c'est plutot une procédure selon la terminologie que tu emploies) qui prennes une String en paramètre et complète cette string !  
 
Ce qui m'intéressait la dedans étauit justement de passer la String en paramètre par référence, pour éviter que l'appli la copie 2 fois (passage In et passage Out)! De plus, je voulais que cette proc/fonction me retourne une Booléen True ou False pour dire si elle a échoué ou pas !
 
Donc, j'aurais voulu un truc du genre :
 

Code :
  1. Private Function CompleteString(ByRef stringToComplete as String)


 
Mais a priori, ca ne marche pas, ca passe quand meme la String par référence !

n°431622
MagicBuzz
Posté le 18-06-2003 à 10:15:15  profilanswer
 

Utilise pas byref, mais byval...
 

function completeString(stringToComplete as string)
   completeString = stringToComplete & " completée"
end function
 
dim test, test2 as string
test = "ma chaîne"
 
test2 = stringToComplete(test)
 
msgbox(test2)


 
PS: msgbox prends infiddérement des parenthèses ou non, puisque c'est une fonction overriddée par une procédure, puisque selon les paramètres, elle renvois des données ou non.

n°431636
Yoyo@
Posté le 18-06-2003 à 10:24:45  profilanswer
 

MagicBuzz a écrit :

Utilise pas byref, mais byval...
 

function completeString(stringToComplete as string)
   completeString = stringToComplete & " completée"
end function
 
dim test, test2 as string
test = "ma chaîne"
 
test2 = stringToComplete(test)
 
msgbox(test2)


 
PS: msgbox prends infiddérement des parenthèses ou non, puisque c'est une fonction overriddée par une procédure, puisque selon les paramètres, elle renvois des données ou non.


 
Mais avec ce que tu me donnes, stringToComplete sera donc une string qui va etre copiée et recopiée, donc, ce sera moins efficace?

n°431662
MagicBuzz
Posté le 18-06-2003 à 10:42:09  profilanswer
 

Quand il s'agit d'une string, non, ça change rien.
 
byref n'est vraiment utile que pour des données volumineuses (et d'ailleurs il est implicite dans ce cas), telles que des tableaux, des arbres ou des objets.
 
Deplus, là la string n'est recopiée qu'une fois, puisque l'affectation dans la fonction n'est pas une affectation, c'est juste la moyen tout pourri qu'a VB de faire un "return".

n°431667
Yoyo@
Posté le 18-06-2003 à 10:52:55  profilanswer
 

D'accord !
 
Donc, tu veux dire qu'implictement, VB recopie l'adresse de la String et non la String elle meme? Si c'est le cas, alors oui, c'est efficace !
 
Merci,
 
Yoyo*
 
 :hello:

n°431680
MagicBuzz
Posté le 18-06-2003 à 11:08:30  profilanswer
 

Bah disons que pour le retour, oui.
 
Byval ne duplique les données que pour l'entrée des paramètres.
 
Pour la sortie, une fonction retourne un pointeur sur la variable retournée en fait. (du moins, pour les strings et les tableaux, puisque ce sont des pointeurs à la base, pour un entier, c'est la valeur qui est recopiée, puisque c'est pas plus gros qu'un pointeur ;)


Message édité par MagicBuzz le 18-06-2003 à 11:09:12
n°431729
Yoyo@
Posté le 18-06-2003 à 11:37:31  profilanswer
 

Donc, le passage de ma String en ByVal se révèle inefficace pour l'entrée du paramètre car copie...  :sweat:  
 
Dommage que je nepuisse le faire par référence si ma fionction doit retourner une valeur !
 
merci pour toutes ces infos en tout cas !
 
Yoyo*

n°431831
drasche
Posté le 18-06-2003 à 12:52:54  profilanswer
 

si tu peux toujours passer TOUT CE QUE TU VEUX par référence.  Le problème se situe plus au niveau propreté et logique du code qu'autre chose, mais dans l'absolu, rien ne t'en empêche ;)
 
pour ma part, je passe quasi toujours les strings par référence histoire d'éviter la recopie justement :/


---------------
Whichever format the fan may want to listen is fine with us – vinyl, wax cylinders, shellac, 8-track, iPod, cloud storage, cranial implants – just as long as it’s loud and rockin' (Billy Gibbons, ZZ Top)
n°431879
Yoyo@
Posté le 18-06-2003 à 13:57:34  profilanswer
 

Bah alors rxplique moi comment utiliser une fonction myFunc (utilisation de la valeur de retour et passage par référénce !)

n°431897
MagicBuzz
Posté le 18-06-2003 à 14:25:33  profilanswer
 

C'est quoi le problème avec ta chaîne ?
 
Elle fait 20 Go ?
 
Tu boucles dessus un million de fois ?
 
De toute façon, en VB, dès que tu utilises le signe "&", il recopie toute la chaîne à un autre endroit pour faire la concaténation, donc si tu cherche à avoir de bonnes perfs, c'est pas en VB qu'il faut bosser.
 
Très clairement, même avec des chaînes de 50 Mo, tu ne vois aucune différence notable entre byref et byval.
 
Arrête de te poser des question existencielles comme ça.
 
Riens que de la SDRAM PC133, y'a une bande passante de 800 Mo/s, alors que tu copies une fois de plus ou une fois de moins une chaîne de 100 caractères, ça fa changer un quarte de pouillème de microseconde au final...


Message édité par MagicBuzz le 18-06-2003 à 14:26:37
n°432048
Yoyo@
Posté le 18-06-2003 à 16:33:05  profilanswer
 

Bien sur que sur ce cas précis, je n'ai pas forcément besoin de mon ByRef !
 
maintenant :
- D'une aprt, je suis assez perfectionniste, et j'aime bien optimiser les choses quand ca ne demande pas trop d'effort(question de propreté!)
- Le jour où j'aurai vraiment besoin d'un passage par référence, si je n'ai aps ma réponse today, alors je risque d'être en galère...
 
Je ne sis pas du genre attentiste : quand je me pose une question, je cherche la réponse, y a que comme ca qu'on progresse, non !
 
Yoyo*

n°432191
MagicBuzz
Posté le 18-06-2003 à 17:39:24  profilanswer
 

Pour moi, un perfectionniste est quelqu'un qui fait un code propre. :p
 
Et un code propre est souvient aussi optimisé que le bidouilleur du dimanche qui privilégie l'optimisation à un algo propre et performant ;)
 
Sinon, franchement, je vois pas où tu bloques avec le byref, il est pourtant tout ce qu'il y a de plus standard, c'est pareil avec tous les langages :??:
 
Bon, un dernier exemple :
 


function test1(byref mastring as string, byval addon as string) as integer
   on error resume next
   mastring = mastring & addon
   test1 = err.number
   on error goto 0
end function


 
Cette fonction prends en paramètre deux chaînes.
Elle ajoute la seconde à la première byref, c'est à dire qu'elle va changer la variable passée comme premier paramètre.
Et la fonction retourne le code d'erreur en cas d'erreur (par défaut, 0)
 
Là, t'as tout pour faire un truc presque pas trop proc. (perso, je hais les byref, je les utilise au minimum).
 
A savoir que le second paramètre est en byval.
 
Donc d'un point de vue logique, la valeur sera recopiée en mémoire lors de l'accès à la fonction.
 
Mais le compilo VB, comme la plupart des compilos, n'est pas dupe. Il voit bien que tu n'écris pas dedans. Donc implicitement, lors de la compilation, c'est un byref qui sera utilisé.
 
Mais il est extrêment important que dans le code tu utilises un byval. En effet, c'est le seul moyen d'éviter des gros bugs super chiant à trapper, genre tu écris sans faire attention dans un paramètre qui ne doit pas être modifié (genre les gros malins qui prennent en paramètre des variables nommées "i" par exemple... à la première boucle il foutent par terre leur programme avec un byref)

n°432389
Yoyo@
Posté le 18-06-2003 à 21:01:40  profilanswer
 

MagicBuzz a écrit :

Pour moi, un perfectionniste est quelqu'un qui fait un code propre. :p
 
Et un code propre est souvient aussi optimisé que le bidouilleur du dimanche qui privilégie l'optimisation à un algo propre et performant ;)
 


 
Je suis d'accord avec toi, mais chaque chose en son temps !
 
En fait, je viens de comprendre : quand je faisais :
 

Code :
  1. Dim i As Integer
  2. i = 1979
  3. RunTest (i)
  4. MsgBox i
  5. Private Sub RunTest(ByRef essai As Integer)
  6.   essai = 2003
  7. End Sub


 
ca foirait !
 
Tout celà parce que jemettais les parenthèses, alors qu'en fait, un "bon" appel de procédure se fait sans parenthèses ! Par contre, je viens de tester, et en utilisant une fonction avec des parenthèses, ca marche !
 
Conclusion :
- Pour les fonctions : utiliser des parenthèeses lors de l'appel, et récupérer la valeur de retour
- Pour les procédures, ne pas utiliser de parenthèses lors de l'appel (et of course, y a rien à récupérer au retour)
 
Sur ces basses, tout marchera bien !
 
La logique derrière tout ca est un peu bancale je trouve (ou alors je n'ai pas saisi toute la finesse), mais bon, à l'utilisation, ca se tient!
 
Merci à vous (surtout à toi MagicBuzz pour tes éclaircissements théoriques que j'apprécie beaucoup !)
 
Yoyo*
 

n°432466
MagicBuzz
Posté le 18-06-2003 à 22:17:38  profilanswer
 

Yoyo@ a écrit :


La logique derrière tout ca est un peu bancale je trouve (ou alors je n'ai pas saisi toute la finesse), mais bon, à l'utilisation, ca se tient!


Relis bien mes premiers posts, j'avais justement expliqué en détail le pourquoi du comment de cette syntaxe "bancale" (qui même si elle est bizarre, est plus propre que celle du C qui fait pas la différence entre fonction et procédure.

n°432471
Yoyo@
Posté le 18-06-2003 à 22:26:10  profilanswer
 

MagicBuzz a écrit :


Relis bien mes premiers posts, j'avais justement expliqué en détail le pourquoi du comment de cette syntaxe "bancale" (qui même si elle est bizarre, est plus propre que celle du C qui fait pas la différence entre fonction et procédure.


 
Oui, oui, j'avais relu, et en gros, c'est ce qui permttait à Access de faire une "surcharge" de fonction et de faire la différence entre une procédure et une fonction ! Une astuce quoi !

n°432477
MagicBuzz
Posté le 18-06-2003 à 22:32:32  profilanswer
 

Nan nan, je parle de ça :
 
Une procédure FAIT quelquechose.
Une fonction VAUT quelquechose.
 
VB fait donc la distinction entre les deux, afin que le code soit plus explicite.

n°433028
Yoyo@
Posté le 19-06-2003 à 14:43:13  profilanswer
 

Enfin, je pense que la diférence, ici, reste plus théorique que pratique !
 
Je pense que nombre d'entre nous utilisent des fonctions qui VALENT et FONT quelque chose à la fois !  
 
Ce n'est peut etre pas bon sémantiquement, mais bon...

n°433130
MagicBuzz
Posté le 19-06-2003 à 15:51:16  profilanswer
 

D'un point de vue algo, c'est une hérésie.
 
Mais après, pour des raisons de rendement, on préfère généralement moins réfléchir et faire un truc moins propre, mais qui marche, plutôt que de faire un truc nickel crhome en 6 mois ;)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  VB/VBA/VBS

  [VBA] Le passage de parametre par référence ne marche pas???

 

Sujets relatifs
[VBA excel] composant ActiveX[excel VBA] test valeur numérique
[VBA] Dernière ligne d'un fichier texte.[VBA] Trouve la derniere cellule non-vide d'une colonne.
[VBA excel] rouddown et nombres décimaux[PHP] erreur lors du passage php -> html
[VBA + Access] Récupérer tous les champs de mes tables Access...[PHP & JS] Passage de variables ...? [RESOLVU]
[VBA] Lire à partir d'un fichier texte[VBA] - Incompatibilité Excel 2000 --> Excel Xp.
Plus de sujets relatifs à : [VBA] Le passage de parametre par référence ne marche pas???


Copyright © 1997-2018 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR