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 :

mettre une propriété d'objet dans une variable pour boucle


Sujet :

Macros et VBA Excel

  1. #1
    Membre du Club
    mettre une propriété d'objet dans une variable pour boucle
    Bonjour,


    Je me demandais si c'était possible de faire passer une variable dans une propriété d'objet pour boucler sur toutes les propriétés. Je m'explique plus clairement avec un exemple.

    J'ai un userform avec des noms de controls. J'ai créé une classe d'objet avec les mêmes noms, juste un complément sépare les deux noms chaque fois. Et de manière identique j'ai une table access pour stocker les informations de mon formulaire.

    J'aimerai, au lieu de lister tous les champs, les balayer en quelques lignes... Du type :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Dim check As Control
     
    Dim gg As New oblig
     
    For Each check In FO_ticket.Controls
     
        gg. & vba.right(check.Name,len(check.Name)-3) = check
     
    Next


    Voilà, si quelqu'un sait si c'est possible et comment faire s'il vous plaît ?

  2. #2
    Responsable
    Office & Excel

    Salut.

    Nativement, le VBA ne permet pas cela (si j'ai bien compris ta question).

    Tu pourrais travailler sur un de ces trois axes:
    1. utiliser une collection (mais tu ne sais pas rechercher les clés);
    2. utiliser un dictionnaire, mais soit tu travailles en late binding soit tu dois référencer la bibliothèque idoine, et tu peux alors rechercher sur la clé;
    3. utiliser un array dynamique.



    Voici un exemple pour la troisième option

    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
    Function getControls(usf As UserForm)
      ReDim Controls(0 To 1, 0 To 0)
      Dim c As MSForms.Control
     
      For Each c In usf.Controls
        If Not IsEmpty(Controls(0, 0)) Then ReDim Preserve Controls(0 To 1, 0 To UBound(Controls, 2) + 1)
        Controls(0, UBound(Controls, 2)) = c.Name
        Set Controls(1, UBound(Controls, 2)) = c
      Next
      getControls = Controls
    End Function
     
    Sub Test()
      Dim Controls
     
      Controls = getControls(UserForm1)
    End Sub


    Cela dit, il serait intéressant de connaître la finalité, car mis à part pour des userforms très chargés, je ne vois pas bien l'intérêt de la chose.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  3. #3
    Membre du Club
    Bonjour,

    merci pour le retour.

    Les idées ne sont pas bêtes, et merci pour le bout de code mais c'est pas ce que j'aurai aimé. Ce sont les propriétés de mon objet personnalisé que j'aimerai parcourir.

    Pour reprendre l'exemple de votre super cours les objets, dont je m'inspire largement (https://fauconnier.developpez.com/ar...neral/classes/) et je suis très content que ce soit vous qui me répondiez, je créais un userform pour une fiche contact, mes deux champs de userform s'appelle "nom" et "prenom". Mon objet ccontact contient les deux propriété du même Cnom et Cprenom. Au lieu d'écrire :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     
    ccontact.Cnom=Me.nom
    ccontact.Cprenom=Me.prenom



    J'aurai voulu plutôt :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    For Each check In FO_ticket.Controls
           ccontact. & check.name = check
    next


    Si je pouvais parcourir la liste des propriétes de mon objet avec un code, je pourrai m'en sortir je pense, mais je ne trouve pas non plus comment faire celà

  4. #4
    Responsable
    Office & Excel

    Merci pour ton appréciation de mon tuto.

    En VBA, on ne peut pas parcourir les propriétés d'un objet d'une classe perso de cette manière. D'une manière ou d'une autre, tu devras boucler et utiliser des Select Case. Je ne vois pas d'autre possibilité (hors api windows, mais je pense que c'est prendre un bazooka pour tuer une mouche).

    La solution que je préconise utilise une fonction SetValue dans la classe perso:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Function setValue(PropertyName As String, Value)
      Select Case PropertyName
        Case "Prenom"
          mPrenom = Value
        Case "Nom"
          mNom = Value
        Case "DateNaissance"
          mDateNaissance = Value
      End Select
    End Function


    Deux solutions:
    1. utiliser une table de mappage pour découpler le userform de la classe
    2. Utiliser directement le tag des contrôles pour spécifier à quelle propriété il se rapporte;
    3. utiliser le nom des contrôles en les préfixant (couplage fort entre le userform et la classe, mais ce n'est à priori pas gênant car ça n'apporte pas grand-chose de génériser vu le contexte), mais il faut pouvoir identifier les contrôles qui contiennent l'info à transférer (dans mon exemple, sur base du tag du contrôle).



    1. Table de mappage


    Code de transfert
    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 SaveData(c As Contact, usf As UserForm)
      Dim i As Long
     
      For i = 1 To Range("t_Mappage").Rows.Count
        c.setValue Range("t_Mappage[Propriété]")(i).Value, usf.Controls(Range("t_Mappage[Contrôle]")(i).Value).Value
      Next
    End Sub
     
    Sub Test()
      Dim c As Contact
     
      Set c = New Contact
      SaveData c, UserForm1
    End Sub


    2. Cette solution utilise aussi SetValue mais sans table de mappage. Tu dois alors distinguer les contrôles porteurs de données des autres, par exemple au moyen du tag des contrôles
    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 SaveData(c As Contact, usf As UserForm)
      Dim Item As MSForms.Control
     
      For Each Item In usf.Controls
        If Item.Tag <> "" Then c.setValue Item.Tag, Item.Value
      Next
    End Sub
     
    Sub Test()
      Dim c As Contact
     
      Set c = New Contact
      SaveData c, UserForm1
    End Sub



    3. Utiliser le nom des contrôles en en enlevant le préfixe
    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 SaveData(c As Contact, usf As UserForm)
      Dim Item As MSForms.Control
     
      For Each Item In usf.Controls
        If Item.Tag = "HasData" Then c.setValue Right(Item.Name, Len(Item.Name) - 3), Item.Value
      Next
    End Sub
     
    Sub Test()
      Dim c As Contact
     
      Set c = New Contact
      SaveData c, UserForm1
    End Sub
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  5. #5
    Membre du Club
    Merci beaucoup pour les éclairages.

    C'est exactement ce que j'avais en tête dans le procédé. Donc je suis obligé de passer par une fonction pour la transformation de la donnée mais ça laisse plus de clarté dans ma procédure ensuite. C'est top merci beaucoup encore

  6. #6
    Responsable
    Office & Excel

    Oui, tu seras obligé de passer une étape intermédiaire, mais elle clarifie effectivement le code, et elle peut être rendue générique. si tu ajoutes des propriétés à ta classe et donc des contrôles dans le userform, tu devras adapter ta table de mappage mais la fonction SaveData restera identique.

    Il y a un peu moins d'un an, j'ai posté une contribution qui généralise le transfert entre un userform et un tableau structuré... Elle reprend peu ou prou l'idée développée ici, le Select Case dans la classe en moins
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  7. #7
    Membre du Club
    Bonjour,


    je vois les tableaux, et c'est vrai que c'est bien plus simple, ça se rapproche beaucoup d'autres langage de data, c'est plus simple. Mais du coup, je me posais une question. J'avais prévu, initialement de stocker les informations rentrer dans mes tickets dans une base access. Mais, il vaut mieux les stocker dans un onglet excel dans un tableau structuré ou dans une base access ? J'ai peur que le fichier excel soit trop lourd avec le temps ? Et surtout je ne crois pas qu'on puisse croiser des données de tableaux structurés comme dans access via une requête.

  8. #8
    Responsable
    Office & Excel

    Si tu es seul à travailler sur tes tickets, je pense qu'un tableau structuré suffit. Les nouvelles versions d'Excel permettent déjà d'encoder pas mal de lignes avant de saturer, et POWER QUERY est un outil qui permet d'agréger et de préparer les données à l'analyse aussi bien qu'Access. Power Pivot peut venir en renfort pour établir des mesures et des comparaisons. Donc je pense qu'Excel est bien outillé. C'est un outil d'analyse des données qui permet de réaliser de belles choses avant d'en atteindre les limites.

    Access n'aurait de sens que pour ergonomiser la saisie, notamment en permettant mieux qu'Excel la saisie simultanée par plusieurs personnes, mais ça a un coût de développement (frontal/dorsal, création des formulaires, etc). J'ai bataillé durant des années pour faire comprendre qu'Excel n'est pas un "Access léger" mais honnêtement, avec les outils actuels d'Excel et selon la configuration de l'utilisation des données (saisie, consultation, multi-utilisateurs ou non, etc), Excel peut parfaitement tenir la distance.

    Ce n'est que mon avis, bien entendu, et on pourra débattre des heures entre "spécialistes" sans tomber d'accord
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  9. #9
    Membre du Club
    J'ai opté pour l'alliance avec Access pour sauver les données, car nous sommes plusieurs personnes à intervenir, et à différents moments de la vie du ticket, avec une certaine hiérarchie d'étape chacun, donc j'ai fait une table pour chaque étape avec un numéro de ticket pour tracer toutes les étapes et retrouver toutes les informations...

    Du coup, j'ai structuré mon userform en page et en frame, et je n'arrive pas à passer dans le code le usf en référence, pour garder juste la fonction de savedata , sans en faire une pour chaque formulaire, mais juste en précisant le nom du formulaire d'où l'on vient via me.name.

    De plus au lieu de parcourir tout le userform, j'aimerai parcourir seulement le frame de l'étape où je suis dans la vie du ticket. J'arrive à le parcourir, en rajoutant le nom du frame dans les paramètres, mais dans ma boucle j'ai juste for each item in frm.controls, sans préciser le userform, même s'il est dans mes paramètres ...
    Actuellement j'ai qu'un userform, mais il devrait y en avoir plusieurs donc j'aimerai bien lui préciser sur lequel on est, sachant que les frames auront tous le même nom, décrivant l'étape où le ticket se trouve... Peut-être que je n'ai pas à le préciser parce qu'un seul usf peut être ouvert à la fois et donc l'ordinateur le saura, je ne sais pas....

  10. #10
    Responsable
    Office & Excel

    J'ai écrit 4 billets de blog sur la façon d'interagir avec Access. Voici le premier, les autres sont en enfilade.

    Tu verras en les lisant que les procédures "métier" (celles de tes userforms) s'appuient sur des procédures génériques (celles du premier billet). En mappant tes échanges userform/table (mon billet sur la liaison userform/Tableau structuré t'aidera), tu vas pouvoir limiter ton code à peu de choses, à savoir "en gros" déterminer les contrôles de mappage qui vont orchestrer la manoeuvre. L'utilisation d'arrays de paires Clé/Valeur est une technique très intéressante pour ce genre de traitement car tu déportes le paramétrage dans des feuilles Excel, dégageant le code des notions métier. Cette façon de voir les choses est possible car sur le plan technique, transférer des données d'un userform dans une table Access, c'est toujours le même principe, quel que soit le userform et quelle que soit la table Access (ou le tableau structuré si on travaille en Excel).


    Question qui vient peut-être un peu tard: Pourquoi pas tout dans Access? Access offre des possibilités de création de formulaires sans VBA qui modélisent tous les échanges formulaires/Tables. Tu ajoutes le VBA uniquement pour certains contrôles de validité et tu as rapidement une application frontale/dorsale que ton équipe peut utiliser.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  11. #11
    Membre du Club
    on a déjà un outil sur access uniquement, mais il plante souvent... on l'a obtenu de l'extérieur par un nouveau responsable qui est arrivé, je l'ai adapté à notre process mais je le trouve lourd, compliqué avec beaucoup trop d'information à renseigner. Il a été mal fait, il y a trop de tables dont une de 253 colonnes... J'aime pas les rapports dans access non plus pour faire les tickets.
    Et surtout, c'est qu'il plante souvent. On peut être plusieurs dessus, et ajouter des informations, mais comme on travaille sur serveur, j'ai l'impression qu'il n'aime pas trop ça, et souvent la base "explose" en faisant une sauvegarde automatique d'avant les saisies, donc il faut qu'on reprenne le process pour la remettre à jour... Il y a un risque opérationnel aussi, où des utilisateurs "lambda" utilise la base et je pense qu'ils la font planter aussi. En séparant les deux, je veux éviter de perdre de la donnée, et faciliter le transfert de connaissance si je venais à partir de la société (beaucoup plus de monde connait excel). Si ça ne tenait qu'à moi, j'aurai tout développé en R ou python mais ce sont des langages non autorisé sur nos réseaux...

  12. #12
    Responsable
    Office & Excel

    Ok. Merci pour ces précisions.

    Tu ne renseignes pas ta version d'Excel, mais si tu es en windows 365, les PowerApps permettent de créer rapidement des formulaires de saisie liés à des tableaux structurés Excel. Après, en téléchargeant l'application PowerApps sur un smartphone, tu peux saisir des données au travers du formulaire sur le smartphone et les données sont instantanément disponibles sur le fichier Excel. J'en suis à la découverte de l'outil, mais c'est quand même pas mal de réaliser une appli de saisie en quelques clics. Evidemment, c'est dans le cloud de Microsoft. Ce n'est peut-être pas permis dans ta boite...
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
    Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
    VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
    Vous avez apprécié la réponse? =>
    ---------------

  13. #13
    Membre du Club
    HA c'est trop bien ça !! mais on n'a pas les autres logiciels microsoft, enfin il faudrait que je demande si ils sont dans la liste des logiciels disponibles à mon informatique, parce qu'on a microsoft 365... je pourrai me renseigner sur ce système et cloud et notamment peut être coder les informations pour ce que soit possible... mais ça va me demander du temps pour découvrir le logiciel et voir comment ça fonctionne mais ça peut donner des possibilités sympa pour les managers... Ensuite une autre raison de basculer sur excel en saisie, c'est qu'on n'a pas accès aux bases access en télétravail... Ils refusent parce qu'ils disent que ça demande trop de bandes passantes. Du coup, j'ai pensé à un système de base centrale qui est alimenté via les bases de chacun à chaque MAJ. Les infos étant sauvé sous format texte dans une nomenclature prédéfinie où chaque fichier et base vient vérifier à chaque opération s'il est bien à jour. C'est un peu systeme D mais on essaie de s'adapter à son environnement ^^

###raw>template_hook.ano_emploi###