2

I've programmed in several languages but i'm at my first tests on VBA.

I need to make a class who has as a property, an array of objects of another class. Let's make an example a Person class who keeps info about name, surname and addresses. And an address class who keeps info about a street and zipcode. A person could have many addresses so Person should have an arrays of Addresses.

class Address
Private pStreet as String
Private pZip as Int

Public Property Let Street(val As String)
    pStreet = val
End Property
Public Property Get Street() As String
    Street = pStreet
End Property
Public Property Let Zip(val As String)
    pZip = val
End Property
Public Property Get Zip() As String
    Zip = pZip
End Property
class Person
Private pName as String
Private pSurname as String
Private pAddresses() as Address

Public Property Let Name(val As String)
    pName = val
End Property
Public Property Get Name() As String
    Name = pName
End Property

Public Property Let Surname(val As String)
    pSurname = val
End Property
Public Property Get Surname() As String
    Surame = pSurname
End Property

How should i manage the array of Address?

i tried with such code but if i try to call this method on a person object i get an error" obect doesn't support this property or method"

Public Sub addAddress(val as Address)
    ReDim pAddresses(1)
    pAddresses(0) = val
End Sub

what's the way to do this? i cannot find any tutorial or something who shows how to use arrays of objects inside of an object

1
  • One suggestion would be to use Collections instead of Arrays. Irregardless, try using Set in addAddress: Set pAddresses(0) = val. Commented Mar 31, 2022 at 14:43

2 Answers 2

1

When you use redim, it actually makes a brand new array of the specified size, so all existing data is lost. To copy the values from the old array to the new one, you need the 'Preserve' keyword as follows

ReDim Preserve pAddresses(1)

But this is really inefficient as adding another element to the array requires rewriting the entire array. You are probably better of using a collecion. So instead of declaring pAddress like this

Private pAddresses() as Address  ' delcare as an array

do it like this

Private pAddresses as New Collection ' declare as a collection

Now your method to add an address can look like this:

Public Sub addAddress(val as Address)
    pAddresses.Add val
End Sub

The indices for collections start counting at one instead of zero (as arrays do) so the following line prints the first entry in the collection

Debug.Print pAddresses(1)
Sign up to request clarification or add additional context in comments.

8 Comments

ok i did as you said, i changed my pAddresses as a collection, then added the following methods Public Sub addAddress(val as Address) pAddress.Add val End Sub Public Sub remAddress(val as Address) pAddress.Remove val End Sub but when i try to add an address i get "invalid qualifier" and the first line of the method add is highlighted
Your code should be pAddresses.Add val to match your declaration.
it worked! but how can i retrieve an object of that collection? with array i'd do x.array(1), how about to get for instance the zip code of the second address of a person?
Also, the remove method of collections takes an index number, not a value to remove, so you would need "pAddresses.Remove 1" to remove the first address in the collection
In your code example, pAddresses is declared as private so it is not accessible from code outside the person class. From inside the class, I think it would be "pAddresses(2).Zip"
|
1

Change your code to this should work

 Public Sub main()
        
    Dim val As New Address
    val.Street = "MyStreet"
    val.Zip = 666
    Dim val2 As New Address
    val2.Street = "my New Street"
    val2.Zip = 999
    
    
    Dim myself As New Person
    With myself
        .Name = "its Me"
        .Surname = "Smith"
        Call .addAddress(val)
        Call .addAddress(val2)
    End With
    
    
    ' Get Number off addresses available
    Debug.Print "Number of Adresses: " &   myself.GetAddresses.Count
    
    ' Read the Addresses
    Dim Add As Address
    For Each Add In myself.GetAddresses
        Debug.Print "Streetname: " & Add.Street & ", Zip:" & Add.Zip
    Next
    
    ' Get First Address of the List
    Debug.Print "First Adress - Streetname:  " & myself.GetAddresses(1).Street
    Debug.Print "First Adress - Zip:  " & myself.GetAddresses(1).Zip
        
    ' Get The Address Object itself
    Dim theAdd As Address
    Set theAdd = myself.GetAddresses(1)
    Debug.Print "First Adress - Streetname:  " & theAdd.Street
    Debug.Print "First Adress - Zip:  " & theAdd.Zip
    
    ' Remove Address
    Call myself.GetAddresses.Remove(1)
    
End Sub
        
            
            
                
 class Address
    Private pStreet As String
    Private pZip As Integer
    
    Public Property Let Street(val As String)
        pStreet = val
    End Property
    Public Property Get Street() As String
        Street = pStreet
    End Property
    Public Property Let Zip(val As String)
        pZip = val
    End Property
    Public Property Get Zip() As String
        Zip = pZip
    End Property
    
 end class

            
             
                
class person
                    
    Private pName As String
    Private pSurname As String
    Private pAddresses As Collection

    Private Sub Class_Initialize()
       Set pAddresses = New Collection
    End Sub
    
    Public Property Let Name(val As String)
        pName = val
    End Property
    Public Property Get Name() As String
        Name = pName
    End Property
    
    Public Property Let Surname(val As String)
        pSurname = val
    End Property
    Public Property Get Surname() As String
        Surame = pSurname
    End Property
    
    Public Sub addAddress(val As Address)
        Call pAddresses.Add(val)
    End Sub
    
    Public Function GetAddresses() As Collection
        Set GetAddresses = pAddresses
    End Function
    
end class

First, create objects using NEW Keyword and then SET the objects to variables. You Always have to use the SET Keyword if you want to store a reference to an existing object inside of an variable.

Revealing Access trough the Person.GetAddresses() Function to the Person class address collection itself is not a clean way for encapsulation. But I think this helps for a better understanding.

Nice Starting Point to get into collections: Excel Collection Ultimate Guide Definitly important topic, since mostly all for each loops iterate trough collections.

2 Comments

thank you so much... how to retrieve then an object of that collection? for instance, how to print the zip code of one of the addresses of a person?
See my changes in the main() method and inside of the Person class. Also accept the answer if it was helpfull to you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.