a_thomas
a_thomas

Reputation: 31

VBA class with a property that has properties

I'm an trying to build a class that describes basically a geospatial conditional statement where one of the parameters is the altitude. Altitude has 4 properties like Min, Max, Units, Invert and I'm trying to make the class support a 2 layer property.

IE

Dim blah as qClass
Set blah = New qClass

blah.Altitude.Min = 100

That is the effect I'm looking for but I'm having a hard time figuring out how to implement it. (Moderate VBA experience but first time getting into classes)

My Solution: I made a generic class that had the Min/Max/Unit/Invert arguments that I'll use for each parameter so that only has to be set up once then reused.

Settings Class

Private pMin As Integer
Private pMax As Integer
Private pUnit As String
Private pInvert As Boolean

Public Property Get Min() As Integer
    Min = pMin
End Property

Public Property Get Max() As Integer
    Max = pMax
End Property

Public Property Get Unit() As String
    Unit = pUnit
End Property

Public Property Get Invert() As Boolean
    Invert = pInvert
End Property

Public Property Let Min(Value As Integer)
    pMin = Value
End Property

Public Property Let Max(Value As Integer)
    pMax = Value
End Property

Public Property Let Unit(Value As String)
    pUnit = Value
End Property

Public Property Let Invert(Value As Boolean)
    pInvert = Value
End Property

Parent Class Settings use

'CPA Range Property
Public Property Get CPARange() As cSettings
    If pCPARange Is Nothing Then Set pCPARange = New cSettings
    Set CPARange = pCPARange
End Property
Public Property Set CPARange(Value As cSettings)
    Set pCPARange = Value
End Property

Upvotes: 3

Views: 1127

Answers (3)

John Alexiou
John Alexiou

Reputation: 29264

If you want to do this:

Public Sub Test()
    Dim a As New aClass
    a.InitializeFromValues 40, 150

    Dim q As New qClass
    q.Altitude = a
    ' q.Altitude.Min = 40
    ' q.Altitude.Max = 150

    Dim z As New qClass
    z.Altitude.Max = 100
    ' z.Altitude.Min = 0   (default)
    ' z.Altitude.Max = 100
End Sub

The you need two classes. I call them qClass and aClass.

=== aClass Definition ===

Private m_min As Double
Private m_max As Double

Private Sub Class_Initialize()
    m_min = 0#
    m_max = 0#
End Sub

Public Sub InitializeFromValues(ByVal Min As Double, ByVal Max As Double)
    m_min = Min
    m_max = Max
End Sub

Public Property Get Min() As Double
    Min = m_min
End Property

Public Property Let Min(ByVal X As Double)
    m_min = X
End Property

Public Property Get Max() As Double
    Max = m_max
End Property

Public Property Let Max(ByVal X As Double)
    m_max = X
End Property

and

=== qClass Definition ===

Private m_alt As aClass

Private Sub Class_Initialize()
    Set m_alt = New aClass
End Sub

Public Sub InitializeFromValues(ByVal alt As aClass)
    Set m_alt = alt
End Sub

Private Sub Class_Terminate()
    Set m_alt = Nothing
End Sub

Public Property Get Altitude() As aClass
    Set Altitude = m_alt
End Property

Public Property Set Altitude(ByVal X As aClass)
    Set m_alt = X
End Property

Upvotes: 1

user3598756
user3598756

Reputation: 29421

since you seem to need only properties handling of a geospatial "object" then you could use UDT's

you can declare it in any module as follows:

    Option Explicit

    Public Type AltitudeType '<~~ first declare the UDT that will be a sub-type of the main one
        Min As Long
        Max As Long
        Units As String 'my guessing...
        Invert As Boolean 'my guessing...
    End Type

    Public Type GeoSpatial '<~~ then declare the main UDT
        Altitude As AltitudeType
        GeoInfo1 As Long ' I don't know anything about geospatials...
        GeoInfo2 As Double ' I don't know anything about geospatials...
        GeoInfo3 As String ' I don't know anything about geospatials...
    End Type

and then use it in any other module like follows:

Sub main()

    Dim GeoSpatials(1 To 10) As GeoSpatial '<~~ initialize the UDT. here I assumed you would need an array        

    SetDefault GeoSpatials '<~~ launch default setting...
    GeoSpatials(1).Altitude.Min = 200 '<~~ ... and then define only peculiar properties
    GeoSpatials(2).GeoInfo1 = 2000000 '<~~ etc...

End Sub


Sub SetDefault(geospatArray() As GeoSpatial) '<~~ Sub to initialize each element of the geospatial array
    Dim i As Long
    For i = LBound(geospatArray) To UBound(geospatArray)
        With geospatArray(i)
            With .Altitude
                .Min = 100
                .Max = 200
                .Units = "Meters"
                .Invert = True
            End With
            .GeoInfo1 = 1000000
            .GeoInfo2 = 100.2
            .GeoInfo3 = "Geospat"
        End With
    Next i
End Sub

Upvotes: 0

Tim
Tim

Reputation: 2902

Actually, I'll expand on my comment with an example. I have two custom classes: clsComputer, and clsHDD. clsComputer has 3 properties: pModel, pSerialNumber, and pHDD. pHDD is an instantiation of clsHDD (because a computer can have multiple hard drives that are dissimilar). The really important part is in clsComputer where we check If pHardDrives(index) Is Nothing! If you don't do that and try to access objComputer.HDD.Status it will crash.

clsComputer:

Private pModel As String
Private pSerialNumber As String

''''''''''''''''''''''
' Model property
''''''''''''''''''''''
Public Property Get Model() As String
    Model = pModel
End Property
Public Property Let Model(value As String)
    pModel = value
End Property
''''''''''''''''''''''
' SerialNumber property
''''''''''''''''''''''
Public Property Get SerialNumber() As String
     SerialNumber = pSerialNumber
End Property
Public Property Let SerialNumber(value As String)
    pSerialNumber = value
End Property
''''''''''''''''''''''
' HardDrives property
''''''''''''''''''''''
Public Property Get HardDrives(index As Integer) As clsHDD
    If pHardDrives(index) Is Nothing Then Set pHardDrives(index) = New clsHDD
    Set HardDrives = pHardDrives(index)
End Property
Public Property Set HardDrives(index As Integer, value As clsHDD)
    Set pHardDrives(index) = value
End Property
''''''''''''''''''''''
' HardDrives property
''''''''''''''''''''''
Public Property Get HardDrives(index As Integer) As clsHDD
    If pHardDrives(index) Is Nothing Then Set pHardDrives(index) = New clsHDD
    Set HardDrives = pHardDrives(index)
End Property
Public Property Set HardDrives(index As Integer, value As clsHDD)
    Set pHardDrives(index) = value
End Property

clsHDD:

Private pDescription As String
Private pStatus As String

Public Property Get Description() As String
    Description = pDescription
End Property
Public Property Let Description(value As String)
    pDescription = value
End Property

Public Property Get Status() As String
    Status = pStatus
End Property
Public Property Let Status(value As String)
    pStatus = value
End Property

Upvotes: 0

Related Questions