XL 2013 CreateObject("scripting.dictionary") et/ou variable tableau ?

BenHarber

XLDnaute Occasionnel
Bonjour le Forum,
J'ai trouvé la fonction VBA suivante sur développez.net (merci Mchel M) qui me permet de compter sans doublon les enregistrements d'une plage de cellules. Elle fonctionne bien (même si je ne vois pas trop à quoi CreateObject("scripting.dictionary") correspond...)

A présent, je souhaiterais utiliser les différentes valeurs trouvées dans cette plage de cellules. Je pensais pour cela les enregistrer dans une variable tableau [du type : monTab(0 à n)] : ma question est de savoir si je peux pour cela utiliser "dico" (?) ou si je dois obligatoirement créer une nouvelle variable tableau ?
Merci d'avance pour vos idées toujours constructives !
BH
Function compter_uniques(plage As Range) As Long

Set dico = CreateObject("scripting.dictionary")
For Each cellule In plage
ref = cellule.Value
If Not dico.exists(ref) Then
dico.Add ref, ref
End If
Next
compter_uniques = dico.Count
End Function
 

vgendron

XLDnaute Barbatruc
Bonjour
dico est une variable déclarée en tant que dictionnaire
un dictionnaire est constitué de clés associées à leur valeur
regarde ce site (une mine d'or) tu auras toutes les réponses et de nombreux exemples. et meme des solutions que tu n'imaginais meme pas.. (en tout cas.. c'est mon cas à chaque fois que j'y vais :-D

 

Dranreb

XLDnaute Barbatruc
Bonjour.
CreateObject("scripting.dictionary") correspond à un nouvel objet de type Dictionary défini par la scrrun.dll mais en liaison tardive ce qui n'apporte pas l'assistance à la programmation des instructions l'utilisant.
Pour l'avoir en liaisons anticipées, cochez la référence Microsoft Scripting Runtime et déclarez votre Dico As Dictionary. Vous pourez alor remplacer cette instruction par Set Dico = New Dictionary. Après quoi et en tapant dans le codes Dico. vous aurez les menbres disponibles de l'objet suggérés dans une liste.
Vous pourriez aussi le faire avec une Collection de VBA, à condition de mettre un On Error Resume Next au début pour ne pas avoir de plantage si la clé existe déjà.
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Bonjour,

Si la plage est grande, utiliser un Array accelère la fonction.

VB:
Function compter_uniques(plage As Range) As Long
   Set d = CreateObject("scripting.dictionary")
   Tbl = plage.Value
   For Each c In Tbl
     If c <> "" Then d(c) = ""
   Next
   compter_uniques = d.Count
End Function


-L'objet Dictionary associe des valeurs à des clefs.
-L'objet Dictionary permet notamment de générer des listes sans doublons.
-Cet objet, simple à programmer, est très performant.
-Dictionary peut être vu comme un tableau à une dimension. On accède aux élément par une clé et non pas un indice.
-Pour les ajouts/suppressions, l'objet Dictionary est + facile à utiliser qu'un tableau (Redim + indice à gérer).
L'accès aux clés particulièrement rapide doit s'expliquer par l'utilisation de hash-code qui fait correspondre à une clé alphabétique une adresse de rangement numérique par un algorithme
et donc de la retrouver directement au lieu de balayer une table séquentiellement.


mondico.GIF

Add clé,élémentAjoute une clé et la valeur associée
Exists(clé)Teste l'existence d'une clé
Tbl=ItemsDonne dans un tableau les éléments
Tbl=Keys Donne dans un tableau les clés
Remove (clé)Supprime la clé
Removeall Supprime tous les éléments
CountDonne le nombre d'éléments
Item(clé) =valeurModifie la valeur de la clé
Item(clé)Donne la valeur associée à la clé
CompareMode=vbTextCompareIgnore la casse


Boisgontier
 

Pièces jointes

  • FonctionUnique.xlsm
    21.2 KB · Affichages: 36
Dernière édition:

dysorthographie

XLDnaute Accro
Bonjour,
Un dictionnarry est une variable objet elle fait partie de la famille des collections ?
Une collection est une sorte de variable tableau mais disposant d'un système de recherche par clé!

Par exemple en t(3,1) on trouve "toto" et en t(3,2) on trouve 10 lié à un comptage du nombre de "toto" un nous faudra rechercher la position de "toto" dans t(x,1) pour incrémenté de 1 t(x,2)+1!

Pour un dico("toto")=Dico("toto") +1 pas besoin de faire un dico.add avant add est implicite !

On peut utiliser soreddictionnarry pour en plus faire un trie des données par la clé.
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Bonsoir,

Sur MAC, l'objet Dictionary n'existe pas.
IL peut être simulé avec 2 collections:

VB:
Sub SimulDictionnareCollection()
  Dim CollecItem As New Collection, CollecCle As New Collection
  nom = "Dupond": age = 30
  CollecCle.Add Item:=nom, Key:=nom
  CollecItem.Add Item:=age, Key:=nom
  nom = "Martin": age = 35
  CollecCle.Add Item:=nom, Key:=nom
  CollecItem.Add Item:=age, Key:=nom
  For i = 1 To CollecCle.Count      ' Toutes les clés et items
    Cells(i + 1, 1) = CollecCle(i)
    Cells(i + 1, 2) = CollecItem(CollecCle(i))
  Next i
  '---
  clé = "Martin"
  MsgBox CollecItem(clé)
End Sub

Fonction NbUNiques()

VB:
Function NBUniques(plage As Range)
  Dim Collec1 As New Collection
  Tbl = plage.Value
  On Error Resume Next
  For Each c In Tbl
    If c <> "" Then Collec1.Add Item:=c, Key:=c
  Next c
  On Error GoTo 0
  NBUniques = Collec1.Count
End Function

Boisgontier
 

Pièces jointes

  • SimulDicoCollection.xlsm
    16.3 KB · Affichages: 10
Dernière édition:

jmfmarques

XLDnaute Accro
Bonjour
- l'utilisation d'une collection s'avère plus performante que celle d'un dictionnaire lorsque le nombre d'éléments à traiter n'est pas très important. Les collections deviennent lentes lorsqu'elles contiennent un grand nombre d'éléments.
- l'objet dictionnaire est, lui, lourd. Il implique par ailleurs sa disponibilité, ce qui n'est pas le cas sur MAC, mais n'est pas le cas non plus sur les machines Windows sur lesquelles VBS a été délibérément inhibé pour des raisons de sécurité.
L'utilisation toute bête d'une feuille "tremplin" de calcul temporaire ad hoc s'avère souvent la solution à la fois la plus économique en ressources et la plus performante.
C'est par exemple le cas ici, puisque (relisons) :
..... qui me permet de compter sans doublon les enregistrements d'une plage de cellules. ....
......A présent, je souhaiterais utiliser les différentes valeurs trouvées dans cette plage de cellules...
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Bonjour.
Il est aussi possible que vous n'ayez besoin ni de Collection ni de Dictionary. Ce pourrait être le cas si c'est une ComboBox dans un UserForm qui devra recevoir cette liste, classée et sans doublon, et que vous voudriez retrouver rapidement les lignes d'une base de donnée à consulter voire mettre à jour dans lesquelles un élément de sa liste est spécifié. J'ai des outils pour ça. Îl y en a même un qui retrouve rapidement les lignes ciblées par plusieurs choix dans des ComboBox correspondant à des colonnes différentes, sans avoir besoin pour cela de reconsulter la base de donnée …
 

Dranreb

XLDnaute Barbatruc
Bonjour @jmfmarques
Heu… Ce n'est pas à cette possibilité là que je pensais, mais à cette ressource qui propose une fonction SujetCBx qui renvoie ce qu'on pourrait appeler un objet fonctionnel. J'appelle ça un Sujet. Ce n'est pas un objet VBA. C'est un simple Array à deux éléments. Classé et sans doublon, l'élément 0 est conçu pour être directement affecté à la propriété List d'une ComboBox. Chaque poste de l'élément 1 est la liste des numéros de lignes de la base contenant la clé du poste correspondant de l'élément 0. Elle peut être directement obtenue d'après la propriété ListIndex de la ComboBox sans avoir besoin de reconsulter la base. Enfin un Objet ComboBoxLiées sait combiner tout ça pour plusieurs ComboBox.
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Bonjour,

>l'utilisation d'une collection s'avère plus performante que celle d'un dictionnaire lorsque le nombre d'éléments à traiter n'est pas très important.
>l'objet dictionnaire est, lui, lourd.


Quelles contre-vérité!

Boisgontier
 

jmfmarques

XLDnaute Accro
Tu as par exemple de comparaisons et entre autres (on en trouve partout sur la toile) :
With regards to the performance of collections versus dictionaries, I am finding that writing to dictionaries performs similarly to writing to collections, reading from a dictionary takes about twice as long as reading from a collection. Creating a dictionary in the first place is way slower than creating a collection.


These are results I got for doing 100,000 iterations of reading from, writing to, and creating dictionaries/collections:

Creating Multiple Dictionaries: 731ms
Writing To Dictionary: 494ms
Reading From Dictionary: 65ms

Creating Multiple Collections: 29ms
Writing To Collection: 459ms
Reading From Collection: 26ms

Note adding a reference to the Microsoft Scripting Runtine improves the speed of creating multiple dictionaries (to 495ms here).

Ce que je tempère quand-même (me relire) : avantage énorme aux collections si le nombre d'éléments n'est pas pléthorique.

si tu es intéressé (tu devrais l'être, puisque tu as l'assurance que tu montres) : tu trouveras le code du test correspondant que cette page ;) :
Bonne lecture et bon test.
 

BOISGONTIER

XLDnaute Barbatruc
Repose en paix
Il n'y a pas besoin de littérature Américaine.

Pour obtenir 50.000 nombres aléatoires sans doublons, on obtient 3,7 secondes et 0,07 sec ce qui fait un rapport de 50 en faveur du Dico.

Code:
Sub DicoSansDoublons()
   Set d = CreateObject("scripting.dictionary")
   Dim t, i As Long, n As Long, temp As Long
   t = Timer()
   n = 50000
   For i = 1 To n
     temp = Int(Rnd * n)
     d(temp) = ""
   Next i
   Tbl = d.keys
   [B2].Resize(d.Count) = Application.Transpose(Tbl)
   MsgBox Timer() - t ' 10 sec
End Sub

VB:
Sub CollectionSansDoublons()
   Dim t, i As Long, n As Long, temp As Long
   t = Timer()
   Dim Maliste As New Collection
   On Error Resume Next
   n = 50000
   For i = 1 To n
     temp = Int(Rnd * n)
     Maliste.Add Item:=temp, Key:=CStr(temp)
   Next i
   On Error GoTo 0
   Dim a()
   ReDim a(1 To n)
   For i = 1 To Maliste.Count
     a(i) = Maliste(i)
   Next i
   [a2].Resize(Maliste.Count) = Application.Transpose(a)
   MsgBox Timer() - t ' 10 sec
End Sub

Pour 100.000, on obtient 20 sec et 0,24 sec.

Boisgontier
 

Pièces jointes

  • ComparaisonCollectionDico.xlsm
    566.7 KB · Affichages: 28
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
312 213
Messages
2 086 302
Membres
103 174
dernier inscrit
OBUTT