Gestion de librairie Dictionnary
Bonjour forum,
J'ai pu évoluer sur un environnement VBA où je pouvais créer un dictionnaire avec la ligne de code:
Dim MyDico as dictionary
set MyDico as new dictionaryou encore pour une fonction
Public function trie( MyDico as Dictionary) as Dictionary
End subJ'ai chargé la librairie Microsoft Offie Runtime mais il ne reconnait pas cet écriture. Il affiche: Utilisateur a utilisé un style non défini.
Quelqu'un a t il une idée?
Merci d'avance.
Bonjour,
je ne vois pas bien le rapport entre le message d'erreur et tes lignes (?.!?)
Ceci dit déclare tes dictionary plutôt comme ça :
Dim dict
Set dict = CreateObject("Scripting.Dictionary")pour ne pas être tributaire de la version présente sur le pc.
Et si la fonction te pose toujours des problèmes laisse en Variant.
eric
Bonjour Eric,
Oui, je suis d'accord avec ta proposition. C'est de la sorte que je contourne l'autre façon de déclarer qui utilise dictement le mot "dictionary".
Pour la fonction, je demandais un contournement parce que scripting.dictionary ne fonctionne pas. Je n'ai pas pensé en style variant. Je vais tester.
Merci.
Bonjour Eric,
Le type variant modifie la nature de mon élément de sortie. Ma ligne de code:
MyDico = FonctionTrieDico(MyDico) plante par ce que l'élément de sortie est de type variant alors que MyDico est de type dictionary (même si on est passé par le scripting.dictionary).
Il semble qu'il y ait une bibliothèque spécifique à charger en plus de la biblio: "MS Office Runtime " pour le forcer à accepter les déclaration directe en
Dim Dico as DictionarySi tu déclares le dict comme je te l'ai indiqué plus besoin de se soucier des librairies.
Tu ne peux pas trier un dictionary directement.
On peut même se demander si tu as bien fait de choisir ça vu que son but est d'obtenir directement une valeur à partir d'une autre et pour cet usage nul besoin qu'il soit trié.
Il faut mettre items et keys dans 2 variables tableaux, faire ton tri sur l'un ou l'autre en faisant suivre sur le second, et reconstruire un dictionary.
Public function trie( MyDico as object) as object
dim it, ke
it=MyDico.items
ke=MyDico.keys
' trier
'...
Set trie = CreateObject("Scripting.Dictionary") ' ton nom de fonction
' construire le nouveau dico avec une boucle et trie.add clé, item
'...
End FunctionTu as un autre objet (ArrayList) qui a la méthode .Sort et permet un tri immédiat.
Sur cet exemple faire arrList.Sort
Ok. Je vais tester ta proposition.
Je souhaitais utiliser un bout de code qui fonctionne bien normalement. C'est celui là que je cherchais à utiliser. Je te le partage, tu me diras ce que t'en pense. Je vais voir comment l'adapter de mon côté si possible.
Public Function TrierDictionnaireParCle(Dico As Dictionary) As Dictionary
'par Excel-Malin.com ( http://excel-malin.com )
'Fonction VBA qui trie l'Object Dictionnary par clé
'ce code nécessite que la référence "Microsoft Scripting Runtime" soit activée
On Error GoTo ErreurTri
'définition des variables
'Dim Dict As Scripting.Dictionary
Dim DicoTemporaire As Scripting.Dictionary
Dim PaireTemporaire As Variant
Dim ArrayTemporaire() As Variant
Dim OrdreTemporaire As Variant
'Dim Txt As String
Dim i As Long
Dim j As Long
'Allocation de l'espace de mémoire pour un Array dynamique
ReDim ArrayTemporaire(0 To Dico.Count - 1)
' 1) Remplissage de l'Array avec les valeurs du Dictionnaire non-trié
For i = 0 To Dico.Count - 1
ArrayTemporaire(i) = Dico.Keys(i)
Next i
' 2) Tri de l'Array
For i = LBound(ArrayTemporaire) To UBound(ArrayTemporaire) - 1
For j = i + 1 To UBound(ArrayTemporaire)
If ArrayTemporaire(i) > ArrayTemporaire(j) Then
OrdreTemporaire = ArrayTemporaire(j)
ArrayTemporaire(j) = ArrayTemporaire(i)
ArrayTemporaire(i) = OrdreTemporaire
End If
Next j
Next i
' 3) Création d'un nouveau Dictionnaire (Temporaire)
Set DicoTemporaire = New Dictionary
' 4) Ajout des valeurs triées dans le Dictionnaire temporaire(à partir de l'Array créé précédemment)
For i = LBound(ArrayTemporaire) To UBound(ArrayTemporaire)
PaireTemporaire = ArrayTemporaire(i)
DicoTemporaire.Add Key:=PaireTemporaire, Item:=Dico.Item(PaireTemporaire)
Next i
' 5) Renvoi du Dictionnaire trié
Set TrierDictionnaireParCle = DicoTemporaire
Exit Function
ErreurTri:
Set TrierDictionnaireParCle = Nothing
End Functionoui, c'est exactement ça.
Tu as juste à remplacer la déclaration et l'initialistaion du dico par ce que je t'ai indiqué.
Merci de ton retour.
C'est bon au niveau de la sortie de fonction. L'objet en sortie est bien un dictionnaire, là pas de problème.
Seulement, quand je trie le dictionnaire avec
set MyDico = trie(MyDico)et que dans la suite du programme j'appelle dans un
for each key in MyDico.keys, le programme plante là encore.
Est ce à cause du type object en paramètre de fonction trie selon ta préconisation?
Public function trie( Dico as object) as object
set trie=createobject("Scripting.Dictionary")Je constate que le programme compile bien sans l'appelle de trie. Mais dès que je l'appelle, il y a un problème de compilation.
Et le problème de compilation n'a pas lieu sur la fonction trie ni sur aucune ligne où elle apparait. Je ne peux juste plus appeler les éléments de MyDico par MyDico.keys.
Un peu étrange tout pour moi, je te l'avoue.
Si tu donnais les messages d'erreurs au lieu de "ça plante" tu ne crois pas que ça aiderait ?
Dans for each key in MyDico.keys key doit être variant
For i = 0 To UBound(AA) - 1
If AA(i) <> BB(i) And AA(i) <> "" Then
D = AA(i)
If Not MonDico2.exists(D) Then MonDico2.Add D, cle
End If
Next iSur la ligne If not... Erreur d'exécution 91: "Variable objet ou varable de bloc with non définie"
Bonsoir,
Avec un VRAI tri
Sub TriDico()
Set f = Sheets("BD")
Set d1 = CreateObject("Scripting.Dictionary")
a = f.Range("A2:A" & f.[A65000].End(xlUp).Row) ' tableau a(n,1) pour rapidité
For i = LBound(a) To UBound(a)
If a(i, 1) <> "" Then d1(a(i, 1)) = ""
Next i
DicoTri d1
f.[C2].Resize(d1.Count) = Application.Transpose(d1.keys)
End Sub
Sub DicoTri(dico)
Tbl = dico.keys
Tri Tbl, LBound(Tbl), UBound(Tbl)
dico.RemoveAll
For i = LBound(Tbl) To UBound(Tbl)
dico(Tbl(i)) = ""
Next i
End Sub
Sub Tri(a, gauc, droi) ' Quick sort
ref = a((gauc + droi) \ 2)
g = gauc: d = droi
Do
Do While a(g) < ref: g = g + 1: Loop
Do While ref < a(d): d = d - 1: Loop
If g <= d Then
temp = a(g): a(g) = a(d): a(d) = temp
g = g + 1: d = d - 1
End If
Loop While g <= d
If g < droi Then Call Tri(a, g, droi)
If gauc < d Then Call Tri(a, gauc, d)
End SubCeuzin
If Not MonDico2.exists(D) Then MonDico2.Add D, cleta fonction s'appelle MonDico2 ???
Le dict à utiliser doit porter le nom de la fonction, je te l'avais mis en commentaire.
eric
Formidable, le tri est dichtomique à la lecture du code. Je ne le connaisse qu'en C.
Cela dit, quand je lance ton bouton dans le fichier excel, il s'affiche en MsgBOx: !argument ou appel de procédure incorrect dans le Sub TriDico.
Pour ce qui est de toon précédent message
eriiic a écrit :If Not MonDico2.exists(D) Then MonDico2.Add D, cleta fonction s'appelle MonDico2 ???
Le dict à utiliser doit porter le nom de la fonction, je te l'avais mis en commentaire.
eric
Je t'avoue que je n'ai pas compris le principe, désolé d'être si débutant. La fonction ne fonction pas comme les autre fonction du genre: set Dico =TrieDico( Dico ) ? Pourquoi le dictionnaire doit il porter le même nom que la fonction?
Je viens de me relire, ce que je n'ai pas fait tout à l'heure. Navré des diverses fautes d'écriture.
Je veux dire, plus lisiblement cette fois, je n'ai pas compris la raison pour laquelle le Dico doit porter le nom de la fonction systématiquement.
Bonjour,
parce que tu veux que ta fonction retourne le dico.
Et tu vois bien que c'est ce que fait la fonction que tu as collé après :
Set TrierDictionnaireParCle = DicoTemporaire
Exit FunctionLe mieux est d'appliquer bêtement et de tester.
eric
Bonjour Eric,
Merci beaucoup du retour.
Peut être une dernière question avant de clore le sujet, quand on supprime des éléments d'un dictionnaire ( pas forcéments aux extrémités du dico), la position des clés dictionnaire est elle recalculée automatiquement ? Ce qui implique que a taille diminue aussi du nombre d'éléments retirés? Ou le dictionnaire reste tel quel, avec des cases vides, sans redimensionnement automatique.
Merci encore du précieux temps que tu consacres à donner en réponse à mes interrogations.
Pareil.
Tu testes et tu reviens nous dire
Sert-toi de la fenêtre Espions. Tu sélectionnes une variable ou une expression dans le code que tu fais glisser dans cette fenêtre.
Par exemple avec monDic. Dans la fenêtre Espions tu ajoutes au bout .keys ou .items et tu peux contrôler
Entendu. Je ferai et te reviendrai à ce moment là. Merci encore.
Bonsoir,
- Tri dictionnaire Keys/Valeurs ou Tri Valeurs/Keys sous forme de procédure
- Tri dictionnaire Keys/Valeurs ou Tri Valeurs/Keys sous forme de fonction
Option Compare Text
Sub TriDicoKeysValeurs()
Set f = Sheets("BD")
Dim d1 As New Dictionary
Dim d2 As New Dictionary
d1.CompareMode = vbTextCompare
a = f.Range("A2:B" & f.[A65000].End(xlUp).Row) ' tableau a(n,2) pour rapidité
For i = LBound(a) To UBound(a)
If a(i, 1) <> "" Then d1(a(i, 1)) = a(i, 2)
Next i
Set d2 = DicoTriKeysVal(d1, 1) ' tri par clés
f.[d2].Resize(d2.Count) = Application.Transpose(d2.keys)
f.[e2].Resize(d2.Count) = Application.Transpose(d2.items)
End Sub
Function DicoTriKeysVal(dico, colTri) As Dictionary
Dim d As New Dictionary
Dim Tbl(): ReDim Tbl(1 To dico.Count, 1 To 2)
i = 0
For Each c In dico.keys
i = i + 1
Tbl(i, 1) = c: Tbl(i, 2) = dico(c)
Next c
Tri Tbl, LBound(Tbl), UBound(Tbl), colTri
For i = LBound(Tbl) To UBound(Tbl)
d(Tbl(i, 1)) = Tbl(i, 2)
Next i
Set DicoTriKeysVal = d
End FunctionCeuzin
Bonjour Ceuzin,
Merci beaucoup je pour na proposition que je vais tester. Je note que vous utilisez la déclaration directe Dim d1 as new dictionary sans passer par le scripting comme je demandais plus tôt.
C'est un détail mais qui simplifie l'écriture à mon sens. Comment charger cette librairie pour imposer le type dictionary comme les autres type "collection", "variant","string" etc. ..?
Merci d'avance.
Bonjour,
C'est un détail mais qui simplifie l'écriture à mon sens.
Là tu retournes à la case départ où il te faudra intervenir pour chaque version différente d'excel.
Fait une recherche sur le late binding, j'abandonne de t'expliquer moi.
eric