Commentaires

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

    Je viens de consulter ce billet.
    Très belle fonction qui intègre les WorksheetFunction de VBA. Sauf erreur, toutes les fonctions natives du tableur ne le sont pas. J'ai donc vérifié.

    Dans ma contribution,

    ces 4 lignes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Dim tb() As Variant
    ReDim tb(1 To rng_dest.Count)
    tb = Application.Transpose(rng_dest)
    
    liste_adresses = Join(tb, ";")
    sont remplacées par 1 seule

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste_adresses = Application.WorksheetFunction.TextJoin(";", True, rng_dest)
    ou bien, si l'on intègre les 2 fonctions citées TRIER et UNIQUE

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste_adresses = Evaluate("=TEXTJOIN("";"",TRUE,SORT(UNIQUE(" & rng_dest.Address & ")))")
    Je m'empresse donc de l'actualiser.

    Une remarque au demeurant,

    TRI retourne une erreur. Ce car Excel considère, du moins sur sa version 2016, comme "taux de rendement interne"
    Il me faut écrire TRIER

    =JOINDRE.TEXTE(";";VRAI;TRIER(UNIQUE(T_liste2[détail_liste])))
    Merci.
    Mis à jour 26/10/2020 à 18h36 par MarcelG
  2. Avatar de Pierre Fauconnier
    • |
    • permalink
    Citation Envoyé par MarcelG
    [...]

    Je préfère, et de loin, .[...]
    Nous sommes bien d'accord. J'ai pris aussi l'habitude de préfixer mes contrôles et de leur donner un nom explicite.

    Chimay bleue (ne pas abuser car c'est du costaud), c'est la brune. L'autre, la blonde un peu ambrée, c'est la Triple Karmeliet... Ne pas abuser non plus...

    Une autre, pas mauvaise du tout mais un peu plus traître pour moi, c'est la Rochefort 10 (un peu plus de 11°). Une tuerie à boire avec modération...

    Cela étant, aller en Toscane ou dans les Pouilles pour découvrir les jus de raisin de là-bas ne serait pas pour me déplaire...

    Bonne soirée et
  3. Avatar de MarcelG
    • |
    • permalink
    D'accord, Pierre.
    A tort, je confondais Propriété et mot clé. Je voulais simplement signifier que Value fait partie du langage VBA.
    Don't Act.

    Au demeurant, cet échange sous-entend un autre sujet sur lequel je m'interroge bien souvent.
    A savoir, la dénomination des objets.
    Et je l'ai d'ailleurs maintes fois mentionné sur le forum.

    On voit trop de .

    Je préfère, et de loin, .

    Ces considérations rentrent dans un cadre général qui concerne la clarté, donc la rigueur dans la manière de coder. Voir mon dernier billet.

    Mais tout cela constitue un autre débat.

    Bonne soirée à toi.

    Et n'oublie pas la Chimée Bleue (l'autre marque, je ne m'en rappelle plus.)
    Il devrait y avoir un sous forum boissons (bières, vins, alcools...)
  4. Avatar de Pierre Fauconnier
    • |
    • permalink
    Citation Envoyé par MarcelG
    [...]
    Si l'objet en question est Range, cela donne

    [...]
    On ne pourra jamais éviter cela à 100%. Pour moi, le principe consiste à ne pas utiliser de mots-clé VBA, ou plus généralement de mots-clé du langage utilisé. Value n'est pas un mot-clé VBA, mais la propriété d'un objet particulier d'une bibliothèque particulière, donc je n'ai personnellement aucun problème à l'utiliser comme nom de variable ou de propriété dans mes propres développements.

    Dans la mesure où je systématise mon approche et mon code autant que possible, j'ai dû faire un choix et appeler Value la valeur que l'on attribue à une propriété d'un objet ne m'a pas paru idiot ou bizarre (la preuve, c'est que les ingénieurs de MS l'on fait avec un objet Range)...

    Les appellations des procédures, fonctions, propriétés, variables (ce que sont les arguments d'une fonction), modules et classes seront toujours sujettes à caution. Certains mettent des appellations anglaises ou (mal) anglicisées, d'autres ne jurent que par le français, d'autres écrivent des abréviations dont eux-mêmes ne connaissent plus le sens lorsqu'ils se replongent dans le code six mois plus tard ...

    Le choix des uns paraîtra bizarre aux autres, et vice versa. Perso, un Value.Value ne me gêne pas, comme un range("a1").Parent.Parent pour remonter au classeur ne me gêne pas
    Mis à jour 14/10/2020 à 07h52 par Pierre Fauconnier
  5. Avatar de MarcelG
    • |
    • permalink
    'ai décidé une fois pour toutes d'appeler Value un paramètre passé à une propriété d'un objet...
    Oui mais ne crois-tu que, pour la plupart des néophytes dont je suis, cette écriture puisse porter à confusion?

    Si l'objet en question est Range, cela donne

    C'est juste un avis.
  6. Avatar de Pierre Fauconnier
    • |
    • permalink
    Bonjour Marcel

    Citation Envoyé par MarcelG
    [...]pour laquelle, au passage, je n'ai pas aperçu de fichier joint[...]
    Cette discussion est polluée par des gens qui n'ont pas compris grand chose aux tableaux structurés, aux bases de données et à la programmation, et qui s'imaginent que l'informatique, c'est de la philosophie de café de commerce où même les plus cons (surtout les plus cons) ont droit de parole et pensent que l'informatique est "relative", qu'on peut faire n'importe quoi et que toutes les idées et pratiques se valent.




    Citation Envoyé par MarcelG
    [...]Tu fais allusion, dans ce billet, à une discussion. En as-tu le lien?[...]
    En cliquant sur le bouton à droite de mon nom, tu atterris sur la discussion...

    Citation Envoyé par MarcelG
    [...]
    Ici, dans le code du formulaire, que représente "Value" en tant que paramètre des 2 Property.

    Sans doute par ignorance, j'ai du mal à m'y retrouver, surtout lorsque des mots clés de VBA sont ainsi utilisés.[...]
    Value n'est pas un mot-clé de VBA. Dans le cas présent, c'est simplement le nom de l'argument que je passe à la propriété. Pour éviter de me gratter l'occiput à trouver des noms de paramètres, j'ai décidé une fois pour toutes d'appeler Value un paramètre passé à une propriété d'un objet...

    Mis à jour 14/10/2020 à 07h51 par Pierre Fauconnier
  7. Avatar de MarcelG
    • |
    • permalink
    Au temps pour moi!

    Tu injectes dans les Property les valeurs définies dans le module standard. D'où d'ailleurs Property Let
    C'est le "Value" qui m'interpellait.

    Perso, je préfère ce type de développement à celui que tu exposais dans la discussion que j'ai consultée.

    D'autant qu'il est adaptable à x combobox.

    A plus tard.
  8. Avatar de MarcelG
    • |
    • permalink
    Bonjour Pierre,

    Je me réfère à ce développement par rapport à cette discussion (pour laquelle, au passage, je n'ai pas aperçu de fichier joint).

    Tu fais allusion, dans ce billet, à une discussion. En as-tu le lien?

    Ici, dans le code du formulaire, que représente "Value" en tant que paramètre des 2 Property.

    Sans doute par ignorance, j'ai du mal à m'y retrouver, surtout lorsque des mots clés de VBA sont ainsi utilisés.
    Je ne vois pas explicitement la logique de ce code. Trop fort pour moi

    Merci pour ton retour.

    Cordialement.

    Marcel
  9. Avatar de MarcelG
    • |
    • permalink
    Salut Pierre,

    D'accord.
    Merci pour ces précisions.

    A plus tard.
  10. 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.
  11. 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 à 15h54 par MarcelG
  12. 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 à 14h04 par MarcelG
  13. 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.
  14. 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
  15. 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.
  16. 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.
  17. 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
  18. Avatar de User
    • |
    • permalink
    Sympa ce billet !

    Je ne connaissais pas la formule.

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

    Merci pour ton appréciation et bon weekend
  20. 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
Page 1 sur 5 12345 DernièreDernière