Search notes:

VBA: Microsoft Scripting Runtime - Dictionary

The Scripting Runtime has a dictionary object which allows to index variables by keys or numbers. In other programming languages, this feature is also referred to as hashes or associative arrays.
In order to use the dictionary object (or the scripting runtime for that mattter), the respective reference needs to be added:
thisWorkbook.vbProject.references.addFromGuid _
        GUID   :="{420B2830-E718-11CF-893D-00A0C9054228}" , _
        major  :=  1                                      , _
        minor  :=  0
It is also possible to create a dictionary object using createObject():
set dict = createObject("scripting.dictionary")

Methods and properties

add(keyName, val) Adds a new (named) key with the given value. If keyName already exists, an error is thrown.
exists(keyName) Check if a key with the name keyName already exists.
items Returns an array of variants that contains the values (without key names) of the dictionary.
keys Returns an array of variants that contains the key names of the dictionary.
remove(keyName) Remove the key whose name is keyName
removeAll Remove all key/value pairs thus emptying the dictionary.
compareMode This property sets or gets the way with which key value names are compared and can be set to vbUseCompareOption (use value of option compare), vbBinaryCompare, vbTextCompare, vbDatabaseCompare (MS Access only). A value greater than 2 is interpreted as the
count This property corresponds to the number of stored key value pairs
item(keyName) Sets or gets the value of the key whose name is keyName. When getting the value of an inexisting key, the key is created. When setting the value of an existing key, the value is overwritten.
key(keyname) = … Overwrites the value for an already existing key. If key does not exist, an error is thrown.

Adding and removing keys

An attempt to add an already existing key throws an error with number 457.
An attempt to remove an unexisting key throws an error with number 32811.
option explicit

sub main() ' {

  on error goto err_

    dim dict as new dictionary

    debug.print "adding k1"
    dict("k1") = "v1"

    debug.print "adding k2"
    dict.add "k2", "v2"

    debug.print "adding k1"
    dict.add "k1", "...."

    debug.print "removing k1"
    dict.remove "k1"

    debug.print "removing inexisting-key"
    dict.remove "inexisting-key"

    debug.print "removing k2"
    dict.remove "k2"

    exit sub

  err_:

    if err.number = 457 then
       debug.print "Error: key is already present in dictionary!"
       resume next
    end if

    if err.number = 32811 then
       debug.print "Error: trying to remove key that does not exist!"
       resume next
    end if

    debug.print "unhandled error " & err.number & ": " & err.description

end sub ' }
Github repository about-VBA, path: /object-libraries/microsoft-scripting-runtime/dictionary/add-remove.bas

removeAll

All keys of a given dictionary can be removed with removeAll:
option explicit

sub main() ' {

    dim dict as new dictionary

    dict("k1") = "v1"
    dict("k2") = "v2"
    dict("k3") = "v3"

    debug.print "elements in dict: " & dict.count

    dict.removeAll

    debug.print "elements in dict: " & dict.count
end sub ' }
Github repository about-VBA, path: /object-libraries/microsoft-scripting-runtime/dictionary/removeAll.bas

Determine if key is present

isEmpty(dict, key) allows to check whether a key is present in the dictionary:
option explicit

sub main() ' {

    dim D as new dictionary

    if isEmpty(D("K")) then
       debug.print "is empty"
    else
       debug.print "is not empty"
    end if

    D("K") = "val"

    if isEmpty(D("K")) then
       debug.print "is empty"
    else
       debug.print "is not empty"
    end if

end sub ' }
Github repository about-VBA, path: /object-libraries/microsoft-scripting-runtime/dictionary/isEmpty.bas

for each in

option explicit

sub main() ' {

    dim capital as new scripting.dictionary

    capital.add "France"     , "Paris"
    capital.add "Germany"    , "Berlin"
    capital.add "Switzerland", "Bern"
    capital.add "Italy"      , "Rome"

    dim country as variant

    for each country in capital
        debug.print country & ": " & capital(country)
    next country

end sub ' }
Github repository about-VBA, path: /object-libraries/microsoft-scripting-runtime/dictionary/for-each-in.bas
See also for each in on collections

uBound and lBound

lBound and uBound can be applied on a dictionary's items and keys:
option explicit

sub main() ' {

    dim dict as new dictionary

    dict("k1") = "v1"
    dict("k2") = "v2"
    dict("k3") = "v3"

    debug.print "keys  - lBound: " & lBound(dict.keys ) & ", uBound: " & uBound(dict.keys )
    debug.print "items - lBound: " & lBound(dict.items) & ", uBound: " & uBound(dict.items)

end sub ' }
Github repository about-VBA, path: /object-libraries/microsoft-scripting-runtime/dictionary/luBound.bas

See also

A dictionary can not only store objects, it can even be indexed by objects, see here.
VBA: Microsoft Scripting Runtime
VBA-Dictionary (github) is a drop-in replacement for Scripting.Dictionary that promises to behave exactly the same.

Index