patternMinor
Traversing and printing complex Dictionary types (Scripting.Dictionary) - Dictionary inside of a Dictionary
Viewed 0 times
scriptingtraversingprintingtypesanddictionarycomplexinside
Problem
Based on this SO post - also reposted on vba4all.com with a few more details and explanations.
Please notice there currently is no error handling whatsoever as I didn't analyse and consider any traps yet. Although feel free to supply details/code based on your assumptions. For Example - the code fails when you try to load duplicate keys into the dictionary... this can easily be handled with the OERN approach...
So the tree would look like this for example
I have created a simple procedure
The simplest version that prints somehow a logical structure to the Immediate Window:
with a result:
and w/ a print out to sheet with somehow even more logical view
```
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
Please notice there currently is no error handling whatsoever as I didn't analyse and consider any traps yet. Although feel free to supply details/code based on your assumptions. For Example - the code fails when you try to load duplicate keys into the dictionary... this can easily be handled with the OERN approach...
So the tree would look like this for example
I have created a simple procedure
TraverseDictionary() which traverses any structure of dictionaries. The simplest version that prints somehow a logical structure to the Immediate Window:
Sub Main()
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
TraverseDictionary dict
End Sub
Private Sub TraverseDictionary(d As Dictionary)
For Each Key In d.Keys
Debug.Print "KEY: " & Key
If VarType(d(Key)) = 9 Then
TraverseDictionary d(Key)
Else
Debug.Print "ITEM: " & d(Key)
End If
Next
End Subwith a result:
and w/ a print out to sheet with somehow even more logical view
```
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
Solution
A couple of things, which you've really more or less pointed out already.
-
You've shown us two different implementations of the same routine that outputs two two different places. I think what you really need is a class that gets initialized with an
-
You're correct that
But that means you'll also have to check
Update:
I finally had time to test this. I created an empty
-
You've shown us two different implementations of the same routine that outputs two two different places. I think what you really need is a class that gets initialized with an
IOuput member. Then you can have different implementations of the IOuput interface, but TraverseDictionary only has to deal with IOutput and one routine can print out to anywhere. -
You're correct that
VarType = 9 is unsafe and TypeName = "Dictionary" is safer, but I'm not sure it's entirely safe. What if there's a namespace conflict because I implemented a VBAProject.Dictionary? TypeName of my custom dict would also be "Dictionary" and who knows what would happen then. TypeOf is another option though. I've not tested it, but I believe you can do this. If TypeOf d(Key) Is Scripting.Dictionary ThenBut that means you'll also have to check
IsObject(d(key)) prior to checking its actual type as well. Update:
I finally had time to test this. I created an empty
Dictionary class and ran the code below. It works.Sub test()
Dim dict As New Scripting.Dictionary
Dim myDict As New VBAProject.Dictionary
Debug.Print TypeOf dict Is Scripting.Dictionary
'true
Debug.Print TypeOf myDict Is Scripting.Dictionary
'false
Debug.Print TypeOf dict Is VBAProject.Dictionary
'false
Debug.Print TypeOf myDict Is VBAProject.Dictionary
'true
End SubCode Snippets
If TypeOf d(Key) Is Scripting.Dictionary ThenSub test()
Dim dict As New Scripting.Dictionary
Dim myDict As New VBAProject.Dictionary
Debug.Print TypeOf dict Is Scripting.Dictionary
'true
Debug.Print TypeOf myDict Is Scripting.Dictionary
'false
Debug.Print TypeOf dict Is VBAProject.Dictionary
'false
Debug.Print TypeOf myDict Is VBAProject.Dictionary
'true
End SubContext
StackExchange Code Review Q#63353, answer score: 7
Revisions (0)
No revisions yet.