Home > Back-end >  Printing the Name of Dictionaries inside a Collection
Printing the Name of Dictionaries inside a Collection

Time:01-30

I have created a collection which consists of several dictionaries. As I try to loop through the collection to print the names of the dictionaries, I get the following error message: 450 - Wrong number of arguments or invalid property argument.

My code reads as follows:

First, create the individual dictionaries and add the data to them:

Dim Cows, Dogs, Goats As Object

Set Cows = CreateObject("scripting.dictionary")
Set Dogs = CreateObject("scripting.dictionary")
Set Goats = CreateObject("scripting.dictionary")

[...Load the dictionaries with the data...]

Once this is done, create the collection of dictionaries and start to loop through it to see the names of each dictionary (the result should give us "Cows, Dogs, Goats" in the immediate window):

Dim TotalAnimals As New Collection

    TotalAnimals.Add Cows
    TotalAnimals.Add Dogs
    TotalAnimals.Add Swans

Here lies the problem:

Dim AnimalType As Variant
        For Each AnimalType In TotalAnimals
        Debug.Print AnimalType
Next AnimalType

Any help would be greatly appreciated!!

CodePudding user response:

What you are trying to achieve is called 'Reflection'. Unfortunately, the VBA language does not have reflection so you cannot directly achieve what you want.

You could emulate what you want using a 'wrapper' class to allow a name to be associated with a specific dictionary.

The example below implements a simple wrapper class which allows the name to be set, but not changed, and exposes the scripting.dictionary via the Host property.

Class AnimalType

Option Explicit

Private Type Properties

    Name                    As String
    Host                    As Scripting.Dictionary

End Type

Private p                   As Properties


Private Sub Class_Initialize()
    Set p.Host = New Scripting.Dictionary
End Sub

Public Property Get Name() As String
    Name = p.Name
End Property

Public Property Let Name(ByVal ipName As String)

    If VBA.Len(p.Name) = 0 Then
    
        p.Name = ipName
        
    Else
    
        Err.Raise 17 ' Can't perform the requested action
        
    End If
    
End Property


Public Property Get Host() As Scripting.Dictionary
    Set Host = p.Host
End Property

Thus


Set Cows = CreateObject("scripting.dictionary")
Set Dogs = CreateObject("scripting.dictionary")
Set Goats = CreateObject("scripting.dictionary")

would become


Set Cows = CreateObject("scripting.dictionary")
Cows.name="Cows"
Set Dogs = CreateObject("scripting.dictionary")
Dogs.Name="Dogs"
Set Goats = CreateObject("scripting.dictionary")
Goats.Name="Goats"

and then

Dim myAnimalType As Variant
For Each myAnimalType In TotalAnimals
    Debug.Print myAnimalType.Name
Next

CodePudding user response:

Please adapt your code in the next way. You can give to the dictionary a Name (in fact a Collection key) when add it to Collection:

Sub testDictNameInCollection()
     Dim Cows As Object, Dogs As Object, Goats As Object
     Dim TotalAnimals As New Collection, i As Long, arrK
     
     Set Cows = CreateObject("scripting.dictionary")
     Set Dogs = CreateObject("scripting.dictionary")
     Set Goats = CreateObject("scripting.dictionary")
     
     'load here the dictionaries...

     TotalAnimals.Add Cows, "Cows"
     TotalAnimals.Add Dogs, "Dogs"
     TotalAnimals.Add Goats, "Goats"
     arrK = Array("Cows", "Dogs", "Goats")
     
     For i = 0 To UBound(arrK)
        Debug.Print TotalAnimals.item(arrK(i)).count
     Next i
     TotalAnimals.item("Cows").Add "Cow 1 ", "a lot of milk"
     Debug.Print TotalAnimals("Cows").Items()(0)
End Sub

If you like a fancy way, please follow the next logic:

Since Scripting.Dictionary does not expose a Name property, you can use a Type in order to use the object and its name:

  1. Please, copy the next code on top of the module (in the declarations area):
Private Type dictProps
    myDict As Object
    Name As String
End Type
  1. Use the next code, in order to accomplish what you need:
Sub testNameDict()
  Dim Cows As Object, Dogs As Object, Goats As Object
  Dim dType As dictProps, Coll As New Collection, i As Long
  
  Set dType.myDict = CreateObject("scripting.dictionary")
   dType.Name = "Cows"
   For i = 1 To 3
        dType.myDict(i) = "Cow " & i   'load the dictionary
   Next i
   Coll.Add dType.myDict, dType.Name   'add the dictionary to collection
   
   Set dType.myDict = CreateObject("scripting.dictionary")
    dType.Name = "Dogs"
    For i = 1 To 3
         dType.myDict(i) = "Dog " & i
    Next i
   Coll.Add dType.myDict, dType.Name   'add the dictionary to collection
   
   Set dType.myDict = CreateObject("scripting.dictionary")
    dType.Name = "Goats"
    For i = 1 To 3
         dType.myDict(i) = "Goat " & i
    Next i
   Coll.Add dType.myDict, dType.Name  'add the dictionary to collection
   
   'extract the dictionaries items using their name:
   Debug.Print Coll("Cows").count, Coll("Cows")(2)   'it returns Cow 2
   Debug.Print Coll("Dogs").count, Coll("Dogs")(1)   'it returns Dog 1
   Debug.Print Coll("Goats").count, Coll("Goats")(3) 'it returns Goat 3
End Sub
  •  Tags:  
  • Related