Trier le contenu d’un LisBox ou d’un ComboBox à 1 seule colonne

Lermiton

XLDnaute Nouveau
Bonjour à tous.

Attention : erreur de référence dans le titre, il s'agit de Excel 2003 et non pas 2007
(mais mon code devrait marcher sous Excel 2007, au nom de la compatibilité ascendante)

J’ai longtemps cherché comment trier les lignes d’un ListBox ou d’un ComboBox à une seule colonne, sans passer par la recopie temporaire des données sur une feuille Excel, et en évitant d’utiliser la propriété « ControlSource ». Et je voulais permettre au cas par cas les choix suivants :
- conserver ou non en tête la première ligne de donnée après le tri (en tant que « titre » des données)
- trier en ordre croissant ou décroissant
- éliminer ou non les doublons

Grâce aux renseignements glanés sur le site (merci à leurs auteurs !), je suis arrivé à une solution opérationnelle qui trie les données directement dans le contrôle (un ListBox en l’occurrence). Mais ça s’avère trop long lorsque la liste des données est importante.

J’ai donc modifié mon code, en utilisant comme tampon de tri une variable « Tampon() ». C’est autrement plus rapide : sur ma machine 0,5 seconde pour une liste de 500 lignes de chaînes comportant de 1 à 100 caractères.

Je soumets ici une version simplifiée du code (avec tampon), qui ne permet pas de choix au cas par cas, mais où on peut modifier les options (voir les lignes de commentaires commençant par « ==> »). Pour que le tri ne fasse pas passer le « à » après le « z », le module doit comporter en tête l’option « Option Compare Text ». Et, la procédure étant externe au Userform, son appel doit se faire comme ceci : Trier_Box [NomDuUserform].[NomDuControle]

Et pour ceux que le code complet (avec choix au cas par cas) intéresse ou qui souhaitent tester mes solutions (avec ou sans tampon), je joins un fichier de test qui donne aussi les consignes d'utilisation du code, lequel n'est pas verrouillé.

Les commentaires et critiques seront les bienvenus.
Bonne journée.

Code:
Option Explicit

Option Compare Text

Sub Trier_Box(Ctrl As Control)
    Dim n, x, y, Deb, Fin As Integer
    Dim a, b As String
    Dim Tampon() As String
    
Rem     Vérifie le type du controle à trier
    If TypeName(Ctrl) <> "ListBox" And TypeName(Ctrl) <> "ComboBox" Then
        Err.Raise 600, , "Le contrôle à trier doit être un ListBox ou un ComboBox."
    End If

Rem     Vérifie que le controle n'est pas vide
    If Ctrl.ListCount = 0 Then
        Err.Raise 601, , "Le contrôle à trier est vide !"
    End If

Rem     Recuperation des données non vides du controle dans le Tampon
    For x = 0 To Ctrl.ListCount - 1
        If Ctrl.List(x, 0) <> "" Then
            n = n + 1
            ReDim Preserve Tampon(n)
            Tampon(n) = Ctrl.List(x, 0)
        End If
    Next

Rem     Vide le controle
    Ctrl.Clear

Rem     Tri dans le Tampon
'==> Si la 1ère ligne doit rester en tête, remplacez "Deb = 1" par "Deb = 2"
    Deb = 1
    Fin = UBound(Tampon())
    
    For x = Deb To Fin - 1
        For y = x + 1 To Fin
            a = Tampon(x)
            b = Tampon(y)
'==> Si vous voulez un tri descendant, rempacez "If a > b Then" par "If a < b Then"
            If a > b Then
                Tampon(x) = b
                Tampon(y) = a
            End If
        Next
    Next

Rem     Suppression des doublons dans Tampon si c'est demandé
        ' les doublons sont remplacés par des chaînes vides qui ne seront pas recopiées
'==> Si vous voulez conserver les doublons, supprimez cette boucle "For ... Next"
    For n = UBound(Tampon()) To 2 Step -1
        If Tampon(n) = Tampon(n - 1) Then
            Tampon(n) = ""
        End If
    Next

Rem     Recopie les données du Tampon dans le contrôle
    For n = 1 To UBound(Tampon())
        If Tampon(n) <> "" Then
            Ctrl.AddItem Tampon(n)
        End If
    Next

Rem finale
    Erase Tampon

End Sub
 

Pièces jointes

  • Tri_Box.zip
    39.1 KB · Affichages: 48
Dernière édition:

Staple1600

XLDnaute Barbatruc
Re : Trier le contenu d’un LisBox ou d’un ComboBox à 1 seule colonne

Bonjour Lermiton


Avais-tu vu ceci et cela dans la FAQ d'XLD ?

Personnellement, pour trier , j'utilise (sous condition) ceci
VB:
Private Sub UserForm_Initialize()
Dim t
With Sheets(1).Range([A1], [A65536].End(xlUp))
    .Sort .Cells(1, 1): t = .Value: ComboBox1.Clear
    ComboBox1.List = t
End With
End Sub

PS:
je joins un fichier de test qui donne aussi les consignes d'utilisation du code, lequel n'est pas verrouillé.
Pourquoi le serait-il dans le cadre d'un échange/partage de savoirs ?
 
Dernière édition:

Lermiton

XLDnaute Nouveau
Re : Trier le contenu d’un LisBox ou d’un ComboBox à 1 seule colonne

Bonsoir Stapl1600.

Non, je n'avais vu ni "ceci" ni "cela", je suis allé voir, et il me semble que, comme dans ta solution, c'est justement ce que je veux pas faire : utiliser une feuille Excel pour faire le tri.

Pourquoi ?
D'une part pour éviter que Excel considère le classeur comme modifié et me rabatte les oreilles avec son "voulez-vous enregistrer ?" seulement parce que j'ai fait un tri.
Et d'autre part, parce qu'il me semble (à tord peut-être ?) que le tri dans une variable va plus vite que dans une feuille de calcul, même si on prend les précautions "ScreenUpdating = False" ou "Calculation = xlCalculationManual".

Pourquoi le serait-il dans le cadre d'un échange/partage de savoirs ?
Ben oui, ça va sans dire ... mais ça va encore mieux en le disant, non ?

Bonne fin de soirée.
 

Discussions similaires

Réponses
2
Affichages
92

Statistiques des forums

Discussions
312 215
Messages
2 086 329
Membres
103 184
dernier inscrit
Di Martino