Classes are objects and objects are classes. Have you ever seen an error message like this:
“Cannot get the WorksheetFunction property of the Range class”
We call it the Range Object, but we could just as accurately call it the Range Class. Objects are nothing more than the properties, methods, and events they contain. A Range object is what it is because of its unique combination of properties, methods, and events (and because the name of the class is “Range”).
You may have seen how to use classes for Application Level Events, CommandbarButton events, or QueryTable events. You can also use classes to create your own custom objects. Some of the benefits of using class modules are
- Encapsulation – a programming best practice, encapsulation allows you to keep related code in one place making debugging easier and leading to…
- Portability – with an encapsulated class, you can move that class to another VBA project and use it there.
- Ease of Programming – while coding the “business” end of an application, it’s easier to use a classes properties and methods than to code all that information yourself. Of course, setting up the class takes some time and resources too.
- Self-Documentation – Properly named classes and their respective properties and methods aid in creating self documenting code.
Assume you want to create a card game in Excel. You can create a Card class which has certain properties and methods which you can then use to program your game. If later you want to create a different card game, you copy that class to another project and save yourself some setup time. Here’s a simple example of Card class:
Private mValue
As String
Property Get Value() As String
Value = mValue
End Property
Property Let Value(aValue As String)
If aValue Like “1#[C,D,H,S]“ Then
mValue = aValue
ElseIf aValue Like “#[C,D,H,S]“ Then
mValue = aValue
Else
Err.Raise Number:=vbObjectError + 513, _
Source:=“MyCardGame.Card”, _
Description:=“Value must in the form 1D, 2H, 10S, 13C”
End If
End Property
Property Get Suit() As String
Suit = Right(mValue, 1)
End Property
Property Get Number() As Long
Number = Val(mValue)
End Property
The name of the class is Card and it has three properties, Value, Suit, and Number. Value is a read/write property and Suit and Number are both read-only. I start by defining a private variable called mValue. This will hold the Value property for this instance of the class. Then I define a series of Property Let/Get statements that allow the programmer access to that variable.
The Value property has both a Property Get and a Property Let procedure which is what makes it read/write. The Get procedure merely returns the mValue variable. The Let procedure assigns a value to the mValue variable, but also includes some error checking. If the programmer tries to assign a value to the Value property that is not in the proper format, and error is raised. The property format being a number 1-13 followed by a one-letter suit (Clubs, Diamonds, Hearts, Spades).
The Suit and Number properties only have Get procedures. The programmer cannot assign values to these properties, only read them. Both Get procedures use the mValue variable to retrieve the portion of the Value that the property calls for. For the Suit property, it returns the right most character – the one-letter alpha that is the suit. For the Number property, the Val() function is used to strip off the suit and only return the number.
You don’t need to provide the programmer with a Suit and Number property, but since the programmer will likely be you, you want to make life as easy as possible. If you create a poker game and want to determine if a poker hand is a flush, you can just use the Suit property.
Here’s some code that uses the new Card object.
Sub TestCard()
Dim Crd As Card
Set Crd = New Card
‘Nothing assigned to value
Debug.Print Crd.Value, Crd.Suit, Crd.Number
Crd.Value = “9S”
Debug.Print Crd.Value, Crd.Suit, Crd.Number
Crd.Value = “10D”
Debug.Print Crd.Value, Crd.Suit, Crd.Number
End Sub
And the results:
