Search code examples
vbaclassdictionarymembervariant

Getting Object member from dictionary in vba


I have a class with a member that is an array of double

'cls_Person
Public Name as String
Public InAMeeting as Variant
'InAMeeting: Type: Array of Double.
'Sometimes with dimensions of 1 to 8, sometimes of 1 to 10.

I fill my class in a loop and then fill them into a global dictionary with a string as the key.

My problem comes when I try to access the InAMeeting member directly from the dictionary:

'g_dict_People is a globally defined dictionary.
'KeyPerson is a unique key in the dictionary matching a filled object of type cls_Person
Dim Bravo as Double
Bravo = g_dict_People(KeyPerson).InAMeeting(3)

results in error: Property let procedure not defined and property get procedure did not return an object (Error 451)

But if I first create a copy of the object from the dictionary then it works:

Dim Bravo as Double
Set temp_cls_Person = g_dict_People(KeyPerson)
Bravo = temp_cls_Person.InAMeeting(3)

I can access the Name member directly - this works:

Dim Alpha as string
Alpha = g_dict_People(KeyPerson).Name

Why the difference? Is it to do with the way that I declared the InAMeeting member in the class definition? Is there any way to directly access an object's members when they are of type array?

Sorry I haven't detailed a minimal working example - the code is spread out across multiple modules and classes.


Solution

  • I can't test your code since we don't have an MCVE, but the following code works for me. Modified from this answer. TIL yet another use case for ()! Try:

    Bravo = g_dict_People(KeyPerson).InAMeeting()(3)
                              ' extra parens!  ^^
    

    InAMeeting is apparently implemented as a property, i.e., a function that you have to call to get the array you want to index into. The extra () make that call.

    My test case:

    Class1.cls

    Public v As Variant
    

    ThisDocument.bas

    Public Sub foo()
        Dim v As Variant
        v = Array(1#, 2#, 3#, 4#, 5#)    ' Assuming you're doing something like this
    
        Dim o As Class1          ' Put the variant array in the object
        Set o = New Class1
        o.v = v
    
        Dim c As Collection      ' Put the object in the collection
        Set c = New Collection
        c.Add o, "key"
    
        On Error Resume Next
    
        Err.Clear
        Debug.Print "Direct"
        Debug.Print v(3)         ' Works OK
        Debug.Print Err.Number, Err.Description
    
        Err.Clear
        Debug.Print "From collection with ()"
        Debug.Print c("key").v()(3)             ' <== Your use case - works OK
        '        Extra parens ^^
        Debug.Print Err.Number, Err.Description
    
        ' Reproducing the problem
    
        Err.Clear
        Debug.Print "From collection"
        Debug.Print c("key").v(3)      ' <== Bombs --- I think this is analogous to your use case
        Debug.Print Err.Number, Err.Description
    
        Err.Clear
        Dim o1 As Object
        Set o1 = c("key")
        Debug.Print "Intermediate object"
        Debug.Print o1.v(3)         ' Trying what you tried, but it didn't work for me.
        Debug.Print Err.Number, Err.Description
    
        ' Another thing that works
    
        Err.Clear
        Debug.Print "Intermediate object with ()"
        Debug.Print o1.v()(3)               ' <== This works
        '   Those extra ^^ parens
        Debug.Print Err.Number, Err.Description
    
    End Sub