How to use comparison methods between class object modules in VBA in a similar manner as VB.NET?

后端 未结 1 1721
难免孤独
难免孤独 2020-11-27 09:47

Due to new project in VBA I moved from VB.NET, to be honest don\'t really know how to deal between objects classes here. What I want to reach is comparing objects between di

相关标签:
1条回答
  • 2020-11-27 10:33

    VBA doesn't support class polymorphism so I recommend to change the way you're thinking about the Employee and Manager classes.

    You can't have an Employee class as a base class and then a separate Manager class that derives from Employee. They could be 2 separate classes implementing a common interface.

    I will talk about it in detail in a bit. Let's now go through a few examples...


    ↓ Easy approach ↓


    A base class (Person) and child classes which derive from the base class. (applies to C#, VB.NET, etc)

    but in VBA you have to think of it like this:

    A base class which exposes an enum property describing the position.

    Something like

    enter image description here

    enter image description here

    This is the easiest way to have a class exposing some properties. It allows you to add your Person objects into a collection and iterate over using the easy for each loop with Intellisense!

    enter image description here

    Properties comparison system would be very very easy

    enter image description here

    note: same applies to enum as its implicitly converted to a number


    ↓ More complex approach ↓


    Two separate classes which both expose public properties. For instance you have an Employee and Manager classes which both implement a Person Interface and an additional Comparer class exposing a Compare() method

    enter image description here

    In your VBA Project you need 4 class modules and a standard module

    enter image description here

    Person (this is your Interface)

    Public Property Get Name() As String
    End Property
    
    Public Property Get Age() As Long
    End Property
    

    this class is the interface which both the Employee and Manager both need to implement to share some common functions (getters for Names and Ages). Having the interface allows you to do the for each loop using the interface type variable as the enumerator. You will see in a minute.

    Employee and Manager are identical. Obviously you may modify them to suit your real life solution.

    Implements Person
    
    Private name_ As String
    Private age_ As Long
    
    Public Property Get Name() As String
        Name = name_
    End Property
    
    Public Property Let Name(ByVal Value As String)
        name_ = Value
    End Property
    
    Public Property Get Age() As Long
        Age = age_
    End Property
    
    Public Property Let Age(ByVal Value As Long)
        age_ = Value
    End Property
    
    Private Property Get Person_Name() As String
        Person_Name = Name
    End Property
    
    Private Property Get Person_Age() As Long
        Person_Age = Age
    End Property
    

    ComparerCls you will use an instance of this class to compare two objects properties or references. You do not necessarily need to have a class for this but I prefer it that way.

    Public Enum ComparisonMethod
        Names = 0 ' default
        Ages = 1
        References = 2
    End Enum
    
    ' makes names the default comparison method
    Public Function Compare(ByRef obj1 As Person, _
                            ByRef obj2 As Person, _
                            Optional method As ComparisonMethod = 0) _
                            As Boolean
    
        Select Case method
            Case Ages
                Compare = IIf(obj1.Age = obj2.Age, True, False)
            Case References
                Compare = IIf(obj1 Is obj2, True, False)
            Case Else
                Compare = IIf(obj1.Name = obj2.Name, True, False)
        End Select
    
    End Function
    

    And your Module1 code

    Option Explicit
    
    Sub Main()
    
        Dim emp As New Employee
        emp.Name = "person"
        emp.Age = 25
    
        Dim man As New Manager
        man.Name = "manager"
        man.Age = 25
    
        Dim People As New Collection
        People.Add emp
        People.Add man
    
        Dim individual As Person
        For Each individual In People
            Debug.Print TypeName(individual), individual.Name, individual.Age
        Next
    
    End Sub
    

    run the Main() sub and check out the results in the Immediate Window

    enter image description here

    The best part of the above code is the fact that you are creating a reference variable of the Person interface. It allows you to loop through all items in the collection that implement the interface. Also, you can use the Intellisense which is great if you have had many more properties and functions.


    Comparison


    Take a look again at the code in the ComparerCls class

    enter image description here

    I hope you see now why I have separated this to be a class. Its purpose is just to take care of the way the objects are being compared. You can specify the Enum order and modify the Compare() method itself to compare differently. Note the Optional parameter which allows you to call the Compare method without the method of comparison.

    enter image description here

    Now you can play around passing different parameters to the compare function. See what the results are like.

    Try combinations:

    emp.Name = "name"
    man.Name = "name"
    
    Comparer.Compare(emp, name, Names)
    Comparer.Compare(emp, name, References)
    
    Comparer.Compare(emp, emp, References)
    

    If something is still unclear refer to this answer about the Implements keyword in VBA

    0 讨论(0)
提交回复
热议问题