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 :

blocage sur tri de listbox


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2010
    Messages : 23
    Par défaut blocage sur tri de listbox
    Bonjour,
    après recherche sur le forum j'ai trouvé votre solution de tri sur date d'une listbox.
    J'ai le blocage en exécution sur la ligne 6 avec message "incompatibilité de type".
    J'ai placé le code de tri dans un module du formulaire, je l'appelle dans l'initializ du formulaire après remplissage de la list, qui comprend 4 colonnes , la date étant la 3è col . Les dates sont renseignées dans la liste au format dd/mm/yyyy à partir d'une colonne du tableau excl. Je suis en excel 2007.
    Voyez-vous une réponse à ce pb ?
    Cdlmt, JP

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Salut.

    Avec le code, c'est plus facile...

    Note que les dates, dans une listbox, sont considérés comme tu texte. Dès lors, au format que tu proposes, tu n'auras jamais un bon tri. Certaines "solutions" proposent de chargeer les données dans un tableau vba (un array), mais tu vas devoir transformer tes dates pour pouvoir les trier correctement (je suppose que si tu tries sur les dates, tu souhaites un ordre chronologique).

    Ma première idée, pour être pragmatique et penser Excel avant de penser VBA (voir ma signature), sans connaître tes données ni leur provenance, mais en voyant que tu charges la liste dans l'initialize (pas une bonne idée, au passage), serait de trier la plage (normalement un tableau structuré) qui alimente la listbox. Tu délègues ainsi à Excel le travail de tri, et tu ne t'embêtes pas à essayer de le faire avec des arrays et des transformations de données.

    Comme je l'explique dans ce message, tu as intérêt à généraliser ton code et à le couper en "petites" procédures/fonctions qui ne font qu'une chose...

    Ici, sur base du tableau illustré ci-dessous, je vais utiliser une fonction générique qui trie un tableau structuré. Cette fonction est placée dans un module standard.

    Nom : 2020-04-26_204531.png
Affichages : 698
Taille : 4,1 Ko

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Sub Table_Sort(Tablename As String, SortArray)
      Dim lo As ListObject
      Dim Counter As Long
     
      Set lo = Range(Tablename).ListObject
      With lo.Sort
        .SortFields.Clear
        For Counter = 0 To UBound(SortArray) Step 3
          .SortFields.Add Range(Tablename & "[" & SortArray(Counter) & "]"), SortArray(Counter + 1), SortArray(Counter + 2)
        Next
        .Apply
      End With
    End Sub
    Je vais créer une procédure qui appelle le userform et qui va d'abord trier le tableau sur les dates de naissance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Sub ShowUserform1()
      Table_Sort "t_Contacts", Array("DN", xlSortOnValues, xlAscending)
      With UserForm1
        .ListBox1.List = Range("t_Contacts").Value
        .Show
      End With
    End Sub
    Voici la listbox du userform après ouverture, triée sur les dates

    Nom : 2020-04-26_204939.png
Affichages : 722
Taille : 4,3 Ko

    Si tu la souhaites triée sur le noms puis les prénoms, il te suffit de changer l'ordre de tri en modifiant les arguments de Table_Sort avant ouverture du formulaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Sub ShowUserform2()
      Table_Sort "t_Contacts", Array("Nom", xlSortOnValues, xlAscending, "Prénom", xlSortOnValues, xlAscending)
      With UserForm1
        .ListBox1.List = Range("t_Contacts").Value
        .Show
      End With
    End Sub
    Nom : 2020-04-26_205130.png
Affichages : 686
Taille : 4,1 Ko


    Attention, la lecture du code de la procédure de tri te fera comprendre que ton tableau structuré sera trié différemment. Normalement, dans un classeur bien construit et sauf à de très rares exceptions, la modification du tri de la table de données ne peut avoir aucun impact sur ton classeur.
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    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...
    ---------------

  3. #3
    Membre extrêmement actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    1 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 1 369
    Par défaut
    Bonsoir,

    Voici un exemple de tri de ListBox. Les dates sont au format jj/mm/aaaa.
    L'ordre n'est pas modifié dans la table mais seulement le ListBox;

    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
    Private Sub UserForm_Initialize()
      NomTableau = "tableau1"
      Me.ListBox1.ColumnCount = Range(NomTableau).Columns.Count
      If Range(NomTableau).Item(1, 1) <> "" Then Me.ListBox1.List = Range(NomTableau).Value
      Me.Label1.Caption = Me.ListBox1.ListCount & " Ligne(s)"
      Me.ComboBox1.List = Application.Transpose(Range(NomTableau).ListObject.HeaderRowRange)
    End Sub
     
    Private Sub ComboBox1_click()
      Dim Tbl()
      colTri = Me.ComboBox1.ListIndex
      Tbl = Me.ListBox1.List
      TriMultiCol Tbl, LBound(Tbl), UBound(Tbl), colTri
      Me.ListBox1.List = Tbl
    End Sub
    Nom : Sans titre - Copie (10).png
Affichages : 722
Taille : 8,0 Ko

    Boisgontier
    Fichiers attachés Fichiers attachés

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2010
    Messages : 23
    Par défaut blocage sur tri de listbox
    Bonjour Pierre,
    d'abord un grand merci d'avoir répondu aussi rapidement ( vive le confinement ? ), en tous les cas je constate que ce forum est toujours aussi vivant, bravo !
    Tu as parfaitement compris l'objet de mon programme : visualiser sur une période à la demande les anniversaires des membres de la famille

    Effectivement face aux difficultés de tri, je me doutais bien que les dates seraient un problème !, j'ai opté pour la solution que vous préconisez : à savoir je constitue la liste dans une colonne décalée ( non visible) de la feuille de données en faisant une sélection par un critère de choix de période de consultation (en nombre de jours) et je fais le tri dessus. Ensuite après le choix de la période je charge ma liste box avec ces données .
    Par contre je n'ai pas compris ta remarque sur le principe du chargement des données de la listbox à l'initialisation du formulaire ?

    Mais je suis vivement intéressé par ta méthode car je suis nul en manipulation de tableau, je vais donc analyser çà en détail (on a jamais fini d'apprendre avec excel !), notamment comment désigner dans un module de classe les contrôles d'un formulaire : worksbook("dossier").userform("Titi").textbox "machin"... ?? pour l'instant j'ai résolu le problème en mettant mes procédures dans un module du userform ce qui me permet d'atteindre tous les contrôles par me.

    Cordialement, JPierre

  5. #5
    Membre extrêmement actif
    Homme Profil pro
    Inscrit en
    Septembre 2013
    Messages
    1 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 1 369
    Par défaut
    Bonjour,



    >visualiser sur une période à la demande les anniversaires des membres de la famille


    Il ne s'agit pas d'un tri mais d'une sélection entre 2 dates

    Nom : Sans titre - Copie (11).png
Affichages : 730
Taille : 11,0 Ko

    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
    Dim TblBD(), nomTableau, NbCol, ColDate, Dates()
    Private Sub UserForm_Initialize()
      nomTableau = "Tableau1"
      TblBD = Range(nomTableau).Value
      NbCol = Range(nomTableau).Columns.Count
      ColDate = 2
      EnteteListBox
      '---Dates
      Set d = CreateObject("scripting.dictionary")
      ColDate = 2
      For i = LBound(TblBD) To UBound(TblBD)
        d(TblBD(i, ColDate)) = ""
      Next i
      Dates = d.keys
      Tri Dates, LBound(Dates), UBound(Dates)
      Me.ComboBox2.List = Dates: Me.ComboBox2 = Dates(0)
      Me.ComboBox3.List = Dates: Me.ComboBox3 = Dates(UBound(Dates))
      Filtre
      Me.ComboTri.List = Application.Transpose(Range(nomTableau).ListObject.HeaderRowRange)
    End Sub
     
    Private Sub ComboBox2_click()
       Filtre
    End Sub
     
    Private Sub ComboBox3_click()
      Filtre
    End Sub
    Private Sub ComboBox1_click()  ' alimentation ListBox
       Filtre
    End Sub
     
    Sub Filtre()
        Dim Tbl()
        début = CDate(Me.ComboBox2)
        fin = CDate(Me.ComboBox3)
        n = 0
        For i = LBound(TblBD) To UBound(TblBD)
          If TblBD(i, ColDate) >= début And TblBD(i, ColDate) <= fin Then
            n = n + 1: ReDim Preserve Tbl(1 To NbCol + 1, 1 To n)
            For c = 1 To NbCol
              Tbl(c, n) = TblBD(i, c)
            Next c
           End If
         Next i
         If n > 0 Then Me.ListBox1.Column = Tbl Else Me.ListBox1.Clear
    End Sub

    Boisgontier
    Fichiers attachés Fichiers attachés

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2010
    Messages : 23
    Par défaut
    Waouhh !! je sens que je vais avoir du boulot !!!
    merci pour le cours, je vais étudier çà tranquillement car je trouve dans tes codes plein de notions que je ne connaissais pas, comme la déclaration Data ...
    Après un rapide coup d'oeil la procédure tri (a,gauc,droi) [dans un des modules du pgm que tu as joint (tri entre 2 dates)]m'interpelle :
    tu utilises des variables a, g, d , ref , etc mais je ne trouve pas les déclarations dim ... ? je suppose que vba se débrouille ! ou alors j'ai raté un métro
    Je ne comprends pas bien la structure de ce module , à la fin tu rappelles la procédure ( call Tri ..) , j'ai l'impression qu'on boucle ?? je ne trouve pas la sortie
    Mais je ne veux pas monopoliser ton temps, je vais prendre le temps de réfléchir à tout çà, ta méthode de programmation structurée me plaît bien, je l'utilise déjà en partie mais pas assez.

    je n'avais pas remarqué l'intervention de Jacques que je remercie de la participation , mais je m'y perds un peu vous êtes bien 2 interlocuteurs différents ??? j'ai un doute
    cette messagerie est curieuse car je ne reçois pas tout en même temps

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2010
    Messages : 23
    Par défaut
    Citation Envoyé par boisgontierjacques Voir le message
    [...]
    Bonsoir Jacques, n'étant pas certain que tu vois tous les échanges (?) peux-tu me confirmer que tu as accès aux messages que j'ai eu avec Pierre ? si non je te reposerai la question que je lui ai posé par erreur concernant le pgm sélection entre 12 dates que tu m'as gentiment envoyé.
    JP

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    @ Boisgonter

    Filtrer les anniversaires sur les dates de naissance? Inattendu et rigolo, comme démarche... ^^


    @Rominet

    Si tu veux connaître les anniversaires à fêter entre le 01/04 et le 30/06, ce n'est pas sur les dates de naissance que tu dois filtrer, mais sur les dates d'anniversaire. Tu as deux méthodes possibles:
    • Reconstituer les dates de naissance en les mettant toute à l'année courante (2020 en l'occurrence*) puis filtrer sur celles qui sont dans la période voulue;
    • Travailler sur le format MMDD des dates pour ne pas tenir compte de l'année.



    J'ai opté pour la seconde solution dans le code que je présente, sur base du tableau t_Famille illustré ci-dessous:
    Nom : 2020-04-27_142242.png
Affichages : 666
Taille : 3,7 Ko

    Voici la procédure qui prépare et charge le userform à mettre dans un module standard (je me passe de l'événement Initialize):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Sub Test()
      With UserForm1
        .Data = Range("t_Famille").Value
        .Show
      End With
    End Sub
    Voici le code du userform. On voit que, fidèle à une bonne architecture de code, l'événement sur le bouton "ne fait rien" à part appeler la procédure qui nettoie la liste et la remplit. On remarque dans le code la propriété publique Data qui reçoit l'array correspondant à la plage de données du tableau. On considère évidemment que le tableau est rempli avant l'opération.
    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
    Option Explicit
     
    Public Data
     
    Private Sub CommandButton1_Click()
      PrepareListbox
    End Sub
     
    Sub PrepareListbox()
      Dim Counter As Long
     
      With lboData
        .Clear
        For Counter = 1 To UBound(Data)
          If Format(Data(Counter, 2), "mmdd") >= Format(CDate(tboFirstDate), "mmdd") And _
            Format(Data(Counter, 2), "mmdd") <= Format(CDate(tboLastDate), "mmdd") Then
            .AddItem
            .List(.ListCount - 1, 0) = Data(Counter, 1)
            .List(.ListCount - 1, 1) = Data(Counter, 2)
          End If
        Next
      End With
    End Sub
    Voici, sur base du tableau ci-dessus, la liste remplie pour le deuxième trimestre.

    Nom : 2020-04-27_142712.png
Affichages : 670
Taille : 4,9 Ko

    Remarque: Le code ne teste pas la validité des dates saisies, qui sont a priori considérées comme du texte par le VBA. Pour un usage plus large, il conviendrait de tester que les valeurs saisies sont bien des dates.


    Je ne sais pas pourquoi tu as besoin de cela en VBA, mais si une solution Excel te tente, la voici avec les formules. Les cellules G1 et G2 sont nommées Début et Fin. Tu peux alors filtrer sur la troisième colonne pour extraire les données, ou passer par une mise en forme conditionnelle...

    Nom : 2020-04-27_142901.png
Affichages : 669
Taille : 61,2 Ko

    Nom : 2020-04-27_143807.png
Affichages : 697
Taille : 151,7 Ko




    * Si l'on voulait tendre vers du générique, il y aaurait lieu de choisir une année bissextile et de déterminer comment le 29/02 devrait être géré (en février ou en mars).
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    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...
    ---------------

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 125
    Billets dans le blog
    131
    Par défaut
    Je ne sais pas trop à qui tu réponds.

    Moi, j'utilise effectivement Public Data dans mon formulaire, pour respecter les bonnes pratiques de la manipulation des objets, par contre, je n'utilise ni a, ni gau, ni droi, et certainement pas sans déclarer mes variables. Option Explicit est systématiquement mis en début de module, j'en explique les raisons dans ce billet. Tu ne trouveras donc jamais dans mes codes de variables non déclarées. Ce serait pour moi un non-sens... Je n'utilise pas non plus la syntaxe Call Tri(...) parce que je ne vois pas l'intérêt du Call. Lorsque j'appelle une procédure, c'est avec la syntaxe "directe" ( Tri ...), bien plus largement répandue, ici et ailleurs .

    Du coup, je ne sais pas quelle solution ou quel mix de solutions tu as essayé...
    "Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
    ---------------
    Mes billets de blog sur DVP
    Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
    Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
    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...
    ---------------

  10. #10
    Membre averti
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Décembre 2010
    Messages : 23
    Par défaut
    Citation Envoyé par Pierre Fauconnier Voir le message
    [...]
    Avec mes excuses Pierre, mais je n'avais pas fait attention à l'auteur des messages , je croyais que nous étions que tous les deux. Donc c'est bien Jacques qui m'a envoyé et détaillé une solution , je m'en excuse auprès de vous deux. C'est vrai je ne suis pas trop familiarisé avec le fonctionnement du forum, mais en tous les cas merci pour votre contribution. Jacques pourra donc s'il le souhaite répondre à ma question, en attendant il faut que je me plonge dans ce que vous m'avez proposé tous les deux, mais là je sens qu'il va falloir que je change d'étage !! Mais c'est bon d'apprendre !
    Bonne soirée à tous les deux.
    JPierre

Discussions similaires

  1. [SSRS] [2K5] Blocage sur tri basique
    Par zebulo80 dans le forum SSRS
    Réponses: 2
    Dernier message: 04/07/2010, 22h49
  2. [C#] tri de listbox
    Par mod_pello dans le forum Windows Forms
    Réponses: 4
    Dernier message: 25/04/2006, 18h50
  3. Blocage sur récursivité de base
    Par gilles641 dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 07/04/2006, 13h42
  4. blocage sur Left
    Par TSS dans le forum Access
    Réponses: 5
    Dernier message: 10/03/2006, 12h33
  5. [10g1][OCI][C++][IIS] Blocage sur un update
    Par Herode dans le forum Interfaces de programmation
    Réponses: 2
    Dernier message: 21/02/2006, 09h32

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