Reputation: 2108
I have two classes of shapes and an interface. After I instantiate objects from each class and set their properties I add them to a collection. That's pretty straightforward. Then I declare a variable of type MyInterface
and loop through the collection to add each shape. But there is an additional property for each type of shape that I want to set but which are not part of the interface. Is there a way to do this? I think other languages call this type casting but I am not sure. Does VBA support this? Any help is appreciated. My code is below:
Interface (iShape)
Option Explicit
Public Property Let Top(value As Long)
End Property
Public Property Get Top() As Long
End Property
Public Property Let Left(value As Long)
End Property
Public Property Get Left() As Long
End Property
Public Property Let Width(value As Long)
End Property
Public Property Get Width() As Long
End Property
Public Property Let Height(value As Long)
End Property
Public Property Get Height() As Long
End Property
Public Function Draw(obj As Worksheet) As Excel.Shape
End Function
Class (cDiamond)
Option Explicit
Private pTop As Long
Private pLeft As Long
Private pWidth As Long
Private pHeight As Long
Private pColor As Long
Implements iShape
'====================Properties====================
Public Property Let Top(value As Long)
pTop = value
End Property
Public Property Get Top() As Long
Top = pTop
End Property
Public Property Let Left(value As Long)
pLeft = value
End Property
Public Property Get Left() As Long
Left = pLeft
End Property
Public Property Let Width(value As Long)
pWidth = value
End Property
Public Property Get Width() As Long
Width = pWidth
End Property
Public Property Let Height(value As Long)
pHeight = value
End Property
Public Property Get Height() As Long
Height = pHeight
End Property
Public Property Let Color(value As Long)
pColor = value
End Property
Public Property Get Color() As Long
Color = pColor
End Property
'====================Methods====================
Public Function Draw(obj As Worksheet) As Excel.Shape
Set Draw = obj.Shapes.AddShape(msoShapeFlowchartOffpageConnector, Me.Left, Me.Top, Me.Width, Me.Height)
End Function
'====================Interface====================
Private Property Get iShape_Height() As Long
iShape_Height = Height
End Property
Private Property Let iShape_Height(RHS As Long)
Height = RHS
End Property
Private Property Get iShape_Left() As Long
iShape_Left = Left
End Property
Private Property Let iShape_Left(RHS As Long)
Left = RHS
End Property
Private Property Get iShape_Top() As Long
iShape_Top = Top
End Property
Private Property Let iShape_Top(RHS As Long)
Top = RHS
End Property
Private Property Get iShape_Width() As Long
iShape_Width = Width
End Property
Private Property Let iShape_Width(RHS As Long)
Width = RHS
End Property
Private Function iShape_Draw(obj As Worksheet) As Shape
Set iShape_Draw = Draw(obj)
End Function
Class (cTextbox)
For the sake of brevity, this class is identical to cDiamond except it has a Caption
property instead of a Color
property.
Module (mTest)
Option Explicit
Private Sub Test()
Dim wks As Excel.Worksheet
Set wks = ActiveSheet
Dim c As Collection
Set c = New Collection
Dim d1 As cDiamond
Set d1 = New cDiamond
d1.Top = 10
d1.Left = 10
d1.Height = 25
d1.Width = 25
d1.Color = RGB(255, 0, 0)
c.Add d1
Dim d2 As cDiamond
Set d2 = New cDiamond
d2.Top = 50
d2.Left = 10
d2.Height = 25
d2.Width = 25
d2.Color = RGB(0, 255, 0)
c.Add d2
Dim t1 As cTextbox
Set t1 = New cTextbox
t1.Top = 90
t1.Left = 10
t1.Height = 25
t1.Width = 25
t1.Caption = "Textbox"
c.Add t1
Dim shp As iShape
For Each shp In c
shp.Draw wks
' I would like to set the color or caption properties depending on the type of shape in the collection.
Next shp
Set c = Nothing
End Sub
Upvotes: 1
Views: 72
Reputation:
Declaring shp as object you will lose intellisense. Another technique would be to have Interface return a reference to the instance of object. Similarly to how OLEObject.Object
returns the instance of the object that it is wrapping. In my example I use This
to return the instance of the class.
In this way you will have intellisense for all the common properties and methods. We can also access the properties and methods that are unique to the classes that implement your interface using a With
statement.
You'll need to first test check the type of the object. Then use a With
statement to temporarily instantiate a new Object of that type and write your code inside the With
statement .
If TypeOf shp Is cTextbox Then
With New cTextbox
Msgbox .Caption
End With
End If
Finally, you simply replace the New
instance with the actual instance of the Object.
If TypeOf shp Is cTextbox Then
With shp.This
Msgbox .Caption
End With
End If
Interface (iShape)
Public Function This() As Object
End Function
Classes cTextbox & cDiamond
Public Function This() As Object
Set This = Me
End Function
Public Function iShape_This() As Object
Set iShape_This = This
End Function
mTest.Test
Dim shp As iShape
For Each shp In c
shp.Draw wks
If TypeOf shp Is cTextbox Then
With shp.This
MsgBox .Caption
End With
End If
' I would like to set the color or caption properties depending on the type of shape in the collection.
Next shp
Upvotes: 1
Reputation: 60344
If I understand you correctly, (and I don't fully understand interfaces either), you should be able to do what you want by declaring shp as of type variant.
Dim shp
For Each shp in C ...
shp
will then take on the type of either cDiamond
or cTextbox
depending on which is retrieved from the Collection
. Then you will be able to retrieve or modify shp.color
or shp.caption
. You may also want to change Caption
to datatype String
in cTextBox
Upvotes: 1