IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB 6 et antérieur Discussion :

[Trucs et astuces]Propagation d'arguments avec ParamArray


Sujet :

VB 6 et antérieur

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de DarkVader
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    2 130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 130
    Points : 3 118
    Points
    3 118
    Par défaut [Trucs et astuces]Propagation d'arguments avec ParamArray
    Nov.

    Une fonction qui utilise l'argument ParamArray permet de transmettre à cette fonction un nombre d'arguments variables tout en standardisant sa signature.
    Ex:
    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
    Cette fonction qui utilise l'argument paramArray pourra alors être appelée indifféremment par
    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
    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
    ce qui induit évidemment une erreur puisque l'argument récupéré ne sera plus un tableau à 1 dimension de n arguments
    ... 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

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Août 2006
    Messages
    243
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 243
    Points : 328
    Points
    328
    Par défaut
    Merci DarkVader !

    Et une technique de plus utilisable/adaptable/à étudier pour mon petit problème de binpacking.

    Pour faire rapide, mon problème du moment est de trier des formes rectangulaires sur 1,2,3,...n critères (par ex. : Largeur puis Hauteur, etc.)

    Actuellement, via CallByName, j'ai extrait de mes algos de tri (un seul ne me suffit pas, je suis gourmand ) la "connaissance" de la propriété/méthode à utiliser pour obtenir la valeur de mes instances. Ainsi, l'algo. est générique quelque soit le critère (largeur, longueur,etc..) : il fait un CallByName sur les instances à trier en utilisant le critère (largeur, longueur, etc.) qu'il a en paramètre.

    Mais :
    1) Je suis un vieux grincheux donc mon code ne me plaît pas tellement .
    2) Mon code est non récursif donc code "doublon" pour gérer le second critère et obligation d'en refaire pour chaque critère additionnel et comme je sais que j'aurais besoin d'au moins 3 critères (je refait en VB ce que j'ai déjà codé en Python : je sais, je régresse ), donc ré-écriture récursive en vue pour faire sauter la limitation sur le nb de critères.
    4) Je me sens toujours obligé de réfléchir à un peu plus loin que mes besoins immédiats (je sais, c'est pas bien en dev. pro. mais bon, comme là, c'est pour moi, autant me faire plaisir )
    5) J'aime bien connaitre de nouvelles techniques

  3. #3
    Rédacteur
    Avatar de DarkVader
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    2 130
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 130
    Points : 3 118
    Points
    3 118
    Par défaut
    Bonsoir,
    Cela fera au moins une personne à qui cela aura servi ; c'est déjà ça.
    Merci de ton commentaire : je me sens moins seul. lol

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Août 2006
    Messages
    243
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 243
    Points : 328
    Points
    328
    Par défaut
    Te biles pas, j'suis sûr que dans les lecteurs, il y a moins une personne qui a noté cette astuces dans un coin de sa tête et une autre l'a fait mais inconsciemment

  5. #5
    Membre éclairé
    Inscrit en
    Décembre 2007
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 512
    Points : 671
    Points
    671
    Par défaut
    Bonjour,

    Te biles pas, j'suis sûr que dans les lecteurs, il y a moins une personne qui a noté cette astuces dans un coin de sa tête et une autre l'a fait mais inconsciemment
    Pas dans un coin de ma tête ,mais toutes les astuces de Dark, dans un fichier texte de références (avec Notepad,c'est le plus simple) pour pouvoir les étudier à l'aise.

    A+ amicalement

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Août 2006
    Messages
    243
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 243
    Points : 328
    Points
    328
    Par défaut
    Tu vois Dark, avec toi, on est au moins 3 à résister et faire du VB6 en france

Discussions similaires

  1. Réponses: 0
    Dernier message: 07/11/2008, 23h48
  2. [VBA-E] passage d'argument avec la méthode "Show"
    Par JOUBERT dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 14/03/2006, 13h56
  3. trucs et astuces XML
    Par grishka dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 09/09/2004, 13h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo