XL 2010 Trier un dictionnaire par ordre alphabétique

Magic_Doctor

XLDnaute Barbatruc
Bonsoir,

Sur une feuille il y a plusieurs ComboBox. Seuls certains recueillent une liste d’items se trouvant dans la même base de données située sur une autre feuille. Quand on ouvre le classeur, tous les ComboBox concernés par ladite liste sont chargés. Quand on choisit un item dans l’un de ces ComboBox, il disparaît dans la liste des autres ComboBox, de telle sorte qu’il est impossible de choisir par inadvertance plusieurs fois le même item. Jusqu’à présent tout marche bien. Mon seul souci, c’est que je voudrais que les ComboBox présentent une liste triée par ordre alphabétique. En effet, dans la BD cette liste n’est pas forcément ordonnée par ordre alphabétique (comme dans la PJ). J’ai trouvé une fonction (ici) qui, théoriquement, devrait permettre de résoudre ce problème, mais je n’ai pas su l’adapter à l’application.
 

Pièces jointes

  • Dico.xlsm
    43.2 KB · Affichages: 13

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Merci pour votre intervention. Ça marche, mais dommage que dans la liste de chaque ComboBox la dernière ligne est inutilement vide.
Il suffisait donc de remplacer :
VB:
liste = SortDictionaryByKey (liste)
par :
VB:
SortDictionaryByKey (liste(c))
Franchement, je n'y aurais pas pensé.
Par curiosité, j'ai fait la substitution dans le fichier natif et, contre toute attente, ça ne marche pas avec en plus la dernière ligne de chaque liste vide. Il est tard chez moi, peut-être la fatigue... mais aurais-je raté quelque chose ?

Encore merci et bonne journée septentrionale.
 

job75

XLDnaute Barbatruc
Bonjour Magic_Doctor, M12, le forum,

Le plus simple est de trier la plage source :
VB:
    With f2.Range("ListeItems").Offset(, 2)
        .Value = .Offset(, -2).Value
        .Sort .Cells, xlAscending, Header:=xlNo 'tri
        For Each c In .Cells
            If Len(c) Then liste(c.Value) = "" 'on remplit le dictionnaire
        Next
        .ClearContents
    End With
Notez aussi que On Error Resume Next est inutile car on teste plus loin liste.Exists(c.Object.Value)

A+
 

Pièces jointes

  • Dico (1).xlsm
    45.1 KB · Affichages: 7

Magic_Doctor

XLDnaute Barbatruc
Bonjour job, le forum,

Bravo ! En effet, pourquoi faire compliqué quand on peut faire simple. Pour un truc, ma foi, assez sophistiqué, la solution finit par être, disons, minimaliste. Cela dit en passant, cette application est très pratique quand on a plusieurs ComboBox avec les mêmes items.
Quoi qu'il en soit, tout comme les Arrays, trier les dicos c'est plutôt tartignole... Curieux que Microsoft n'ait pas conçu des fonctions pour le faire.

A +
 

patricktoulon

XLDnaute Barbatruc
Bonjour
Curieux que Microsoft n'ait pas conçu des fonctions pour le faire.
ben en fait Si !! il l'a fait ( et depuis longtemps) sauf que c'est pas l'object "scripting.dictionary"
mais le
system.collection.arraylist qui possède sa propre fonction".sort"
qui est plus un tableau car il n'a pas de key/item
et le
system.collection.sortedlist 'qui est trié automatiquement dans l'ordre chron ou apha
qui est tres similaire au dictionnaire
et plus recemment
system.collection.generic.sortedlist 'idem que son prédécesseur (je ne l'ai pas encore étudié en VBA)
qui est le même mais plus récent

pour le sortedlist
late binding
VB:
Set SortL= CreateObject("System.Collections.SortedList")
early binding
Code:
dim SortL as new SortedList
une source parmi tant d'autres ci dessous

pour le arraylist
late binding
VB:
Set ARRL = CreateObject("System.Collections.ArrayList")
early binding
VB:
Dim ARRL As New ArrayList
une source parmi tant d'autres ci dessous

si tes mises a jour Windows sont a jour
donc tu a certainement une des version de net framework ci dessous ,donc tu l'a dans tes librairies
.NET Framework1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8

have a good day ;)
 

Magic_Doctor

XLDnaute Barbatruc
Re,

Je viens d'essayer en m'appuyant sur l'exemple du @Grand Chaman Excel et ça marche !
L'euphorie aidant, j'ai tenté de remplacer :
VB:
Sub CreeListeDispo(nomCombo$)

Dim f1 As Worksheet, f2 As Worksheet, c, liste As Scripting.Dictionary

    Set f1 = Sheets("Données")
    Set f2 = Sheets("BD")
    Set liste = New Dictionary                   'le dictionnaire
    
    With f2.Range("ListeItems").Offset(, 2)      'on tri, par ordre alphabétique, dans une colonne "fantôme" dédiée sur la feuille "BD"
        .Value = .Offset(, -2).Value             'récupération dans la colonne "fantôme" de l'intégralité de "ListeItems"
        .Sort .Cells, xlAscending, Header:=xlNo  'tri
        For Each c In .Cells
            If Len(c) Then liste(c.Value) = ""   'on remplit le dictionnaire
        Next
        .ClearContents                           'la colonne "fantôme" est purgée
    End With
            
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
            If liste.Exists(c.Object.Value) Then liste.Remove c.Object.Value
        End If
    Next
    
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
            c.Object.List = liste.Keys
        End If
    Next
End Sub
par :
VB:
Sub CreeListeDispo(nomCombo$)

Dim f1 As Worksheet, f2 As Worksheet, c
Dim cel As Range, AL As Object

    Set f1 = Sheets("Données")
    Set f2 = Sheets("BD")
    Set AL = CreateObject("System.Collections.ArrayList")
    
    For Each cel In f2.Range("ListeItems")       'on dresse l'Array
       AL.Add cel.Text                           'il faut utiliser ".Text" sinon impossible de trier, car on enverrait un "range"
    Next
    AL.Sort                                      'tri, par ordre alphabétique, de l'Array
    
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
'            If liste.Exists(c.Object.Value) Then liste.Remove c.Object.Value
             AL.Remove c.Object.Value
        End If
    Next
    
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
'            c.Object.List = liste.Keys
            c.Object.List = AL  'ça plante là
        End If
    Next
End Sub
Mais ça beugue...
 

Magic_Doctor

XLDnaute Barbatruc
Bonsoir,

J'ai finalement réussi à résoudre le problème en tombant sur un blog du Grand Chaman Excel (ici) :
VB:
Sub CreeListeDispo(nomCombo$)

Dim f1 As Worksheet, f2 As Worksheet, c, AL As Object

    Set f1 = Sheets("Données")
    Set f2 = Sheets("BD")
    Set AL = CreateObject("System.Collections.ArrayList")
    
    For Each c In f2.Range("ListeItems")  'on dresse l'Array "AL"
       AL.Add c.Text                      'il faut utiliser ".Text" sinon impossible de trier, car on enverrait un "Range"
    Next
    AL.Sort                               'tri, par ordre alphabétique, de l'Array
    
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
             AL.Remove c.Object.Value
        End If
    Next
    
    For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
            c.Object.List = AL.ToArray
        End If
    Next
End Sub
Un peu plus concis et le tri se fait hors de la feuille.
 

Pièces jointes

  • Dico2.xlsm
    42.4 KB · Affichages: 6

patricktoulon

XLDnaute Barbatruc
re
bonjour
voilà t a tout compris ;)
conclusion Ms l'avait fait ;)

bien que l'idée ( de @job75) de tri sur feuile avant reste la meilleure solution et la plus économique
j’étais intervenu uniquement pourdire qu' il existait donc bien un outils a cet effet utilisable en VBA
garde bien au chaud les deux liens ;)
 

ChTi160

XLDnaute Barbatruc
Bonjour Magic_Doctor
Bonjour le Fil ,le Forum

il n'y aurait pas moyen de fusionner ces deux Boucles ?
VB:
For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
             AL.Remove c.Object.Value
        End If
Next
    
For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
            c.Object.List = AL.ToArray
        End If
Next
'En
For Each c In f1.OLEObjects
        If TypeName(c.Object) = "ComboBox" And Left(c.Name, 10) = nomCombo Then  'on passe en revue tous les ComboBox présents dans la feuille et on ne retient que ceux dont le nom commence par "ComboListe"
             AL.Remove c.Object.Value
                       c.Object.List = AL.ToArray
        End If
Next
Bonne journée
Jean marie
 

Discussions similaires

Membres actuellement en ligne

Statistiques des forums

Discussions
312 177
Messages
2 085 972
Membres
103 073
dernier inscrit
MSCHOE16