VBA Class Method Chaining

2019-07-15 06:56发布

问题:

I'm looking for a way to 'chain class methods', for example the Range object can do things like "Range.Borders.Color", I guess that the Borders part is it's own class which is being accessed by the Range class but I have no idea how to implement something similar with my own classes - Nor do I even know what this is called and after hours of searching I think I might slowly be un-learning VBA.

Can anybody either a) Provide code which I could look at to replicate or b) Tell me what this is called and maybe even nudge me in a helpful direction?

As I know asking for code without providing any makes me look like a dick, consider the following pseudo-code. I know it's horrific but it might help me make any sense:

main ------------------------------------------------------------------------

Dim obj as class1
set obj = new class1

obj.Target = Range("A1:B5")
obj.Borders.Add

'A1:B5 put into modRange then given borders

class1 ------------------------------------------------------------------------

Private modRange as range

Public Property Let Target(newTarget as Range)
  set modRange = newTarget
End Property

Public Property Borders()
    Public Sub Add()
        'Code to add borders to modRange
    End Sub 
    Public Sub Remove()
        'Code to remove borders from modRange
    End Sub 
End Property

I know this is not how the actual code would look. but as I don't know the syntax this is the closest thing I can imagine. I guess the real thing would have class1 linking to other class modules. Maybe.

As a side note. If I did have a class called "Borders" (I probably wont) as part of this class 1 object, would it conflict with the Borders portion of the Range object as well as it has a similar name? Or will the Private scope save the day?

(The .Borders.Add/Remove is a bit ridiculous to have as a class I know, I'm really only after the syntax - Honest)

回答1:

To have complex properties of an object, you need to create a new class and then create an instance of that class in the parent class. So if you want to have something like Class1.Borders.Add(), you'd first have to create a new CBorders class (I used to prepend C to my class names in VB6 / VBA to avoid name collisions). Something like:

'- in class CBorder
Private m_lColor As Long

Public Property Get Color() As Long
    Color = m_lColor
End Property

Public Property Let Color(ByVal lNewColor As Long)
    m_lColor = lNewColor
End Property

Public Sub Reset()
    m_lColor = 0
End Sub

...

Then inside Class1, you'd have something like this:

Private m_oBorder As CBorder

Private Sub Class_Initialize()
    ...
    Set m_oBorder = New CBorder
    ...
End Sub

Public Property Get Border() As CBorder
    Set Border = m_oBorder
End Property

...

Then you can do this:

Dim obj As Class1
Set obj = New Class1

obj.Borders.Color = ...
...

Notice how the Borders property of Class1 is accessed as a member of the obj instance and then how the Color property of the CBorder class is used. Creating these values as properties is what lets you chain these calls together.

You'd need error checking and validation code as well - I left those out to keep the example short.



回答2:

Another solution for this is to just return Me to make it chainable.

class module: CChaining

Using Functions for Target and Borders returning Me to enable chaining. Using Subs for Add and Remove to "finish" the chain.

Private modRange As Range, modRangeBorders As Object

Public Function Target(rng As Range)
    Set modRange = rng
    Set Target = Me
End Function

Public Function Borders()
    Set modRangeBorders = modRange.Borders
    Set Borders = Me
End Function

Public Sub Add()
    modRangeBorders.LineStyle = xlContinuous
End Sub

Public Sub Remove()
    modRangeBorders.LineStyle = xlNone
End Sub

Testing the class in a module

Sub testing()
    Dim obj As New CChaining
    obj.Target(Range("A1:B5")).Borders.Add
    'now the target and property (Borders) is set and you could do this
    'obj.Remove
End Sub

Pretty nice ... hmm, with this it would be possible to build a library like in other languages (javascript > jQuery) to make using Excel VBA much easier.