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:
- 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
- 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
