Home » excel » excel – Recursively print next dictonaries in VBA

excel – Recursively print next dictonaries in VBA

Posted by: admin April 23, 2020 Leave a comment

Questions:

I’d like to print nested dictionaries in VBA. Basically I have a Dictionary where every key is a String, but each value can either be a String or another Dictionary.

Say my Dictionary has got the value

{ "FOO" => "BAR" , "HELLO" => { "WORLD => ":)", "OTHER" => ":(" } }

I want to display in an Excel spreadsheet:

FOO  |BAR  |
HELLO|WORLD|:)
HELLO|OTHER|:(

My issue is that I need to find a way to guess what is the type of the value under each key, so when I call dict("HELLO") I can either display the value if it’s a string or if it’s a dictionary call the same function again.

In order to do so I need to know:

  • if there is a way to know what is the type of a value stored in a dictionary
  • if there is a way to cast that value to a target type (string or dictionary)

So here is what I’ve tried

Function display_dictionary(dict As Scripting.Dictionary, out As Range) As Integer

  Dim vkey As Variant
  Dim key As String
  Dim row_offset As Integer
  Dim value As Object
  Dim svalue As String
  Dim dvalue As Dictionary
  Dim each_offset  As Integer

  row_offset = 0

  For Each vkey In dict.Keys()
    key = vkey
    Set value = dict(key)
    if value is String then
       svalue = ???
       out.offset(row_offset, 0).value = key
       out.offset(row_offset, 1).value = svalue
       row_offset = row_offset + 1
    else if value is Dictionary
       dvalue = ???
       each_offset = display_dictionary(dvalue, out.offset(row_offset, 1))
       For each_row = 0 To each_offset - 1
        out.offset(row_offset + each_row) = key
       Next
       row_offset = row_offset + each_offset
    End If
  Next

End
How to&Answers:

I am actually going to propose a bit different way for displaying the results. I think it’s more logical but you are welcome to modify it to suit your specific needs. Just as a hint print logical tree of nodes, like below, and then manipulate the results if ever needed.

So the tree would look like this for example (Note I added one more depth level)

dictionary tree

and the code to reproduce

Private i As Long
Private depth As Long

Sub Main()
Cells.ClearContents

    Dim dict As New Dictionary
    Dim subDict As New Dictionary
    Dim lvlDict As New Dictionary

    lvlDict.Add "LVL KEY", "LVL ITEM"

    subDict.Add "HELLO", ":)"
    subDict.Add "WORLD", ":("
    subDict.Add "OTHER", lvlDict

    dict.Add "FOO", "BAR"
    dict.Add "BOO", subDict

    i = 1
    depth = 0
    TraverseDictionary dict

    Columns.AutoFit

End Sub

Private Sub TraverseDictionary(d As Dictionary)

    For Each Key In d.Keys
        Range("A" & i).Offset(0, depth) = "KEY: " & Key
        If VarType(d(Key)) = 9 Then
            depth = depth + 1
            TraverseDictionary d(Key)
        Else
            Range("B" & i).Offset(0, depth) = "ITEM: " & d(Key)
        End If
        i = i + 1
    Next
End Sub

and spreadsheet result:

enter image description here


To get the variable type or its type name you can use this:

Debug.Print TypeName(dict("HELLO")), VarType(dict("HELLO"))