voorbeeldbestand
Dictionaries


1 Wat is een dictionary

2 Waarvoor een dictionary

3 Dictionary achtergrond

4 Dictionary aanroepen

5 Dictionary vullen
5.1 methode .Add
5.2 methode .Item( )=
5.3 methode =.Item()
5.4 met objectvariabele

6 Toevoegen of vervangen ?
6.1 nieuwe sleutel
6.2 bestaande sleutel
6.2.1 methode .Add
6.2.2 methode .Item()=
6.2.3 methode =.Item()
6.2.4 met objectvariabele

7 Sleutels
7.1 tekstreeks
7.2 getal
7.3 datum
7.4 object
7.5 ActiveX-controls
7.6 Diverse sleutels

8 Unieke sleutel

9 Genereer unieke sleutels

10 Unieke elementen

11 Items
11.1 leeg item
11.2 lege tekstreeks
11.3 gewone tekstreeks
11.4 niet-afdrukbaar teken
11.5 getal
11.6 datum
11.7 1-dimensionele matrix
11.8 meer-dimensionele matrix
11.9 object
11.10 userformcontrols
11.11 ActiveX-controls
11.12 alle werkbladen
11.13 User Defined Type (UDT)

12 Dictionary: omvang

13 zoek sleutel / item

14 opvragen element
14.1 unieke sleutel
14.2 indexnummer
14.3 indexnummer van sleutel
14.4 Sleutels: lus
14.5 Filter sleutels

15 Sleutelverzameling
15.1 Opslaan
15.2 in variabele
15.3 in tekstreeks
15.4 berekeningen op sleutels
15.5 Filter sleutels

16 Itemverzameling
16.1 opslaan
16.2 in variabele
16.3 in tekstreeks
16.4 berekeningen op items
16.5 filter items

17 Wijzig sleutel

18 Kopieer item

19 Verwijder item

20 Wijzig item-inhoud
20.1 Vervang inhoud
20.2 Voeg toe
20.3 bewerk / bereken
20.3.1 getal
20.3.2 datum
20.3.3 boolean
20.4 wijzig een array-item
20.4.1 1-dimensionele array
20.4.2 2-dimensionele array

21 Dictionary legen

22 Early binding en late binding
22.1 Late binding
22.1.1 impliciet object
22.1.2 object variable
22.2 early binding
22.2.1 impliciet object
22.2.2. objectvariabele
22.2.3.1 private objectvariable
22.2.3.2 public objectvariable

23 Voorbeelden
23.1 Ontdubbelen
23.2 Filter hoogste waarde
23.3 Filter laagste waarde
23.4 records aanvullen
23.5 werkbladen-integratie
23.6 csv gegevens-integratie
23.7 unieke elementenlijst
23.8 vulcontrole ActiveX controls
23.9 werkbladcontrole
23.10 tekens naar 2-dimensionele matrix

1 Wat is een dictionary ?

Een dictionary in VBA is een verzamelobject: je kunt er allerlei verschillende zaken in opbergen: getallen, teksten, datums, arrays, ranges, variabelen en objecten.
Ieder opgeslagen item in een dictionary krijgt een unieke sleutel.
Daarmee kun je het item rechtstreeks benaderen (lezen/schrijven/bewerken).

VBA heeft verschillende mogelijkheden om gegevens op te slaan:
- een dictionary
- een collection
- een array (matrix) variabele
- een ActiveX ComboBox
- een ActiveX ListBox
- een Userform control ComboBox
- een Userform control ListBox
- een sortedlist
- een arraylist

De keuze voor een van deze methoden is afhankelijk van het te bereiken doel.
In deze tutorial wordt geen poging gedaan al deze methoden met elkaar te vergelijken.
We beperken ons tot een besprekeing van de mogelijkheden van de Dictionary.
Hoe beter we daarvan op de hoogte zijn, hoe gemakkeljker we kunnen besluiten deze toe te passen.

Een belangrijk kenmerk van de Dictionary is het gebruik van een unieke sleutel.
Een item hoeft dus niet gezocht te worden met een lus of met de Excelfunktie application.match.
In dat opzicht heeft een dictionary een voordeel ten opzichte van bijv. een array/matrix-variabele.

De manier waarop de dictionary items opslaat is vergelijkbaar met de methode Collection
De Dictionary heeft echter een aantal eigenschappen als .keys, .items en .removeall, waardoor het werken met een dictionary handiger kan zijn dan het gebruik van een collection.
De keus voor een Dictionary ten opzichte van bijv. een matrix-variabele of Collection is dus afhankelijk van wat je met opgeborgen items wil doen.

2 Waarvoor kun je een dictionary gebruiken ?

Je kunt de Dictionary gebruiken om gegevens uit allerlei bronnen bij elkaar te zetten en snel te bewerken omdat ze via de dictionary in het werkgeheugen geladen zijn en snel toegankelijk zijn.
In plaats van gegevens te bewerken in een Excel-werkblad, een Word Document, een Powerpointpresentatie, doe je dat in het werkgeheugen.
Daarvoor hoeft bijv. geen scherm ververst te worden, berekeningen uitgevoerd te worden, waardoor de dictionary snel is.

Globaal gezegd kun je een dictionary gebruiken om gegevens die een bepaald uniek gemeenschappelijk kenmerk hebben (de sleutel) bij elkaar te zetten.
Gegevens die op diverse plaatsen zijn geregistreerd kun je zo eenvoudig integreren.

Omdat een Dictionary alleen unieke sleutels kan bevatten kun je de sleuteleigenschap ook benutten om een reeks van unieke tekstreeksen, getallen, datums maken.
De Dictionary is hiervoor niet ontworpen, maar het is een handige neveneigenschap.
De unieke sleutels zijn niet gesorteerd; ze krijgen de volgorde waarin ze aan de Dictionary zijn toegevoegd.
Wil je een gesorteerde lijst van unieke sleutels hebben dan zul je de aan te bieden gegevens eerst moeten sorteren, of een andere VBA bibliotheek moeten gebruiken (bijv. system.arraylist of system.sortedlist)
Voorbeelden waarin een unieke lijst praktisch is: een validatielijst in Excel, de inhoud van een ActiveX-control (combobox of listbox) of een Userformcontrol (combobox of listbox).

3 Waar komt de Dictionary vandaan ?

De Dictionary maakt geen deel uit van de standaard VBA-bibliotheek.
De dictionary is onderdeel van de bibliotheek Microsoft Scripting Runtime
Die bevindt zich in het bestand ..\Windows\system32\scrrun.DLL of in een vergelijkbare directory
Je kunt via de VBEditor een aktieve verbinding leggen naar dit bestand door Microsoft Scripting Runtime bij de Referenties aan te vinken (Extra/referenties... of Tools/References..)
Als je een bestand waarin je gebruik maatk van een dictionary verspreidt, wordt meteen ook die verbinding naar deze bibliotheek meeverspreid.

4 Hoe roep je een Dictionary aan ?

Er zijn verschillende methoden om een Dictionary aan te roepen.
Omdat ik het belangrijker vind eerst te bespreken wat je met een dictionary kunt doen behandel ik deze pas in het laatste deel van deze tutorial.
Tot dat laatste deel gebruik ik voor de eenvoud slechts 1 methode.
Dat betekent niet dat dat de beste methode zou zijn; het is wel de eenvoudigste en minst storingsgevoelige.

Om een Dictionary te maken heb je aan deze code voldoende
With CreateObject("scripting.dictionary")

End With
Deze code zegt: maak een nieuw object aan op basis van de scripting.dictionary bibliotheek.
Alle opdrachten / eigenschappen die beginnen met een . tussen With ... End With verwijzen naar de aangemaakte Dictionary

zoals bijvoorbeeld:
With CreateObject("scripting.dictionary")
.Add "sleutel", "inhoud"
End With
De methode .Add voegt een item toe aan de dictionary met de sleutel "sleutel"; het item bevat de tekstreeks "inhoud"

en zoals:
With CreateObject("scripting.dictionary")
MsgBox .Count
End With
De eigenschap .Count van de Dictionary (het aantal items dat de Dictionary bevat) wordt gelezen en getoond in een berichtvenster.

V Hoe vul je een Dictionary

Een Dictionary kun je alleen één-voor-één vullen.
Voor ieder item heb je 2 dingen nodig: de inhoud van het item en een unieke sleutel

De inhoud van een item kan van alles zijn: getallen, teksten, datums, arrays, ranges, variabelen, collections, dictionaries,een lege tekenreeks, niets en objecten

De sleutel kan een getal, tekstreeks, datum of object zijn, of een variabele met een getal, tekstreeks, datum of object
Een sleutel kan geen 1- of meerdimensionele array zijn.
Voor de duidelijkheid zal ik in deze tutorial alleen tekstreeksen gebruiken als sleutel; daardoor blijft duidelijk dat het om sleutels gaat en niet om indexnummers.

Er zijn 4 methoden om een item aan een dictionary toe te voegen

5.1 methode .Add

Voeg een item toe aan de Dictionary met de inhoud "inhoud" en de sleutel "sleutel"
With CreateObject("scripting.dictionary")
.Add "sleutel", "inhoud"
End With
Een object voeg je op dezelfde manier toe:
Dit item in de Dictionary heeft dan alle kenmerken van het object:
With CreateObject("scripting.dictionary")
.Add "gebied", sheet1.range("A1:K10")
Msgbox .item("gebied").rows.count
End With

5.2 methode .Item( )=

Voeg een item toe aan de Dictionary met de inhoud "inhoud" en de sleutel "sleutel"
With CreateObject("scripting.dictionary")
.Item("sleutel") = "inhoud"
End With
Een object kun je alleen maar toevoegen met de instructie 'Set':
Dit item in de Dictionary heeft dan alle kenmerken van het object:
With CreateObject("scripting.dictionary")
Set .Item("gebied") = sheet1.range("A1:K10")
Msgbox .item("gebied").rows.count
End With

5.3 methode =.Item()

With CreateObject("scripting.dictionary")
x0 = .Item("sleutel")
End With
Deze code leest de inhoud van Item("sleutel") in variabele x0
Als het item met deze sleutel niet bestaaat voegt de code het item toe met de opgegeven sleutel
Aan het item wordt dan geen inhoud toegekend.

5.4 methode met objectvariabele

Als je van de dictionary een objectvariabele maakt
Set dict_snb = CreateObject("scripting.dictionary")
dict_snb("sleutel") = Date
Voeg een item toe aan de Dictionary met de inhoud Date en met de sleutel "sleutel"

Dit kun je ook anders schrijven; het resultaat is identiek
Set dict_snb = CreateObject("scripting.dictionary")
dict_snb.Item("sleutel") = Date

6 Toevoegen of vervangen ?

6.1 de sleutel bestaat niet in de Dictionary

Als een sleutel niet bestaat wordt een nieuwe sleutel aangemaakt en het item toegevoegd.
Alle methoden: .Add, .Item()=, =Item() en objectvariabele()= werken analoog zoals hierboven beschreven.

6.2 de sleutel bestaat al in de Dictionary

6.2.1 methode .Add

Als een sleutel al bestaat krijg je met de methode .Add een foutmelding dat de sleutel al bestaat:
Dit is vergelijkbaar met het gebruik van een Collection.
With CreateObject("scripting.dictionary")
.Add "sleutel", Date
.Add "sleutel", "nieuw"
End With

6.2.2 methode .Item()=

Als een sleutel al bestaat wordt met de methode .Item de inhoud van het bestaande item vervangen door de laatste waarde.
In tegenstelling tot bij de methode .Add en een Collection krijg je nu geen foutmelding dat de sleutel al bestaat.
With CreateObject("scripting.dictionary")
.Item("sleutel") = Date
MsgBox .Item("sleutel")
.Item("sleutel") = "nieuw"
MsgBox .Item("sleutel")
End With

6.2.3 methode =.Item()

De inhoud van het item wordt in een variabele gelezen. Het maakt niet uit of het item leeg is of niet.
Als de sleutel al bestaat verandert er niets aan/in de Dictionary.
With CreateObject("scripting.dictionary")
x0 = .Item("sleutel")
End With

6.2.4 methode met objectvariabele

Als een sleutel al bestaat wordt met deze methode de inhoud van het bestaande item vervangen door de laatste waarde.
In tegenstelling tot bij de methode .Add en een Collection krijg je geen foutmelding dat de sleutel al bestaat.
Set dict_snb = CreateObject("scripting.dictionary")
dict_snb("sleutel") = Date
MsgBox dict_snb("sleutel")
dict_snb("sleutel") = "nieuw"
MsgBox dict_snb("sleutel")
Anders geschreven met hetzelfde resultaat:
Set dict_snb = CreateObject("scripting.dictionary")
dict_snb.Item("sleutel") = Date
MsgBox dict_snb.Item("sleutel")
dict_snb.Item("sleutel") = "nieuw"
MsgBox dict_snb.Item("sleutel")

7 Sleutels

De toevoeging van nieuwe sleutels vindt op volgorde plaats. Er wordt noch op sleutel noch op item enige andere volgorde aangebracht.
Een sleutel kan een tekstreeks, een getal, een datum of een object zijn.
Een sleutel kan ook een variabele zijn die een tekstreeks, een getal, een datum, of een object bevat.
Een sleutel kan geen array (1- of meerdimensioneel) zijn.
Een Dictionary kan verschillende soorten sleutels (tekstreeks, getal, datum, object) bevatten.

Illustratie van verschillende soorten sleutels

7.1 tekstreeks sleutel

With CreateObject("scripting.dictionary")
.Items("aa1") = "voorbeeld 1 "
.Add "aa2", "voorbeeld 2"
x = .Item("aa3")
dict_snb("aa4") = "voorbeeld 3"
end with

7.2 getal sleutel

With CreateObject("scripting.dictionary")
.Items(2) = "voorbeeld 4"
.Items(1234589) = "voorbeeld 5"
.Add 23, "voorbeeld 6"
x = .Item(45)
dict_snb(56788) = "voorbeeld 7"
end with

7.3 datum sleutel

With CreateObject("scripting.dictionary")
.Items(Date) = "voorbeeld 8"
.Items(CDate("12-03-2013")) = "voorbeeld 9"
.Add DateAdd("m", 2, 1), " voorbeeld 10"
x = .Item(DateSerial(2013, 5, 5))
dict_snb(56788) = " voorbeeld 11"
end with

7.4 object sleutel

With CreateObject("scripting.dictionary")
.Items(TextBox1) = "voorbeeld 12"
.Items(TextBox2) = "voorbeeld 13"
.Add ListBox1, "voorbeeld 14"
x = .Item(Sheet1)
dict_snb(ComboBox1) = "voorbeeld 15"
end with

7.5 ActiveX-controls in een werkblad

With CreateObject("scripting.dictionary")
For Each it In Sheets("sheet1").OLEObjects
.Item(it) = it.Name
Next
end with

7.6 Verschillende soorten sleutels in 1 Dictionary

With CreateObject("scripting.dictionary")
For Each it In Array("bb1", 12, 45673, Date + 10, sheet4)
.Item(it) = "Item 1" & .Count
Next
end with

8 Wanneer is een sleutel uniek ?

Er zijn twee mogelijkheden:
- onderscheid tussen hoofd- en kleine letters; VanDaaG is een andere sleutel dan Vandaag
- geen onderscheid tussen hoofd- en kleine letters; VanDaaG is dezelfde sleutel als vandaag

De manier waarop sleutels met elkaar worden vergeleken stel je in met de eigenschap .comparemode
- geen specificatie van de comparemode: onderscheid tussen hoofd- en kleine letters
- .comparemode = BinaryCompare (0) : onderscheid tussen hoofd- en kleine letters
- .comparemode = TextCompare (1) : geen onderscheid tussen hoofd- en kleine letters
'8 unieke sleutels, want onderscheid tussen onderkast en bovenkast
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
y = .Item(it)
Next

MsgBox .Count
MsgBox Join(.Keys, vbLf)
End With
'8 unieke sleutels, want onderscheid tussen onderkast en bovenkast
With CreateObject("scripting.dictionary")
.CompareMode = 0
For Each it In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
y = .Item(it)
Next

MsgBox .Count
MsgBox Join(.Keys, vbLf)
End With
'2 unieke sleutels, want onderscheid tussen onderkast en bovenkast
With CreateObject("scripting.dictionary")
.CompareMode = 1
For Each it In Array("aa1", "AA1", "Aa1", "aA1", "bb1", "BB1", "Bb1", "bB1")
y = .Item(it)
Next

MsgBox .Count
MsgBox Join(.Keys, vbLf)

End With

9 Genereer automatisch unieke sleutels

Soms moeten alle items in een dictionary opgenomen worden.
Of gegevends aan eenzelfde sleutel moeten worden toegekend maakt dan niet uit.
Dan is het van belang voor ieder item een unieke sleutel te genereren, om zo ieder item aan de dictionary toe te voegen.
Dat kun je bijv. doen door gebruik te maken van de eigenschap .count van de dictionary
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(.Count) = it & "_inhoud"
Next
End With
Voorbeelden wanneer alle items in de Dictionary terecht moeten komen:
- om een tekstreeks om te zetten naar een 2-dimensionele matrix: Voorbeeld II
- om een aantal ActiveX controls te groeperen: Voorbeeld III

10 Een lijst van unieke elementen

Door items toe te voegen aan een dictionary creëer je een lijst van unieke sleutels.
Daarmee kun je dus een lijst met unieke elementen maken; een sleutel is nl. per definitie uniek.
Om die lijst te maken is het niet nodig gegevens aan het item toe te kennen.
De methode om dit te doen is het uitlezen van een item.
Als het item niet bestaat, wordt een sleutel toegevoegd; als de sleutel bestaat gebeurt er niets.
De methode geeft geen foutmeldingen die eventueel afgevangen zouden moeten worden
' vanwege de dubbele sleutels 22 en 44 bevat de dictionary 5 unieke sleutels
With CreateObject("scripting.dictionary")
For Each it In Array(22, 33, 44, 22, 3, 22, 55, 44)
y = .Item(it)
Next

MsgBox .Count
MsgBox Join(.Keys, vbLf)
End With

11 Items

De toevoeging van nieuwe items vindt op volgorde plaats. Er wordt noch op sleutel noch op item enige andere volgorde aangebracht.
De inhoud van een item kan van alles zijn: getallen, teksten, datums, arrays, ranges, variabelen, collections, dictionaries, een lege tekenreeks, niets en objecten
Hieronder een aantal voorbeelden van items met verschillende soorten inhoud.
Voor de sleutel gebruiken we alleen een tekenreeks.

11.1 een leeg item

With CreateObject("scripting.dictionary")
x0 = .Item("aa1")
End With

11.2 een lege tekstreeks

With CreateObject("scripting.dictionary")
.Item("aa2") = vbNullString
.Item("aa3") = ""
.Add "aa4", ""
dict_snb("aa5") = vbNullString
End With

11.3 een gewone tekstreeks

With CreateObject("scripting.dictionary")
.Item("aa6") = "abcde"
.Add "aa7", "abcde"
dict_snb("aa8") = "abcde"
End With

11.4 een niet-afdrukbaar teken

With CreateObject("scripting.dictionary")
.Item("aa9") = vbTab
Add "aa10", vbLf
dict_snb("aa11") = vbCrLf
End With

11.5 een getal

' typename: Integer
' typename: Long
With CreateObject("scripting.dictionary")
.Item("aa12") = 12345
.Add "aa13" = 1234589
dict_snb("aa14") = RGB(23, 45, 678)
End With

11.6 een datum

(typename: Date)
With CreateObject("scripting.dictionary")
.Item("aa15") = Date
.Add "aa16", CDate("23-04-2012")
dict_snb("aa17") = DateSerial(2013, 10, 12)
End With

11.7 een 1-dimensionele matrix (array)

(typename: Variant())
With CreateObject("scripting.dictionary")
.Item("aa18") = Array("aa1", "aa2", "aa3")
Add "aa19", Split("bb1_cc1_dd1", "_")
dict_snb("aa20") = Array("aa1", "aa2", "aa3")
End With

11.8 een meer-dimensionele matrix

(typename: Variant())
With CreateObject("scripting.dictionary")
ReDim sn(6, 10)
.Item("aa21") = sn
.Add "aa22", Range("A1:K10")
dict_snb("aa23") = Range("A1:K10").Formula
End With

11.9 een object

Bij de methode .Add wordt een object rechtstreeks in de Dictionary gezet. Bij de andere methodes (.Items = en objectvaraibeel=) moeten we de instructie Set gebruiken, anders wordt de defaulteigenschap van het object (bijv. de value ) in de Dictionary gezet.
' typename: Range
With CreateObject("scripting.dictionary")
Set .Items("aa24") = Range("A1:K10")
Set dict_snb("aa25") = Range("A1:K10")
.Add "aa26", Range("A1:K10")
End With

11.10 de controls in een userform

With CreateObject("scripting.dictionary")
For Each it In Controls
Set .Item(it.Name) = it
.Add it.name& "_", it
Next
End With

11.11 de ActiveX-controls in een werkblad

With CreateObject("scripting.dictionary")
For Each it In Sheets("sheet1").OLEObjects
Set .Item(it.Name) = it
.Add it.name & "_", it
Next
End With

11.12 alle werkbladen van een werkboek

With CreateObject("scripting.dictionary")
For Each sh In Sheets
Set .Item(sh.Name) = sh
.Add sh.Name & "_", sh
Set dict_snb(sh.Name & "_#") = sh
Next
End With

11.13 een User Defined Type (UDT)k

Een User Defined Type (UDT) kun je in een array zetten.
bijvoorbeeld
Public Type translation
dutch As String
german As String
french As String
italian As String
End Type

Sub filling_type_array()
ReDim sn(2) As translation
For j = 0 To 2
sn(j).dutch = Choose(j + 1, "tafel", "wijn", "water")
sn(j).german = Choose(j + 1, "Tisch", "Wein", "Wasser")
sn(j).french = Choose(j + 1, "table", "vin", "eau")
sn(j).italian = Choose(j + 1, "tavola", "vino", "aqua")
Next

MsgBox sn(2).german & " = " & sn(2).italian
end sub
Dan kun je per array item de gegevens van het type ophalen met:
For j=0 to ubound(sn)
MsgBox sn(j).german & " = " & sn(j).italian
next
Merkwaardigerwijs kun je voor een UDT niet de methode 'For Each ... Next' gebruiken
Een UDT kun je niet in een dictionary (noch een collection) zetten.
De opdracht
Dim woord As translation

With CreateObject("scripting.dictionary")
.Add "overzicht", woord
End With
Levert een foutmelding op.

Met een andere methode kun je wel een soortgelijk effekt bereiken:
- maak een klassemodule (bijv. met de naam 'trans')
- declareer daarin de eigenschappen van de klasse:
Public german As String, french As String, italian As String
- wijs vervolgens aan nieuwe instanties van die klasse eigenschappen toe en zet die nieuwe instanties in een dictionary.
Ter illustratie 3 methoden om dat te doen:
NB. de Nederlandse woorden worden als sleutel (key) in de Dictionary gebruikt.
Sub type_class_in_dictionary()
With CreateObject("scripting.dictionary")
Set sn = New trans
sn.german = "Tisch"
sn.french = "table"
sn.italian = "tavola"
.Add "tafel", sn

Set .Item("wijn") = New trans
.Item("wijn").german = "Wein"
.Item("wijn").french = "vin"
.Item("wijn").italian = "vino"

.Add "water", New trans
.Item("water").german = "Wasser"
.Item("water").french = "eau"
.Item("water").italian = "aqua"

MsgBox .Item("tafel").french
MsgBox .Item("wijn").italian
End With
End Sub

12 Het aantal elementen in een Dictionary

De methode Dictionary houdt zelf bij hoeveel elementen een Dictionary bevat.
De eigenschap .Count geeft het aantal items van een Dictionary weer.
Omdat ieder item een eigen unieke sleutel heeft geeft de eigenschap .Count ook meteen het aantal unieke sleutels weer in de Dictionary.

De funktie .Items bevat alle items van de Dictionary, weergegeven in een 1-dimensionele array.
De eigenschap Ubound() van een array geeft het aantal elementen van de array weer.
Omdat een 1-dimensionele array standaard de ondergrens 0 heeft, geeft ook Ubound(.items)+1 het aantal elementen in een Dictionary weer.

De funktie .Keys bevat alle sleutels van de Dictionary, weergegeven in een 1-dimensionele array.
De eigenschap Ubound() van een array geeft het aantal elementen van de array weer.
Omdat een 1-dimensionele array standaard de ondergrens 0 heeft, geeft ook Ubound(.keys)+1 het aantal elementen in een Dictionary weer.

Equivalente methodes om de omvang van een Dictionary te bepalen zijn dus
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa2")
y = .Item(it)
Next

MsgBox .Count
MsgBox UBound(.Keys) + 1
MsgBox UBound(.Items) + 1
End With

13 Controle of een sleutel / item in de Dictionary voorkomt

Als je een item aan de Dictionary wil toevoegen met de methode .Add krijg je een foutmelding als de sleutel voor dat item al bestaat.
Je kunt die foutmelding voorkomen door eerst te controleren of de sleutel al in de Dictionary aanwezig is
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
If Not .Exists(it) Then .Add it, it & "_inhoud"
Next
End With
Als je een item aan de Dictionary wil toevoegen met de methode .Item = krijg je geen foutmelding als de sleutel al bestaat, maar wordt het item vervangen.
Als dat niet de bedoeling is kun je controleren of de sleutel al in de Dictionary aanwezig is.
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
If Not .Exists(it) Then .Item(it) = it & "_inhoud"
Next
End With
Als je een item in een Dictionary wil wijzigen kan het handig zijn de aanwezigheid ervan te controleren alvorens de gegevens van het item uit te lezen.
Als de sleutel nl. nog niet bestaat wordt die automatisch aangemaakt als je de item-inhoud probeert uit te lezen met de code.
y = .Item("sleutel")
Als het niet de bedoeling is dat lege items aan de Dictionary worden toegevoegd is controle niet overbodig:
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next
If .Exists("aa2") Then .Item("aa2") = "nieuwe waarde"
End With

14 Hoe vraag je 1 element uit een Dictionary op ?

14.1 Met de unieke sleutel

De Dictionary is ervoor ontworpen om met de sleutel direkt een item te kunnen benaderen (lezen/schrijven)
Met .item("aa2") krijg je de inhoud van het item met de sleutel "aa2"
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next
MsgBox .Item("aa2")
End With

14.2 Met het indexnummer van het item

De funktie .Items is een 1-dimensionele array.
De volgorde waarin elementen aan de Dictionary worden toegevoegd bepaalt het indexnummer van de array .items.
Het eerste element krijgt indexnummer 1, het laatste indexnummer komt overeen met de eigenschap .count.
Je zou verwachten dat .items(2) het tweede element van de Dictionary zou opleveren.
Deze schrijfwijze werkt echter niet.
In plaats daarvan moet je schrijfwijze .items()(2) gebruiken.
' het eerste item
' het tweede item
' het laatste item
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

MsgBox .Items()(1)
MsgBox .Items()(2)
MsgBox .Items()(.count)

End With

14.3 Met het indexnummer van een sleutel

De funktie .Keys is een 1-dimensionele array.
De volgorde waarin elementen aan de Dictionary worden toegevoegd bepaalt het indexnummer van de array .keys.
Het eerste element krijgt indexnummer 1, het laatste indexnummer komt overeen met de eigenschap .count.
Je zou verwachten dat .keys(2) de tweede sleutel van de Dictionary zou opleveren.
Deze schrijfwijze werkt echter niet.
In plaats daarvan moet je schrijfwijze .keys()(2) gebruiken.
' de eerste sleutel
' de tweede sleutel
' de laatste sleutel
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

MsgBox .item(.keys()(1))
MsgBox .item(.keys()(2))
MsgBox .item(.keys()(.count))
End With

14.4 Loop alle sleutels in de Dictionary af en toets op een voorwaarde

Hiervoor maken we gebruik van de function .Keys waarin alle sleutels staan in de vorm van een 1-dimensionele matrix
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

For Each it In .Keys
If it = "aa4" Then MsgBox .Item(it)
Next
End With

14.5 Filter de sleutels in de Dictionary

Hiervoor maken we gebruik van de function .Keys waarin alle sleutels staan in de vorm van een 1-dimensionele matrix
With CreateObject("scripting.dictionary")
For Each it In Array("aa14", "bb345", "cc392", "rrr987")
.Item(it) = it & "_inhoud"

Next

MsgBox .Item(Join(Filter(.Keys, "cc"), ""))
End With

15 Hoe kun je de verzameling van sleutels gebruiken ?

15.1 Schrijf alle sleutels naar een werkblad

' in een rij
' in een kolom
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

Cells(1, 1).Resize(, .Count) = .Keys
Cells(1, 1).Resize(.Count) = Application.Transpose(.Keys)
End With

15.2 Zet alle sleutels in een variabele

De variabele wordt automatisch een array-variabele met ondergrens 0
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

sn = .Keys
End With

15.3 Zet alle sleutels in een tekstreeks

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", 22, 3, 22, DateSerial(2013, 12, 3), 44)
.Item(it) = it & "_inhoud"
Next

MsgBox Join(.Keys, vbLf)
End With

15.4 Voer berekeningen uit op de sleutels

Veel Excel werkbladfunkties kunnen worden toegepast op de array .keys als de keys uit getallen bestaan.
- het maximum van keys die uit getallen bestaan (Excel)
MsgBox Application.Max(.Keys)
- het minimum van keys die uit getallen bestaan (Excel)
MsgBox Application.Min(.Keys)
- de op 2 na hoogste key van keys die uit getallen bestaan (Excel)
MsgBox Application.Large(.Keys, 3)

15.5 Filter de sleutels op een bepaald kenmerk

Bijv. filter op het jaar 2012
Door het gebruik van de methode Filter worden alle sleutels in de functie .keys geconverteerd naar tekst.
De filterterm dient dan ook een tekstreeks te zijn.
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", DateSerial(2012, 12, 3), DateSerial(2012, 12, 4), DateSerial(2012, 12, 8), 22, DateSerial(2013, 12, 3), 44)
.Item(it) = it & "_inhoud"
Next

MsgBox Join(Filter(.Keys, "-2012"), vbLf)
End With
De methode Filter converteert alle sleutels in de functie .keys naar tekst.
Als je de gefilterde sleutels wil gebruiken om de overeenkomstige items op te roepen zul je ze naar de oorspronkelijke vorm, in dit geval datums moet terugconverteren
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", DateSerial(2012, 12, 3), DateSerial(2012, 12, 4), DateSerial(2012, 12, 8), 22, DateSerial(2013, 12, 3), 44)
.Item(it) = it & "inhoud"
Next

For Each it In Filter(.Keys, "-2012")
MsgBox .Item(CDate(it))
Next
End With

16 Hoe kun je de verzameling van items gebruiken ?

16.1 Schrijf alle items naar een werkblad

NB. Dit kan alleen als ieder item naar een cel geschreven kan worden (een tekstreeks een getal, een datum)
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

Cells(1, 1).Resize(, .Count) = .Items in een rij
Cells(1, 1).Resize(.Count) = Application.Transpose(.Items) in een kolom
End With

16.2 Zet alle items in een variabele

De variabele wordt automatisch een array-variabele met ondergrens 0
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

sn = .Items
End With

16.3 Zet alle items in een tekstreeks

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", 22, 3, 22, DateSerial(2013, 12, 3), 44)
.Item(it) = it & "_inhoud"
Next

MsgBox Join(.Items, vbLf)
End With

16.4 Voer berekeningen uit op de items

Veel Excel werkbladfunkties kunnen worden toegepast op de array .items als de items uit getallen bestaan.
- het maximum van keys die uit getallen bestaan (Excel)
MsgBox Application.Max(.Items)
- het minimum van keys die uit getallen bestaan (Excel)
MsgBox Application.Min(.Items)
- de op 2 na hoogste key van keys die uit getallen bestaan (Excel)
MsgBox Application.Large(.Items, 3)

16.5 Filter de items op een bepaald kenmerk

Bijv. filter op het jaar 2012
Door het gebruik van de methode Filter worden alle items in de functie .items geconverteerd naar tekst.
De filterterm dient dan ook een tekstreeks te zijn.
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", DateSerial(2012, 12, 3), DateSerial(2012, 12, 4), DateSerial(2012, 12, 8), 22, DateSerial(2013, 12, 3), 44)
.Item(it) = it & "_inhoud"
Next

MsgBox Join(Filter(.Items, "-2012"), vbLf)
End With

17 Wijzig de sleutel van een item

Je kunt dit ook beschrijven als het 'verplaatsen' van een item binnen een Dictionary.
With CreateObject("scripting.dictionary")
.Item("aa") = "Dit is het eerste item"
MsgBox .Item("aa")

.Key("aa") = "bb"
MsgBox .Item("bb")
End With

18 Kopieer een item binnen de Dictionary

Je kunt de inhoud van een bestaand item aan een andere/nieuwe sleutel koppelen.
With CreateObject("scripting.dictionary")
.Item("aa") = "Dit is het eerste item"
.Item("bb") = .Item("aa")

MsgBox .Item("bb")
End With

19 Verwijder een item uit de Dictionary

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next

.Remove "aa3"
End With

20 Wijzig de inhoud van een item in de Dictionary

20.1 Vervang de inhoud van een item in de Dictionary

Met de methode .Item wordt een bestaand item vervangen door een later toegevoegd item met dezelfde sleutel
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa5", "aa6")
.Item(it) = it & "_inhoud"
Next
For Each it In Array("aa1", "aa2", "aa5", "aa6")
.Item(it) = it & "_nieuwe inhoud"
Next

MsgBox Join(.Items, "|")
End With
Met deze methode kun je bijv. op basis van een sortering de items met de oudste/meest recente datum, of de hoogste of laagste waarde op een sorteerbare sleutel opnemen.
Doordat ieder item wordt overschreven, blijven de laatste ingelezen waarden per sleutel over.
Voorwaarde is een sorteerbare sleutel.
Voor een voorbeeld zie voorbeeld V.

20.2 Voeg gegevens toe aan items binnen de Dictionary

Deze methode werkt alleen als het item geen array is.
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = "aa"
Next
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = .Item(it) & "_bb"
Next

MsgBox Join(.Items, "|")
End With

20.3 Voer een bewerking / berekening uit

Als het item geen array is, maar een getal, datum of boolean bevat

20.3.1 een getal

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = 10
Next
For Each it In Array("aa1", "aa2", "aa1", "aa3", "aa4", "aa2")
.Item(it) = .Item(it) + 40
Next

MsgBox Join(.Items, "|")
End With

20.3.2 een datum

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa4")
.Item(it) = Date + .Count
Next
For Each it In Array("aa1", "aa2", "aa3", "aa4")
.Item(it) = DateAdd("m", 1, .Item(it))
Next

MsgBox Join(.Items, vbLf)
End With

20.3.3 een boolean

With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa2")
.Item(it) = False
Next
For Each it In Array("aa1", "aa2", "aa3", "aa4", "aa2")
.Item(it) = Format(.Item(it), "Yes/No")
Next

MsgBox Join(.Items, "|")
End With

20.4 Breng een wijziging aan in een item dat een array bevat

20.4.1 een 1-dimensionele array

Het is mogelijk een element in een array van een Dictionary Item te lezen
With CreateObject("scripting.dictionary")
.Item("aa") = Array("zz1", "zz2", "zz3", "zz4")
MsgBox .Item("aa")(3)
End With
Het lijkt niet mogelijk een element in een array van een Dictionary Item direkt te wijzigen
Hoewel deze code geen foutmelding geeft, wordt het 4e element van de array niet gewijzigd.
With CreateObject("scripting.dictionary")
.Item("aa") = Array("zz1", "zz2", "zz3", "zz4")
MsgBox .Item("aa")(3)

.Item("aa")(3) = "het vierde item is " & .Item("aa")(3)
MsgBox .Item("aa")(3)
End With
Met een omweg lukt het wel
- zet de array in een variabele
- wijzig een of meer element(en) van de array-variabele
- vervang de inhoud van het dictionary item door de array-variabele
With CreateObject("scripting.dictionary")
.Item("aa") = Array("zz1", "zz2", "zz3", "zz4")

sn = .Item("aa")
sn(3) = "het vierde item is " & sn(3)
.Item("aa") = sn

MsgBox .Item("aa")(3)
End With

20.4.2 een 2-dimensionele array

Het is mogelijk een element in een 2-dimensionele array van een Dictionary Item te lezen
With CreateObject("scripting.dictionary")
ReDim sn(3, 4)
For j = 0 To UBound(sn)
For jj = 0 To UBound(sn, 2)
sn(j, jj) = j + 5 * jj
Next
Next

.Item("aa") = sn
MsgBox .Item("aa")(2, 3)
End With
Het lijkt niet mogelijk een element in een array van een Dictionary Item direkt te wijzigen.
With CreateObject("scripting.dictionary")
ReDim sn(3, 4)
For j = 0 To UBound(sn)
For jj = 0 To UBound(sn, 2)
sn(j, jj) = j + 5 * jj
Next
Next
.Item("aa") = sn

MsgBox .Item("aa")(2, 3)

.Item("aa")(2, 3) = 10 * .Item("aa")(2, 3)
MsgBox .Item("aa")(2, 3)
End With
Met een omweg lukt het wel
- zet de array in een variabele
- wijzig een element van deze array-variabele
- vervang de inhoud van het dictionary item door deze array-variabele
With CreateObject("scripting.dictionary")
ReDim sn(3, 4)
For j = 0 To UBound(sn)
For jj = 0 To UBound(sn, 2)
sn(j, jj) = j + 5 * jj
Next
Next
.Item("aa") = sn

MsgBox .Item("aa")(2, 3)

sp = .Item("aa")
sp(2, 3) = 10 * sp(2, 3)
.Item("aa") = sp

MsgBox .Item("aa")(2, 3)
End With

21 Verwijder alle items uit de Dictionary

With CreateObject("scripting.dictionary")
For Each it In Array("2", "33", "aa3", "aa4", "aa2")
.Item(it) = it & "_inhoud"
Next
.RemoveAll
End With

22 Early binding en late binding

Zoals bij III beschreven maakt de Dictionary geen deel uit van de standaard VBA bibliotheek.
De dictionary zit in de Microsoft scripting runtime bibliotheek.
Dat betekent dat je die bibliotheek moet aanroepen om de code daarin te kunnen gebruiken.
Je legt daarmee een koppeling naar die bibliotheek.
Dat heet in automatiseringstermen 'binding'

Je hebt de keuze om
- eerst de koppeling naar de bibliotheek te leggen en daarna de code ervan te gebruiken: early binding
- of de koppeling pas te maken als je voor de eerste keer die code nodig hebt: late binding

22.1 Late binding

Tot nog toe hebben we gebruik gemaakt van de late binding methode.
Die bestaat eruit dat je met de instructie CreateObject een nieuw object (instantie) aanmaakt op basis van een bepaalde bibliotheek.
Welke tekst je moet gebruiken na CreateObject voor de verschilleden VBA bibliotheken is niet erg overzichtelijk. Bij een Dictionary is het in ieder geval:
Createobject("scripting.dictionary")
Deze code doet 2 dingen:
- legt een koppeling naar de bibliotheek Microsoft Scripting Runtime
- maakt een nieuw object (instantie) op basis van deze bibliotheek

Beide methoden (early en late binding) zijn uitwisselbaar. Doorslaggevend is je eigen voorkeur.
Om met het object te kunnen werken (de eigenschappen en methoden) moet je van die nieuwe instantie een object maken.

22.1.1 impliciet object

Dat kan impliciet met de methode With.... End With
With CreateObject("scripting.dictionary")
.Add "aa1", "vandaag"
End With

22.1.2 object variable

Of met een object variabele
Set d_snb_ = CreateObject("scripting.dictionary")
d_snb.Add "aa1", "vandaag"

22.2 early binding

De bibliotheek is de Microsoft Scripting Runtime bibliotheek
Je kunt de koppeling met de hand leggen via de VBEditor (Alt-F11):
- VBEditor/tools/references (extra/referenties/) : 'Microsoft Scripting runtime' aanvinken
Je kunt de koppeling ook met een macro leggen:
Sub M_link_ref_scripting()
ThisWorkbook.VBProject.References.AddFromFile "C:\windows\system32\scrrun.dll"
End Sub
Deze koppeling wordt in het Excelbestand bewaard.
Als je het werkboek distribueert legt het bestand automatisch de link naar deze biblotheek op iedere andere computer met Office.

Om met de bibliotheek te kunnen werken moeten we een nieuw object (instantie) maken, gebaseerd op deze bibliotheek.

22.2.1 early binding met impliciet object

je kunt een impliciet object aanmaken met With ... End With
With New Dictionary
.Add "aa1", "vandaag"
End With

22.2.2. early binding met objectvariabele

Om een object aan een variabele toe te kennen is de instructie 'Set' noodzakelijk
Set d_snb = New Dictionary
d_snb.Add "aa1", "vandaag"

22.2.3.1 early binding met gedeclareerde objectvariable: 'private'

Je kunt de objectvariabele ook al meteen aan een nieuwe instantie toewijzen in het declaratiedeel van een codemodule.
(bijv. het werkboek, een werkblad, een userform of een macromodule).
Private d_snb As New Dictionary
Daarna kun je overal in deze codemodule de objectvariabele gebruiken
d_snb.Add "aa1", "PPP"

22.2.3.2 early binding met gedeclareerde objectvariable: 'public'

Als je wil dat de objectvariabele in het hele project (werkboek) toegankelijk is, zet dan de declaratie in een macromodule
Public d_snb As New Dictionary
of
In het declaratiedeel:
Public d_snb As dictionary
In een macro:
Set d_snb = New Dictionary

23 Voorbeelden

23.1 Verwijder dubbele records

Kolom A bevat de sleutels voor de records.
Kolommen B:.. etc, bevatten de gegevens van de records.
Sub M_verwijder_dubbele_records()
sn = Sheets("Sheet1").Cells(1).CurrentRegion

With CreateObject("scripting.dictionary")
For j = 1 To UBound(sn)
.Item(sn(j, 1)) = Application.Index(sn, j, 0)
Next

Sheets("Sheet1").Cells(1, 4).Resize(.Count, UBound(sn, 2)) = Application.Index(.items, 0, 0)
End With
End Sub

23.2 Filter records op hoogste waarde

Kolom A bevat de sleutels van de records. Kolom A bevat diverse records met dezelfde sleutel.
Kolommen B: ..... bevatten de gegevens van de records.
Kolom B bevat de gegevens waarop gesorteerd moet worden.
Sub M_filter_records_hoogste_gegeven_in_kolomB()
Sheets("Sheet1").Cells(1).CurrentRegion.Sort Sheets("Sheet1").Cells(1, 2)
sn = Sheets("Sheet1").Cells(1).CurrentRegion

With CreateObject("scripting.dictionary")
For j = 1 To UBound(sn)
.Item(sn(j, 1)) = Application.Index(sn, j, 0)
Next

Sheets("Sheet1").Cells(1, 4).Resize(.Count, UBound(sn, 2)) = Application.Index(.items, 0, 0)
End With
End Sub

23.3 Filter records op laagste waarde

Kolom A bevat de sleutels van de records. Kolom A bevat diverse records met dezelfde sleutel.
Kolommen B: ..... bevatten de gegevens van de records.
Kolom B bevat de gegevens waarop gesorteerd moet worden.
Sub M_filter_records_laagste_gegeven_in_kolomB()
Sheets("Sheet1").Cells(1).CurrentRegion.Sort Sheets("Sheet1").Cells(1, 2),2
sn = Sheets("Sheet1").Cells(1).CurrentRegion

With CreateObject("scripting.dictionary")
For j = 1 To UBound(sn)
.Item(sn(j, 1)) = Application.Index(sn, j, 0)
Next

Sheets("Sheet1").Cells(1, 4).Resize(.Count, UBound(sn, 2)) = Application.Index(.items, 0, 0)
End With
End Sub

23.4 records aanvullen

Kolom A bevat de sleutels van de records.
Kolom B bevat gegevens van de records.
Kolom E bevat sleutels van dezelfde records als kolom A.
Kolom F bevat gegevens die aan de records van kolom A moeten worden toegevoegd.
Sub M_records_aanvullen()
sn = Sheets("Sheet1").Cells(1).CurrentRegion.Resize(, 3)
sp = Sheets("sheet1").Cells(1, 5).CurrentRegion

With CreateObject("scripting.dictionary")
For j = 1 To UBound(sn)
.Item(sn(j, 1)) = Application.Index(sn, j, 0)
Next

For j = 1 To UBound(sp)
st = .Item(sp(j, 1))
st(3) = sp(j, 2)
.Item(sn(j, 1)) = Application.Index(st, 0, 0)
Next

Sheets("Sheet1").Cells(1, 10).Resize(.Count, UBound(sn, 2)) = Application.Index(.items, 0, 0)
End With
End Sub

23.5 integratie van alle werkbladen in een totaalblad

Sub M_integratie()
With createobject("scripting.dictionary")
For each sh in Sheets
.item(sh.name)=sh.usedrange
Next
sheets.add.name="totaal"

for each it in .items
sheets("totaal").cells(rows.count,1).end(xlup).offset(1).resize(ubound(it),ubound(it,2))=it
next
end with
End Sub

23.6 Integratie van gegevens in csv bestanden in een bepaalde directory

In dit voorbeeld wordt gekeken naar directory G:\OF\; pas dit aan.
Sub M_integratie_csv()
sn = Split(CreateObject("wscript.shell").exec("cmd /c Dir ""G:\OF\*.csv"" /b").stdout.readall, vbCrLf)

With CreateObject("scripting.dictionary")
For j = 0 To UBound(sn)
.Item(sn(j)) = GetObject("G:\OF\" & sn(j)).Sheets(1).UsedRange.Value
GetObject("G:\OF\" & sn(j)).Close False
Next

Sheets.Add.Name = "totaal"

For Each it In .items
Sheets("totaal").Cells(Rows.Count, 1).End(xlUp).Offset(1).Resize(UBound(it), UBound(it, 2)) = it
Next
End With
End Sub

23.7 maak een lijst met unieke elementen

Door items toe te voegen aan een dictionary creëer je een lijst van unieke sleutels.
Daarmee kun je dus een lijst met unieke elementen maken; een sleutel is nl. per definitie uniek.
Om die lijst te maken is het niet nodig gegevens aan het item toe te kennen
De methode om dit te doen is het uitlezen van een item.
Als het item niet bestaat, wordt een sleutel toegevoegd; als de sleutel bestaat gebeurt er niets.
De methode geeft geen foutmeldingen die eventueel afgevangen zouden moeten worden
De lijst met unieke elementen kun je gebruiken als een validatiereeks, je kunt er een combobox of listbox mee vullen
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa2", "aa2", "aa4", "aa5")
y = .Item(it)
Next
Sheets("sheet1").Cells(1, 10).Validation.Add 3, , , Join(.Keys, ",")

Sheets("sheet1").OLEObjects("Combobox1").Object.List = .Keys
Sheets("sheet1").ListBox1.List = .Keys
End With
In een userform:
Private Sub Userform_initialize()
With CreateObject("scripting.dictionary")
For Each it In Array("aa1", "aa2", "aa3", "aa2", "aa2", "aa4", "aa5")
y = .Item(it)
Next

ComboBox1.List = .Keys
ListBox1.List = .Keys
Me("ComboBox2").List = .Keys
Me("ListBox2").List = .Keys
Controls("ComboBox3").List = .Keys
Controls("Listbox3").List = .Keys
End With
End Sub

23.8 controle of alle ActiveX elementen gevuld zijn

Toon de ActiveX opdrachtknop als alle ActiveX controls een waarde hebben (niet-leeg zijn).
Private dict As Dictionary

Sub M_vul()
Set dict = CreateObject("scripting.dictionary")
For Each it In Array("TextBox1", "TextBox2", "textbox3", "combobox4", "combobox5")
Set dict(it) = Sheets("sheet1").OLEObjects(it)
Next
End Sub

Private Sub Textbox1_change()
M_controle
End Sub

Private Sub M_controle()
y = True
For Each it In dict.Items
y = y * (it.Object.Value<>"")
Next
Sheets("sheet1").CommandButton1.Visible = y
End Sub

23.9 check of een werkblad bestaat

Zet in een macromodule:
Public dict_sheets As Dictionary

Sub M_sheet_exists()
Set dict_sheets = CreateObject("scripting.dictionary")
For Each it In Sheets
x0 = dict_sheets(it.name)
Next
End Sub
Nu kun je overal in je project gebruiken:
Sub M_vervolg()
' - - -
If Not dict_sheets.Exists("Sheet10") Then Sheets.Add.Name = "Sheet10"
' - - -
End Sub

23.10 maak van een tekenreeks een 2-dimensionele matrix

With CreateObject("scripting.dictionary")
For Each it In Split("aa1_aa2_aa3_aa4_aa5|bb1_bb2_bb3_bb4_bb5|cc1_cc2_cc3_cc4_cc5", "|")
.Item(.Count) = Application.Index(Split(it, "_"), 1, 0)
Next

Cells(10, 1).Resize(.Count, UBound(.Item(1))) = Application.Index(.Items, 0, 0)

End With