Byref et Byval, je pensais avoir compris la différence et ben non !

excelutor

XLDnaute Nouveau
Bonjour,

Je reviens sur ce sujet qui a déjà remué beaucoup d'encre concernant l'utilisation de Byval et Byref dans les paramètres d'une fonction ou d'une procédure. A chaque fois que je lis des explications sur le sujet, je pense que j'ai compris et quand je me trouve confronté à un exemple concret où je suis obligé d'utiliser Byval sinon tout part en couilles, je m'aperçois que je n'ai rien compris. J'admets que je suis une burne mais, comme tout être humain, j'ai le droit de vouloir sortir de mon état de "burnitude".
Au commencement, je pensais, intuitivement, que Byval et Byref était une façon de dire: "tu pointes sur ce que désigne la valeur ou la valeur elle-même."
Par exemple, si t'as

Sub exemple(x as long, y as long)
Cells(1,1)=x*2
Cells(1,2)=y*3
End Sub

Sub Main()
z=5:t=8
Call exemple(z,t)
End Sub

Dans ce cas, t'as une erreur de type parce que comme, par défaut, les paramètres de la ma procédure sont Byref, il (l'interpréteur, le méchant dans cette histoire) n'accepte pas que tu lui donnes à manger des noms de variables z et t alors qu'il attend des valeurs qui sont des Long. Pour remédier à ce problème, tu changes la procédure exemple:
Sub exemple(ByVal x as long, ByVal y as long)
Cells(1,1)=x*2
Cells(1,2)=y*3
End Sub

Et là ça marche parce que, conformément à mon approche intuitive, il ne pointe pas directement sur la valeur mais son contenu. Mais ça, c'est la vision de simplet parce que quand je lis des explications exhaustive sur le sujet, on me parle de procédures appelantes et de procédures appelées et on me dit que des modifs de variables dans la procédure appelante entraineraient des modifs dans la procédure appelée ou pas selon qu'on utilise ByVal ou pas. J'ai rien compris et ça m'a donné mal de tête... Du coup, je me contente de comprendre des cas auxquelles je suis confronté.
Je vous en soumets un et toute explication sera bienvenue.

Considérons qu'on a un classeur Classeur1 avec une feuille Feuille1 et on considère les fonction et procédures suivantes:
Function example(wks As String, wki As String, cpt As Double) As Double
Dim wkf As Workbook
Set wkf = Workbooks(wks)
With wkf.Worksheets(wki)
prod = .Cells(1, 1) * cpt
End With
example = prod
End Function

Sub essai(wks As String, wki As String, ByVal cpt As Double)
Dim wkf As Workbook
Set wkf = Workbooks(wks)
With wkf.Worksheets(wki)
.Cells(2, 1) = example(wks, wki, cpt)
End With
End Sub

Sub Main()
Call essai("Classeur1.xlsm", "Feuille1", 100000)
End Sub

La fonction example récupère la valeur de la cellule A1 dans Feuille1 de Classeur1, la multiplie par cpt et la procédure essai l'affiche en A2. Rien de compliqué
Je mets ByVal cpt dans essai parce que j'utilise cpt en paramètre dans example pour son contenu et pas pour ce qu'il est (sans ByVal, ça part en couilles) mais pourquoi je ne suis pas tenu de mettre ByVal wks et ByVal wki en paramètres dans essai également puisque ce sont des String qui sont appelées dans example aussi pour leur contenu et pas pour ce qu'elles sont c'est-à-dire un ensemble de trois lettres qui n'a rien à voir avec de la lingerie affriolante.
Merci de vos explications
 
Dernière modification par un modérateur:

Caillou

XLDnaute Impliqué
Re : Byref et Byval, je pensais avoir compris la différence et ben non !

Bonjour,

Je n'ai pas forcement bien compris, mais une chose m'interpelle, dans la fonction "example" ne faut-il pas remplacer
compte = prod
par
example= prod

Caillou
 

excelutor

XLDnaute Nouveau
Re : Byref et Byval, je pensais avoir compris la différence et ben non !

Effectivement, il faut remplacer compte par example, ce que je viens de faire dans le texte initial. Bien vu, c'est une erreur de syntaxe mais le coeur du problème est ailleurs comme t'as pu le constater
 
Dernière modification par un modérateur:

Dranreb

XLDnaute Barbatruc
Re : Byref et Byval, je pensais avoir compris la différence et ben non !

Bonsoir.

La règle est simple: Mettez toujours ByVal … sauf :
1) - Si le paramètre correspond à une variable objet du programme appelant qui doit s'y retrouver initialisée suite à l'exécution de la procédure grâce à un Set effectué dessus, dedans. C'est un besoin extrêmement rare. Aussi partez plutôt du principe que pour une programmation correcte les objets doivent toujours être passés ByVal.
2) - Si c'est un tableau. Car il ne serait pas raisonnable de réaliser une copie de tout le tableau chaque fois qu'il est transmis. C'est donc toujours obligatoirement uniquement son adresse qui l'est.
3) - S'il correspond à une variable ni objet ni tableau du programme appelant, qui doit être modifiée dans celui ci s'il est modifié dans la procédure.

Autres précisions: Un paramètre ByVal n'est ni plus ni moins qu'une variable locale au même titre que celles déclarées dans la procédure, à ceci près qu'elle est initialisée par la procédure appelante, laquelle doit veiller à la conversion de type nécessaire pour cela de l'expression qu'elle transmet.
Un paramètre ByRef se traduit au final par une simple adresse. Le programme appelant n'a pas d'autre possibilité que de passer une variable du type exact approprié. Ce sera donc une variable externe et non locale, vu de la procédure.

Cela dit, bien que ce soit en principe incorrect, VBA accepte souvent une expression (telle qu'une constante, ou des termes séparés par des opérateurs) en tant que paramètre ByRef, pourvu qu'elle soit rigoureusement du même type que le paramètre, puisque la procédure appelante n'a pas d'autre ressource que de transmettre son adresse. Une constante String, comme "Feuille1", passera pour un ByRef As String, une constante Long, comme 100000, ne passera pas pour un ByRef As Double. Tandis que pour un ByVal, il peut faire la conversion pour aller installer une copie de son résultat, à domicile en quelque sorte, chez la procédure.

En espérant vous avoir éclairci les choses …
 
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 211
Messages
2 086 299
Membres
103 172
dernier inscrit
Aurelyan