Home > Back-end >  VBA Collection with case specific keys
VBA Collection with case specific keys

Time:01-12

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.

  •  Tags:  
  • vba
  • Related