I need to store class items in vba such that the collection can be string indexed and iterated like a normal collection. But the keys need to be case specific. To clarify I need this behavior:
classWaz:
...
Private mName As String
...
Public Property Get Name() As String
Name=mName
End Property
Public Property Let Name(RHS As String)
mName=RHS
End Property
...
Sub DoIt()
Dim d As Desideratum, foo As classWaz, bar As classWaz, iter As classWaz
Set d = New Desideratum '<- The thing I need - a collection with case specific keys
Set foo = New classWaz
foo.Name = "foo"
Set bar = New classWaz
bar.Name = "bar"
d.Add Item:=foo, Key:="baz"
d.Add Item:=bar, Key:="BAZ"
For Each iter In d
Debug.Print iter.Name
Next
'Should print
' foo
' bar
Set iter = d("baz")
Debug.Print iter.Name
'Should print
' foo
End Sub
The setup is that I have code using Collection that extensively uses these idioms. But I realized as I was testing that my use case requires case specific indexing and Collection doesn't support this.
I've tried Dictionary, but this doesn't appear to support class items. .Items() also returns an array, so a different iteration idiom would be needed. And I'm not aware of any way to force Collection to use vbCompareBinary. Even using Option Compare Binay, which is the default anyway.
I can think of a few workarounds; like having classes that had Collection typed properties, instead have methods GetWaz(wazName As String) As classWaz and an un-keyed GetWazes() As Collection. But this would be a lot of work I'd like to avoid if I can.
Thanks
CodePudding user response:
I don't see the issue with using a Dictionary:
Sub DoIt()
' Requires reference to Microsoft Scripting Runtime
Dim d As Scripting.Dictionary
Set d = New Scripting.Dictionary
Dim foo As classWaz, bar As classWaz, iter As classWaz
Set foo = New classWaz
foo.Name = "foo"
Set bar = New classWaz
bar.Name = "bar"
d.Add Key:="baz", Item:=foo
d.Add Key:="BAZ", Item:=bar
Dim i As Long
For i = LBound(d.Items) To UBound(d.Items)
Debug.Print d.Items(i).Name
Next
Set iter = d("baz")
Debug.Print iter.Name
End Sub
Caveat: the Scripting.Dictionary is not available on macOS, though you might consider this drop-in replacement.
