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.
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
Dernière édition: