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

Commentaires

  1. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    D'accord.
    Merci pour ces précisions.

    A plus tard.
  2. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    Ce que je voulais seulement mentionner.
    En suivant un de tes post sur le forum VBA, j'utilise Property Get pour définir une propriété de formulaire.
    Tandis qu'ici, sauf erreur, la propriété Result est déclarée en entête du module affecté au formulaire.


    Pour ce qui concerne le pilotage de formulaire à distance et l'utilisation d'une variable propriété, c'est le principe que j'adopte depuis nos échanges sur le Forum.
  3. Avatar de MarcelG
    • |
    • permalink
    Bonjour Pierre,

    En ce qui concerne la gestion des boutons d'options, voici les 2 développements, intégrés à la fonction Update, et soumis à ton jugement de grand maître
    (extrait du développement de mon applicatif)

    Le libellé affectant la cellule du tableau est lié à la propriété Caption du bouton

    Dans le sens Formulaire Tableau

    Propriété du formulaire

    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
    Property Get type_opération() As String
    
    Dim i As Byte
    i = 0
    
    Dim ctrl As MSForms.Control
    
    type_opération = ""
    
    Do While type_opération = "" And i < Me.Controls.Count
            Set ctrl = Me.Controls(i)
            With ctrl
                   If TypeName(ctrl) = "OptionButton" Then
                           If .GroupName = "Liste_Opt_Type" Then
                                   If .Value = True Then
                                           type_opération = .Caption
                                   End If
                            End If
                    End If
            End With
            Set ctrl = Nothing
            i = i + 1
    Loop
    
    End Property
    ce qui donne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Data(1, 11) = .type_opération 'Property décrite dans le module de l'Usf

    Dans le sens tableau structuré - formulaire, afin d'affecter la propriété True au bouton correspondant

    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
          typoper = Worksheets("Base").ListObjects("T_Base").ListColumns("Type de l'opération").DataBodyRange.Rows(lr.Index).Value
            i = 0
            
            Do While lebtn Is Nothing And i < .Controls.Count
                  Set ctrl = .Controls(i)
                  With ctrl
                         If TypeName(ctrl) = "OptionButton" Then
                                 If .GroupName = "Liste_Opt_Type" Then
                                         .Value = False
                                         If typoper <> "" and InStr(.Caption, typoper) > 0 Then
                                                 Set lebtn = ctrl
                                                 lebtn.Value = True
                                         End If
                                  End If
                          End If
                  End With
                  Set ctrl = Nothing
                  i = i + 1
            Loop
    A noter
    La variable lr (Listrrow) a une portée module afin d'en utiliser la propriété index pour le calcul tyoper
    Les boutons d'option sont affectés d'une propriété GroupName définie .

    Voilà.

    Au plaisir de te lire
    Mis à jour 14/09/2020 à 14h54 par MarcelG
  4. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    En adaptant ce code, j'en ai constaté la souplesse.

    En effet, l'ajout d'un enregistrement ne pose pas de problème. La variable Data retourne alors des valeurs vides.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Sub Alim_données(Optional numcnt As Long)
    
    Dim lr As ListRow
    Dim Data
    
    If numcnt = 0 Then
            Set lr = Worksheets("Base").Range("T_Base").ListObject.ListRows.Add
    Else
            Set lr = getRow(numcnt)
    End If
    Il me reste à gérer les boutons d'option de mon formulaire.
    Sans doute en y affectant une "Property", ou bien une fonction dans le module standard Data(1,15) = Fn(Data(1,10))
    En cas de problème, j'ouvrirai une discussion sur le Forum.

    En tout cas, merci et à bientôt.
    Mis à jour 14/09/2020 à 13h04 par MarcelG
  5. Avatar de Pierre Fauconnier
    • |
    • permalink
    Salut Marcel,

    je ne comprends pas ton commentaire car il me semble que c'est justement ce que j'explique ici. Une procédure appelante dans un module standard charge le formulaire, le prépare, l'affiche. Comme il est modal, le contrôle du code est passé au formulaire tant que ce dernier est visible, et une pression sur un des boutons masque le formulaire et repasse le contrôle du code à la procédure appelante, qui détermine sur quel bouton on a cliqué grâce à la propriété publique Result du formulaire et poursuit le traitement en récupérant les valeurs saisies dans les contrôles du formulaire.

    Ce n'est pas différent de ce que tu expliques, il me semble.
  6. Avatar de Pierre Fauconnier
    • |
    • permalink
    Salut Marcel,

    Le problème de ta procédure, c'est que si ta feuille est vide, ça plante. Le SpecialCells que je j'utilise ne sert qu'à éviter le plantage dans ce cas de figure.


    Pour ce qui est de la dernière ligne d'un tableau, il faut voir si l'on parle de la ligne absolue (la ligne de la feuille) ou la ligne du tableau. Pour avoir la dernière ligne du tableau, il suffit de compter le nombre de lignes du tableau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Function LastTableRow(Table As ListObject) As Long
      LastTableRow = Table.ListRows.Count
    End Function
    Si on parle de la ligne absolue (celle de la feuille), on peut utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Function LastAbsoluteTableRow(Table As ListObject) As Long
      If Table.ListRows.Count > 0 Then LastAbsoluteTableRow = Table.DataBodyRange(Table.ListRows.Count, 1).Row
    End Function
  7. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    Quelle différence ferais-tu entre ce processus et celui, que tu m'as inspiré au cours de nos échanges, qui consisterait à piloter le formulaire à distance, par procédure placée dans un module standard, en l'affichant tant que l'une de ses propriétés (Property Get) ne serait pas constatée.
    Ici, la propriété serait liée à la valeur testée (booléenne ou autre). D'autre part, le bouton "OK" du formulaire n'aurait pour fonction de cacher le formulaire.
    Celui-ci serait alors déchargé depuis la procédure appelante.

    Bon après-midi et à bientôt.
  8. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    Pour ma part, je quitte peu à peu le processus dernl = ....End(xlUp)

    (il était temps, au bout de 11 ans )

    Je me méfie de SpecialCells qui m'a donné parfois des résultats surprenants (je n'ai pas d'exemple précis sous les yeux)

    Je lui préfère la méthode Find

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    With Worksheets(1)
                With .Range("A1", .Cells(.Rows.Count, .Columns.Count))
                        dernl = .Find(what:="*", searchdirection:=xlPrevious, searchorder:=xlByRows, LookIn:=xlValues).Row
                        derncol = .Find(what:="*", searchdirection:=xlPrevious, searchorder:=xlByColumns, LookIn:=xlValues).Column
                End With
    End With

    Au niveau de la ligne, pour un tableau structuré (là aussi, j'ai tardé!)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    derligne = Worksheets("Entrée").ListObjects("Tableau1").ListColumns("Date").Range.Find("", SearchDirection:=xlNext).Row-1
    On notera au passage l'importance du paramètre SearchDirection dans les 2 cas de figure

    Je sais au demeurant que ces notions font débat.

    C'était donc juste mon - humble - avis

    Bonne journée à toi et à la prochaine.
  9. Avatar de Malick
    • |
    • permalink
    Bonjour Pierre,

    Merci bien pour la contribution

    En te relisant encore, j'ai vérifié mon outil et je me rends compte que j'ai sûrement fait une bourde sur un autre script qui touche les tableaux structurés.

    En fait, en voulant importer le contenu d'un tableau se trouvant sur un autre classeur, j'ai utilisé ListObject, mais pour le collage des données, je suis passé par le range en me positionnant sur la première cellule de la Ligne 1 du tableau de destination. Cela fonctionne bien, mais j'imagine que ce n'est pas la bonne manière

    Pour ne pas polluer le fil, je posterai le code sur le forum VBA pour échanger dessus et le corriger

    encore pour l'apprentissage des bonnes manières que tu dispenses nb

    Malick
  10. Avatar de User
    • |
    • permalink
    Sympa ce billet !

    Je ne connaissais pas la formule.

    Merci Pierre
  11. Avatar de Pierre Fauconnier
    • |
    • permalink
    Citation Envoyé par curt
    [...]
    Salut Curt,

    Merci pour ton appréciation et bon weekend
  12. Avatar de Pierre Fauconnier
    • |
    • permalink
    Salut

    Citation Envoyé par ec
    Je ne sais pas si je sors du sujet, mais j'ai l'habitude de sélectionner ma colonne d’adresse mail dans Excel et de la coller directement dans la zone d'adresse du message. Ne pas avoir peur de la disposition dans Outlook, au bout de quelques secondes il dispose correctement les adresses.
    Oui, c'est aussi une astuce... Mais si on les souhaites filtrées, triées, uniques, ça demande x manipulations à refaire à chaque fois. Avec une formule, si tu veux d'abord avoir celles d'un domaine, puis celle d'un autre, il te suffit de modifier le domaine dans la cellule où tu l'auras mentionné. Ce sera la seule manipulation à réaliser pour obtenir une autre liste.

    De plus, j'ai pris ici des adresses mail à titre d'exemple, mais tu peux envisager ces fonctions pour d'autres situations. En formation, j'ai ainsi pu montrer que l'on pouvait choisir une série de factures à valider dans Excel sur base de leurs numéros, puis créer la liste avec le séparateur pour l'envoyer dans un champ de saisie d'un CRM pour une validation "à la volée". Ce qu'il faut retenir ici, c'est plus l'arrivée de nouvelles fonctions qui ouvrent à de nouvelles possibilités, sans trop se focaliser sur la spécificité d'adresses envoyées dans Outlook
  13. Avatar de curt
    • |
    • permalink
    Bonjour Pierre,

    merci pour l'info et le partage... et avec un tout petit peu de code et on peut envoyer un mail via Outlook en ayant sélectionné la liste de diffusion à partir d'Excel...
    Superbe travail.
    Curt
  14. Avatar de ec
    • |
    • permalink
    Je ne sais pas si je sors du sujet, mais j'ai l'habitude de sélectionner ma colonne d’adresse mail dans Excel et de la coller directement dans la zone d'adresse du message. Ne pas avoir peur de la disposition dans Outlook, au bout de quelques secondes il dispose correctement les adresses.
  15. Avatar de mouftie
    • |
    • permalink
    Bonjour Monsieur,

    Super travail, car peu de gens ont intégré les tables référencées dans leur pratique régulière ; je pense en grande partie à cause des références absolues et de l'abandon du $ avec la touche F4...

    Vos 2 tutos :
    Utilisation courante des tables
    https://fauconnier.developpez.com/tu...ructures/#LVII
    et
    Utilisation des table avec VBA
    https://fauconnier.developpez.com/tu...uresvba/#LII-A
    Sont super et très bien fait ;

    Mon seul regret est que vous n'ayez pas terminé celui pour VBA...

    Je profite de cet occasion pour vous félicitez de votre dévouement pour aider notre communauté.
  16. Avatar de Pierre Fauconnier
    • |
    • permalink
    Bonjour.

    Comme tu as aussi posé la question sur le forum, j'ai répondu dans cette discussion, notamment parce que je ne comprends pas bien le contexte dans lequel tu évolues... N'hésite pas à réagir dans la discussion...
  17. Avatar de elclor
    • |
    • permalink
    Bonjour
    Je ne connais rien du PQ mais tu m'as donné envie de commencer et pour cela j'essaye de refaire ton exemple.
    Mais dès le début en ajoutant une colonne avec la condition identique à la tienne=[@PAYS]="AU" je reçois le message d'erreur suivant : la syntaxe de ce nom est incorrecte et ce qui est dans les crochets est mis en surbrillance. Une colonne PAYS existe bien dans ma BD et AU comme valeur d'une cellule de cette colonne.
    Merci de ton aide
    elclor
  18. Avatar de apt
    • |
    • permalink
    Merci Pierre pour ces précieux conseils
  19. Avatar de Qwazerty
    • |
    • permalink
    Salut Pierre

    C'est une notion qui me semble essentielle.
    D'ailleurs la notation range("A1") est bien souvent trop juste également à mon gout et devrait être accompagnée à minima de la feuille si on utilise le CodeName et au mieux de l'ensemble Classeur.Feuille.Range.

    Je vois très souvent des codes proposés sur les forums qui négligent cette aspect là... et bien souvent ces mêmes codes sont mal structurés, car souvent issu de l'enregistreur, provoquant des lenteurs d'exécution.
    L'ensemble des deux (absence d'antécédent et lenteur) laisse tout loisir à l'utilisateur de changer de feuille voir de classeur durant l'exécution du code...
    Là où ThisWorkbook.Worksheet("Feuil1").Range("A1").Value = "Test" fait le boulot sans histoire, Range("A1").Value = "Test" met un beau bor*el dans la feuille et/ou le classeur passé(e) au premier plan.

    VB est très verbeux, les gens veulent souvent s'épargner du code ou du moins alléger leur code mais je pense que c'est bien souvent un mauvaise idée. (je passe sur l'utilisation des ":" pour tout assembler sur une ligne)
    Il est préférable, toujours à mon avis, d'utiliser une structure With ... End With ou encore utiliser une variable pour pointer la feuille ou le range sur lequel on veut travailler, on allège ainsi le code sans perdre en précision et sans prendre le risque de massacrer une autre feuille.
    Sachant qu'il n'est pas possible d'utiliser Ctrl+Z pour rattraper les dégâts et imaginez si en plus la macro fait un point de sauvegarde du classeur actif.....

    Je te souhaite une bonne soirée
    ++
    Qwaz
  20. Avatar de Pierre Fauconnier
    • |
    • permalink
    Salut.

    Perso, je ne suis pas un grand fan des dictionnaires. Ici, j'ai repris une fonction que j'utilise depuis longtemps en passant un tableau à une dimension (elle provient d'un framework MVC en PHP que j'ai créé il y a quelques années). On pourrait éventuellement utiliser un tableau à deux dimensions qui matérialise peut-être mieux les paires Ancienne valeur/Nouvelle valeur.

    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
    Public Function ReplaceStrings(Source As String, Parameters) As String
      Dim I As Long
     
      ReplaceStrings = Source
      For I = LBound(Parameters) To UBound(Parameters)
        ReplaceStrings = Replace(ReplaceStrings, Parameters(I, LBound(Parameters, 2)), Parameters(I, UBound(Parameters, 2)), vbTextCompare)
      Next I
    End Function
    
    Sub Test()
      Dim t(1, 1)
      Dim s As String
      
      t(0, 0) = "{Femme}"
      t(0, 1) = "Martine"
      t(1, 0) = "{Homme}"
      t(1, 1) = "Pierre"
    
      s = "{Femme} et {Homme}"
      s = ReplaceStrings(s, t)
    End Sub
    Toutefois, que ce soit avec un dico ou un tableau à deux dimensions, il faut passer par une variable pour alimenter le tableau. Un tableau à une dimension peut être peuplé comme je le montre dans le code initial avec Array(...), ce qui a l'avantage de la concision au niveau du code.

    EN VBA/Excel, on pourrait utiliser t = [{"{Femme}","Martine";"{Mari}","Pierre"}] pour créer le tableau à deux dimensions, mais je préfère que la fonction soit la plus générique possible. C'est pourquoi le tableau à une dimension offrant la possibilité d'utiliser la fonction Array a ma préférence.