TechBookReport logo

VBA Dictionary Object


By Pan Pantziarka


Introducing...the Dictionary

The associative array, often called a Map or Hash Map, is one of the most useful data structures available to the programmer. Unlike a normal indexed array, the contents of an associative array are accessed via a 'key' rather than a numerical index. So, instead of having to keep track of where things are in an array, the programmer can assign a unique key to a value and then add the key, value pair to the array. Retrieving the value is just then a case of using the key. For example key value pairs could be names and ages: John, 34; Jane, 46; Ted, 102 etc.

In languages such as Java and C# there are entire families of associative arrays available via collections frameworks. In other languages such as Python, Ruby or Groovy the map is a basic part of the language. What about VBA? Well, it just so happens that there is a form of associative array called the Dictionary that VBA programmers can use. This tutorial will be using Excel as the application, but the same principles are available in Word, PowerPoint and anything else that uses VBA.





The first thing to do is to create a reference to the Microsoft Scripting Runtime, which is the DLL that contains the Dictionary (as well as the FileSystemObject). To do that we open Excel, hit F11 to get to the Visual Basic environment and then select References from the Tools menu. Navigate down through the list of available references and select Microsoft Scripting Runtime (\Windows\system32\scrrun.dll). Once that's done the Dictionary is available for you to use in your code.

With that in place we can write some code to put the Dictionary object through its paces:

Sub DictExample1()

Dim dict As Dictionary
Dim v As Variant

    'Create the dictionary          
    Set dict = New Dictionary

   'Add some (key, value) pairs
    dict.Add "John", 34
    dict.Add "Jane", 42
    dict.Add "Ted", 402

    'How many items do we have?
    Debug.Print "Number of items stored: " & dict.Count

    'We can retrieve an item based on the key
    Debug.Print "Ted is " & dict.Item("Ted") & " years old"


   'We can test whether an item exists
    Debug.Print "We have Jane's age: " & dict.Exists("Jane")
    Debug.Print "We have Zak's age " & dict.Exists("Zak")

    'We can update a value by replacing it
   dict.Item("Ted") = dict.Item("Ted") / 10

    Debug.Print "Ted's real age is: " & dict.Item("Ted")

   'We can add more items
    dict.Add "Carla", 23

   'And we can iterate through the complete dictionary
    For Each v In dict.Keys
        Debug.Print "Name: " & v & "Age: "; dict.Item(v)
    Next

End Sub

That's all well and good and straightforward to do, but how do you use one in real life? OK. Here's a common scenario: Every month you get a workbook that contains a sheet of raw data – sales, orders, exam results, telephone calls etc. This table of data contains some unique fields – sales by salesperson, orders by region, exam results by subject etc. You need to extract the data by these fields to different worksheets. One way is to write some VBA code that runs through the raw data and just copies and pastes the data to the different sheets. The only thing is you need to keep track of where the next row is on these different sheets. This is where the dictionary comes in handy – each field can act as a key in a dictionary, and the next blank row is the value that corresponds to that key.

As an example here's a table of raw exam data by subject:

 

Name Date Subject Score
Alex 04/02/2009 Biology 60.00
Alex 06/03/2009 English 60.00
Angela 04/02/2009 Biology 47.00
Angela 06/03/2009 Physics 47.00
Bharat 02/02/2009 English 64.00
Bharat 04/03/2009 English 64.00
Christine 03/02/2009 Physics 52.00
Christine 05/03/2009 Physics 52.00
George 03/02/2009 Physics 71.00
George 05/03/2009 English 71.00
Gilbert 03/02/2009 Physics 14.00
Gilbert 05/03/2009 Physics 14.00
Jane 02/02/2009 English 56.00
Jane 04/03/2009 Biology 56.00
Peter 02/02/2009 English 45.00
Peter 03/02/2009 Physics 52.00
Peter 04/03/2009 English 45.00
Peter 05/03/2009 Physics 52.00

The VBA code to do the processing looks like this:

Sub ProcessData1()

Dim dict As Dictionary
Dim i As Integer
Dim targetRow As Integer
Dim name As String
Dim subject As String
Dim score As Double
Dim more As Boolean

Set dict = New Dictionary

more = True
i = 2

Worksheets("English").UsedRange.Clear
Worksheets("Physics").UsedRange.Clear
Worksheets("Biology").UsedRange.Clear

While more

    name = Worksheets("Data").Cells(i, 1).Value
    subject = Worksheets("Data").Cells(i, 3).Value
    score = Worksheets("Data").Cells(i, 4).Value

    If dict.Exists(subject) Then
        targetRow = dict.Item(subject)
    Else
        targetRow = 1
    End If

    Worksheets(subject).Cells(targetRow, 1) = name
    Worksheets(subject).Cells(targetRow, 2) = score
    dict.Item(subject) = targetRow + 1

    i = i + 1

    If Len(Worksheets("Data").Cells(i, 1)) = 0 Then more = False

Wend

End Sub

Running this allows us to process the data and produce a sheet that looks like this:

Alex

60

Bharat

64

Bharat

64

George

71

Jane

56

Peter

45

Peter

45

While this has been a very quick introduction to the Dictionary, don't be fooled by how easy it is to use. The Dictionary is a pretty powerful object, and for complex applications where you need more than one level of indirection, it is possible to have a dictionary that contains other dictionaries as keyed values - which we look at in part 2. All in all it's a powerful addition to your VBA coding set.


Contents copyright of Pan Pantziarka © 2009, 2011. If you like it link it, don't lift it. No copying for commercial use allowed. Site © 2009, 2011.