Nov.
Une fonction qui utilise l'argument ParamArray permet de transmettre à cette fonction un nombre d'arguments variables tout en standardisant sa signature.
Ex:
Cette fonction qui utilise l'argument paramArray pourra alors être appelée indifféremment par
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 Function Multiply ( ParamArray args() as Variant dim x as Long, Ret as long if ubound(args)>=0 then ret=1 For x=lbound(args) to ubound(args) ret=ret*args(x) next endif Multiply=ret End Function
i=Multiply(2,7)
ou par
i=Multiply(2,7,11,14)
=> L'argument ParamArray convertit la liste des paramètres transmis en un tableau d'arguments à une dimension.
Problématique du passage d'arguments
Quid de l'appel imbriqué de 2 fonctions utilisant l'argument ParamArray ?
La 1ère idée qui vient à l'esprit serait de transmettre tel quel le tableau récupéré à la seconde fonction -
par exemple
ce qui induit évidemment une erreur puisque l'argument récupéré ne sera plus un tableau à 1 dimension de n arguments
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 i=ComplexeFunct(2,3,4) 'avec Function ComplexFunct(ParamArray args()) ComplexFunct=Multiply(args) End Function
... mais un tableau à 1 seul élément contenant un tableau de n arguments unique de la forme args(0)().
En cas d'imbriquements plus complexes le tableau sera sera du type args(0)(0)(0)()...
Solution pour gérer la propagation des arguments
La solution consiste à utiliser la fonction CallByName
en l'appelant par le biais d'un artifice (InvokeHookArray) délivré par le librairie TLI (TypeLibInfo) .
CallByName impose toutefois deux contraintes :
- la fonction appelée doit appartenir à un module object,
- elle doit être publique.
Exemple de propagation d'un argument paramArray
L'exemple suivant est inspiré de l'exemple extrait de l'adresse suivante http://www.devx.com/tips/Tip/15422.
'Soit 1 Form - Autoredraw:true
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 Option Explicit Private Sub Form_Activate() Dim i As Long, a As Long, b As Long, c As Long a = 2: b = 4: c = 5 Me.Print "Multiply : " & a & " x " & b & " x " & c & " = " & ComplexFunct(1, a, b, c) Me.Print "Divise : " & a & " / " & b & " / " & c & " = " & ComplexFunct(2, a, b, c) End Sub Private Function ComplexFunct(oper As Long, ParamArray args() As Variant) Dim v As Variant v = args Select Case oper Case 1 ComplexFunct = CallByNameEx(Me, "Multiply", VbMethod, v) Case Else ComplexFunct = CallByNameEx(Me, "Divise", VbMethod, v) End Select End Function Public Function Multiply(ParamArray args() As Variant) Dim x As Long, Ret As Long If UBound(args) >= 0 Then Ret = 1 For x = LBound(args) To UBound(args) Ret = Ret * args(x) Next End If Multiply = Ret End Function Public Function Divise(ParamArray args() As Variant) Dim x As Long, Ret As Double If UBound(args) >= 0 Then Ret = args(LBound(args)) For x = LBound(args) + 1 To UBound(args) Ret = Ret / args(x) Next End If Divise = Ret End Function ' INVOKE CALLBYNAME ' '===========================================' Private Function CallByNameEx(Obj As Object, ProcName As String, CallType As VbCallType, Optional vArgsArray As Variant) Dim oTLI As Object Dim ProcID As Long, numArgs As Long, i As Long Dim v() Set oTLI = CreateObject("TLI.TLIApplication") ' Récupérer l'adresse de la fonction ' ProcID = oTLI.InvokeID(Obj, ProcName) ' Aucun paramètre transmis ' If IsMissing(vArgsArray) Then CallByNameEx = oTLI.InvokeHook(Obj, ProcID, CallType) Else ' Inverser les paramètres du tableau ' If IsArray(vArgsArray) Then numArgs = UBound(vArgsArray) ReDim v(numArgs) For i = 0 To numArgs v(i) = vArgsArray(numArgs - i) Next i CallByNameEx = oTLI.InvokeHookArray(Obj, ProcID, CallType, v) Else ' Conserver la compatibilité dans le cas d'un appel direct à un seul argument ' CallByNameEx = oTLI.InvokeHook(Obj, ProcID, CallType, vArgsArray) End If End If Set oTLI = Nothing End Function
Partager