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

Macros et VBA Excel Discussion :

Problème d'utilisation de CallByName [XL-2013]


Sujet :

Macros et VBA Excel

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11
    Points : 9
    Points
    9
    Par défaut Problème d'utilisation de CallByName
    Bonjour,
    Mon objectif est de réaliser différentes opérations sur 2 tableaux (MatriceA et MatriceB). Ces opérations sont définies comme étant à réaliser(1) ou non(0) dans un tableau de booléens ProcX().
    Je suis arrivé à mes fins, la procédure "Init_Operation" est fonctionnelle mais...
    J'aimerais remplacer le "vilain code" de la procédure "Init_Operation" par celui de la procédure "Init_Operation_bis" en utilisant CallByName pour me permettre de gérer les opérations plus proprement.
    Evidemment "Init_Operation_bis" ne fonctionne pas comme je veux...

    La liste des opérations : (j'ai élagué, le contenu de ces procédures importe peu...)
    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
    Sub RotationG(ByRef MatA, MatB, Chg)
    ...
    End Sub
    Sub RotationD(ByRef MatA, MatB, Chg)
    ...
    End Sub
    Sub Inversion(ByRef MatA, MatB, Chg)
    ...
    End Sub
    Sub MirroirHt(ByRef MatA, MatB, Chg)
    ...
    End Sub
    Sub MirroirVt(ByRef MatA, MatB, Chg)
    ...
    End Sub
    La procédure qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Sub Init_Operation(ByRef MatriceA, MatriceB, Proc, Change)
    Dim i As Integer
     For i = 1 To 11
      If Proc(i) Then
        Select Case i
          Case 1: Call RotationG(MatriceA, MatriceB, Change)
          Case 2: Call RotationD(MatriceA, MatriceB, Change)
          Case 3: Call Inversion(MatriceA, MatriceB, Change)
          Case 4: Call MirroirHt(MatriceA, MatriceB, Change)
          Case 5: Call MirroirVt(MatriceA, MatriceB, Change)
        End Select
      End If
     Next
    End Sub
    La procédure -que j'aimerais à l'identique- mais qui ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Sub Init_Operation_bis(ByRef MatriceA, MatriceB, Proc, Change)
     For i = 1 To 11
      If Proc(i) Then
        Call CallByName(ActiveSheet, nProc(i), VbMethod, MatriceA, MatriceB, Change)
        'Call Application.Run(nProc(i), MatriceA, MatriceB, Change)
      End If
     Next
    End Sub
    Quelques initialisations et le lancement des procédures "Init_Operation" et "Init_Operation_bis" :
    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
    Dim nProc() As Variant
     
    Sub Main()
    Dim MatriceA() As Variant : Dim MatriceB() As Variant
    Dim Proc1() As Variant    : Dim Proc2() As Variant
    Dim Change As Boolean
     
     MatriceA = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9))
     MatriceB = Array(Array(7, 8, 9), Array(4, 5, 6), Array(1, 2, 3))
     
     Proc1 = Array(1, 1, 1, 0, 0)
     Proc2 = Array(0, 0, 1, 1, 1)
     
     Call Operation(MatriceA, MatriceB, Proc1, Change)
     Call Operation(MatriceA, MatriceB, Proc2, Change)
     
     nProc = Array("RotationG", "RotationD", "Inversion", "MirroirHt", "MirroirVt")
     
     Call Operation_bis(MatriceA, MatriceB, Proc1, Change)
     Call Operation_bis(MatriceA, MatriceB, Proc2, Change)
    End Sub
    -L'utilisation de CallByName me renvoie une «erreur 438 : propriété ou méthode non gérée par cet objet»
    Le problème doit venir du trop grand nombre d'arguments envoyés (2 tableaux et 1 booléen) dans le CallByName, je ne sais pas faire...
    -L'utilisation de Application.Run lance bien l'opération mais ne retourne rien : le ByRef semble ignoré...
    Merci pour votre aide

  2. #2
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    Salut

    Citation Envoyé par phtpht Voir le message
    (j'ai élagué, le contenu de ces procédures importe peu...)
    Pas vraiment, je m'étais mis ça de coté il y a quelques semaines dans mon répertoire "idées" en me disant que c'était un bon sujet à traiter... donc si tu l'as réalisé, un petit post dans "Contribution" serait le bienvenu . je voulais regarder avant d'attaquer s'il n'y avait pas des fonctions Excel (worksheetfunction) qui faisaient déjà la taff.
    Tu peux aussi dans un 1er temps poster ici, on pourra peut-être y apporter quelques amélioration :p

    Un enum pour les opérations serait sans doute une bonne piste de départ

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Enum eMatrix_Operation
      mo_RotationD = 1
      mo_RotationG = 2
      mo_... = 4
      mo_... = 8
      mo_... = 16
      mo_... = 32
      ...
    end Enum
    Pourquoi faire une boucle for de longueur fixe, plutot que de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     For i = LBound(Proc) To UBound(Proc)
    et en dehors d'une procédure les déclaration de variable sont soit Publiques, soit Privées et elles doivent se trouvées en début de module avant la 1ère procédure.
    Et pour stocker des array, il ne faut pas déclarer tes variables en tableau ouvert, donc pas de parenthèse.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Private nProc As Variant
    Pour les déclarations
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim Proc1 As Variant, Proc2 As Variant

    Pour pouvoir t'aider efficacement, il va falloir dévoiler un peu plus des codes que tu utilises. Faire autant de fonction que d'opérations ne me semble pas efficient. Par exemple entre les rotations D et G, la différence entre les deux code doit être si faible qu'il vaudrait mieux n'en faire qu'une en rendant variable les quelques point de différence.
    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Merci pour ces premières pistes et ces corrections à apporter dans les déclarations de variable (ce manque de rigueur engendre parfois des comportements erratiques dans l'exécution de mes écritures...).
    Les fonctions "Miroir" / "Inversion" / "Rotation" n'ont pas vraiment été élaguées, elles ont été écrites lors de la rédaction de mon message et n'ont même jamais existé dans mon code.
    Confronté à ce problème d'utilisation du CallByName, j'ai cherché à présenter succinctement mon problème ici.
    Le "vrai" code qui m'occupe est destiné à la résolution de grille de sudoku (grille classique).
    Au delà de la résolution en "brute force" qui ne présente aucun intérêt (...) j'essaie d'enchaîner différentes techniques basiques ou avancées de résolution en «pas à pas».

    Pour faire l'analogie avec ce que j'ai présenté au dessus:
    J'ai une grille (9x9) que je soumets à différentes opérations (=différentes techniques de résolution).
    En retour, chaque opération me retourne la grille modifiée (ou non) suivant la réussite (ou l'échec) de la technique.

    Avec actuellement 12 techniques qui s'enchaînent, le code ressemble plus à ça:
    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
    Sub Init_Operation(ByRef GrilleA, GrilleB, Proc, Change)
    Dim i As Integer
     For i = 1 To 11 '(la 12e est brinquebalante pour le moment)
      If Proc(i) Then
        Select Case i
          Case 1: Call Nettoyage(GrilleA, GrilleB, Change)
          Case 2: Call Singlet_Evident(GrilleA, GrilleB, Change)
          Case 3: Call Singlet_Cache(GrilleA, GrilleB, Change)
          Case 4: Call Doublet_Evident(GrilleA, GrilleB, Change)
          Case 5: Call Doublet_Cache(GrilleA, GrilleB, Change)
          Case 6: Call Triplet_Evident(GrilleA, GrilleB, Change)
          Case 7: Call Triplet_Cache(GrilleA, GrilleB, Change)
          ...
        End Select
      End If
     Next
    End Sub
    Mais plutôt que d'enchaîner linéairement ces techniques, je souhaite en shunter certaines (d'où Proc() ) ou même les enchaîner dans des ordres prédéfinis.
    Voilà l'objectif qui m'a conduit vers l'utilisation de l'instruction CallByName.

  4. #4
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    Salut

    Mais plutôt que d'enchaîner linéairement ces techniques, je souhaite en shunter certaines (d'où Proc() ) ou même les enchaîner dans des ordres prédéfinis.
    C'est également possible avec Enum

    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
     
    Option Explicit
     
    Enum eMatrix_Operation
        mo_RotationD = 1
        mo_RotationG = 2
        mo_Inversion = 4
        mo_MirroirHt = 8
        mo_MirroirVt = 16
        'mo_... = 32
    End Enum
     
    Sub Main()
    Dim MatriceA As Variant, MatriceB As Variant
    Dim Change As Boolean
     
    Dim ListOp(1 To 3) As eMatrix_Operation
     
        MatriceA = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9))
        MatriceB = Array(Array(7, 8, 9), Array(4, 5, 6), Array(1, 2, 3))
     
        ListOp(1) = mo_Inversion
        ListOp(2) = mo_RotationD
        ListOp(3) = mo_MirroirVt
        Init_Operation_M MatriceA, MatriceB, ListOp, Change
    End Sub
    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11
    Points : 9
    Points
    9
    Par défaut
    Merci pour cette solution de contournement de CallByName .
    Pour le moment, le fonctionnement du code proposé ne m'apparaît pas comme évident après une lecture simple (...)
    Je vais essayer de comprendre cela sur du code basique avant de l'implanter dans ce qui me préoccupe.

    Ça ne répond pas exactement à mon problème d'utilisation de CallByName mais -a priori- ça devrait permettre d'atteindre l'objectif fixé.
    Je bascule donc en résolu.

  6. #6
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    Salut

    Je n'ai jamais utilisé CallByName mais je pense que ton problème vient de l'emplacement de ton code. La procédure que tu appelles se trouve bien dans ActiveSheet? Elle ne serait pas dans un module par exemple?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CallByName(ActiveSheet,....

    [Edit]
    Je viens de faire le test suivant, le code est placé dans la feuille1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Function TestCBN(a, b, c) As String
        TestCBN = a & b & c
     
    End Function
     
    Sub TestCall()
    Dim result As String
    result = TestCBN("a", "b", "c")
    result = CallByName(Feuil1, "TestCBN", VbMethod, "a", "b", "c")
     
    End Sub
    La function TestCBN est bien appelée deux fois.
    [/Edit]

    [Edit2]
    Autre solution pour pointer vers une procédure contenue dans un module
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Sub TestCall()
    Dim result As String
    result = TestCBN("a", "b", "c")
    'result = CallByName(Feuil1, "TestCBN", VbMethod, "a", "b", "c")
    result = Application.Run("Module2.TestCBN", "a", "b", "c")
    End Sub
    [/Edit2]

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  7. #7
    Expert éminent
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    3 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 3 453
    Points : 6 871
    Points
    6 871
    Par défaut
    Bonjour,

    La discussion est résolue mais je poste quand même car ça peut aider !

    Quand une fonction ou sub se trouve dans un module de feuille et à condition qu'elle ne soit pas déclarée private, on peu l'appeler de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    result = Feuil1.TestCBN("a", "b", "c")
    en faisant précéder la fonction/sub du nom du module et il en est de même pour une variable, si elle est déclarée publique est sera accessible dupuis n'importe où du moment qu'elle est précédée du nom du module où elle se trouve :
    Dans le module de la feuille Feuil1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Public MaVariable As String
    Appel depuis un module standard ou autre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    MsgBox Feuil1.MaVariable
    'ou 
    MsgBox Worksheets("Feuil1").MaVariable

  8. #8
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    Salut Theze

    Le "soucis" en fait c'est que phtpht souhaite faire référence à une fonction en ayant le nom de cette fonction dans une variable String, d'où l'utilisation de CallByName ou de Run

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

  9. #9
    Expert éminent
    Homme Profil pro
    Inscrit en
    Août 2010
    Messages
    3 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 3 453
    Points : 6 871
    Points
    6 871
    Par défaut
    Salut Qwazerty,

    Oui bien sûr tu as raison mais comme tu utilises dans ton exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    result = TestCBN("a", "b", "c")
    Si cette fonction n'est pas dans un module standard mais dans un module de feuille ou du classeur, elle ne sera pas accessible

  10. #10
    Membre expert
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 2 267
    Points : 3 663
    Points
    3 663
    Par défaut
    Bonjour,

    Tant qu'à appeler une fonction en lui passant l'opération voulue par chaine pourquoi ne pas mettre toutes tes fonctions dans une unique.
    Peut-être moins esthétique mais plus de souplesse :
    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
    Dim ope(1 To 2) As String
    Sub test()
        ope(1) = "RotG"
        ope(2) = "RotD"
        'ex d'appel
        C = op("RotG", A, B)
        C = op("rotg,rotd", A, B)
        C = op("1,2,1,1,2", A, B)
    End Sub
     
    Function op(operation, MatriceA, MatriceB)
        Dim ops, opStr As String, i As Long
        ops = Split(operation, ",")
        For i = 0 To UBound(ops)
            If Val(ops(i)) > 0 Then opStr = ope(Val(ops(i))) Else opStr = ops(i)
            Select Case LCase(opStr)
            Case "rotg"
                Debug.Print "RotG"
            Case "rotd"
                Debug.Print "RotD"
            Case Else
                op = "ano": Exit Function
            End Select
        Next i
        op = "fait"
    End Function
    En poussant plus loin on peut même imaginer que tu crées un dictionnaire de suite d'opérations standard, que tu pourrais enchainer en concaténant les items voulus.
    eric

  11. #11
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 898
    Points : 8 529
    Points
    8 529
    Par défaut
    Citation Envoyé par Theze Voir le message
    Salut Qwazerty,

    Oui bien sûr tu as raison mais comme tu utilises dans ton exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    result = TestCBN("a", "b", "c")
    Si cette fonction n'est pas dans un module standard mais dans un module de feuille ou du classeur, elle ne sera pas accessible
    Ah oui! J'avais juste mis cette ligne pour m'assurer que ma fonction TestCBN fonctionnait correctement . C'est toujours dommage de faire des teste d'écriture de code, que ça ne fonctionne pas... et finir par s’apercevoir qu'en fait c'est la fonction démo qui ne fonctionne pas correctement :p

    ++
    Qwaz

    MagicQwaz := Harry Potter la baguette en moins
    Le monde dans lequel on vit
    Ma page perso DVP
    Dernier et Seul Tutoriel : VBA & Internet Explorer
    Dernière contribution : Lien Tableau Structuré et UserForm
    L'utilisation de l’éditeur de message

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RTFEditorKit] Problème d'utilisation
    Par jean.lamy dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 21/10/2004, 18h30
  2. Problème d'utilisation de Mysql avec dev-c++
    Par Watchi dans le forum Dev-C++
    Réponses: 10
    Dernier message: 06/08/2004, 14h35
  3. [cvs] problèmes d'utilisation
    Par gromite dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 29/06/2004, 17h41
  4. Problème: Requête utilisant NOT IN
    Par fages dans le forum Langage SQL
    Réponses: 4
    Dernier message: 04/05/2004, 10h18
  5. problème d'utilisation avec turbo pascal 7.0
    Par le 27 dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 03/12/2003, 10h44

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