| < Day Day Up > |
|
The class module contains all of the properties, methods, and events associated with the class’s interface, along with any local variables, functions, and subroutines used by the class.
You can add a class module to your VBA program by choosing Insert, Class Module from Visual Basic’s main menu. The initial name of the class is formed by appending a unique number to the word Class. Thus, the first class you create will be Class1, and the second will be Class2.
Because a name like Class1 isn’t very descriptive, you should always give the class a more meaningful name. To change the name of a class, select the class in the Project Explorer, and then go to the Properties window and change the Name property associated with this class. (See Figure 14-1.)
Figure 14-1: Use the Properties Window to change the Name property associated with the class.
There are two different types of properties: public class-level variables and property routines. Class-level variables must be defined before any subroutines, functions, or property routines are defined. In practical terms, this means that all of your class-level variables should be located at the start of the class module.
For example, the following line defines a simple property:
Public ProductId As Long
Warning | Simple properties can’t be used to return an array, a fixed-length string, a constant, or a complex structure created with a Type statement. If you need a property that returns any of these things, create the appropriate private class-level variable and then create a property routine that performs the same action. For example, you can create a property routine that accepts a series of parameters that allow the routine to look like an array. Likewise, you can create a property routine that accepts and returns fixed-length strings or complex structures. |
There are three different property routines: Get, Set, and Let. The Property Get routine always returns a value. Here’s a simple example that references a private class-level variable named TheProductName.
Public Property Get ProductName As String
ProductName = TheProductName
End Property
The Property Let and Property Set routines are called to save a value into the property. The Property Let statement is used when the property is a normal variable, whereas the Property Set statement is used when the property is an object.
The corresponding Property Let routine for the ProductName property would look like this:
Public Property Let ProductName(value As String)
TheProductName = value
End Property
Note | The only difference between a Property Set statement and a Property Let statement is that you use a Property Set statement whenever you are dealing with objects, whereas you would normally assign values using the Set statement. Likewise, you would use the Property Let statement whenever you are returning any other value. |
Property routines may also have one or more parameters. Typically, you would use parameters with a property routine if you wanted to simulate an array. For example the following code fragment declares a private class-level variable named MyNames, which is an array of 100 Strings. The code fragment also includes two property routines that make the property appear as an array.
Private MyNames (99) As String
Public Property Get NameArray(index As Long) As String
NameArray = MyNames(index)
End Property
Public Property Let NameArray (index As Long, value as String)
MyNames = value
End Property
Note | You can specify as many parameters as you wish for the property routines. However, they must be identical between the Get and Let/Set routines, except for the very last parameter in the Let/Set routine, which contains the value for the property. |
Someone using the class might access the property like this:
MyObject.NameArray (10) = “Item 10 in the array”
Or like this:
MyVar = MyObject.NameArray (10)
Tip | Property Routines and Parameters |
If you have defined a set of property routines to manipulate a complex structure created with a Type statement, you might run into problems when you attempt to assign a value directly to one of the elements in the structure in a single statement. Suppose you have the following statements in your class:
Public Type MapCoordinateType
Latitude As Single
Longitude As Single
End Type
Private MyMapCoordinate As MapCoordinateType
Public Property Get MapCoordinate As MapCoordinateType
MapCoordinate = MyMapCoordinate
End Property
Public Property Let MapCoordinate (value as MapCoordinateType)
MapCoordinate = value
End Property
Now, assuming that you instantiated the class as MicrosoftWay, you can reference the Lattitude value like this:
TempLatitude = MicrosoftWay.MapCoordinate.Latitude
Because this works, you might be tempted to use the following statements:
MicrosoftWay.MapCoordinate.Latitude = 47.63
MicrosoftWay.MapCoordinate.Longitude = 122.13
However, if you use them, you’ll find that the MicrosoftWay.MapCoordinate.Latitude is zero!
Although this seems like a bug in Visual Basic, it really isn’t. Visual Basic is working properly. When you reference the Latitude element in the first statement, Visual Basic creates a temporary MapCoordinateType variable and sets the Latitude value to 47.63. Because the temporary variable is filled with zeros when it’s allocated and a value isn’t explicitly assigned to Longitude, it contains a value of zero. Thus, when the MapCoordinate Let routine is called, with the temporary variable that Visual Basic created, Latitude element will be set to 47.63 and Longitude element will be set to zero.
The same situation occurs when you execute the second statement. Because a value wasn’t assigned to Latitude in the temporary variable, the previous value of 47.63 is overwritten by zero, which undoes the change made in the first statement.
There are a couple of ways to avoid this problem. The first and probably best way is to create a class rather than use a Type statement. However, if you really want to use the Type statement, you should create a temporary variable of your own, assign the values to the structure, and then assign the structure to the property like this:
Dim TempVar As MapCoordinateType
TempVar.Latitude = 47.63
TempVar.Longitude = 122.13
MicrosoftWay.MapCoordinate = TempVar
Methods are simply public functions and subroutines. They are free to accept any set of parameters and return any type of value. They can also access any class-level variable whether it’s public or private, along with any property routine.
For example, assume that the class held information about a particular product from the Garden Company. You might create a function that computes the discounted price like this:
Public Function DiscountedPrice (Discount As Currency) As Currency
If Discount >= 0 and Discount < 1.0 Then
DiscountedPrice = MyListPrice * (1 - Discount)
Else
DiscountedPrice = MyListPrice
End If
End Function
This routine verifies that the input parameter is valid by making sure that it’s in the range of 0 to 1 and then computes the discount price accordingly. If the discount value is illegal, the list price of the item is returned.
Tip | Saving Cycles |
Events can be very useful in a class, but you can’t assume that everyone that uses your class will actually use the events. Therefore, if you decide to use events in your class, you need to ensure that the class will continue to function if the user doesn’t respond to any of the events.
The Event statement is used to define an event. For all practical purposes, this is effectively a subroutine statement minus the code. This definition is necessary because it identifies the parameters that will be passed to the event. The event definition is used by the by the Visual Basic compiler to ensure that the number of parameters and the type of the parameters match the definition.
Note | Although you can specify nearly any type of parameter you can use in a subroutine, events can’t have named arguments, optional parameters, or ParamArray arguments. |
A sample event definition might look like this:
Event DiscountError (value As Currency, Msg As String)
Within the class, you would use a RaiseEvent statement to trigger an event in the user program. Following the RaiseEvent statement name is the name of the event, followed by a list of values that will be passed to the user program. For example, this statement passes two values back to the calling program.
RaiseEvent DiscountError(discount, “Illegal discount amount. “)
To use events in an application, the WithEvents keyword must be included when the object is defined. Without the WithEvents keyword, all events will be ignored. The following statement shows how you would declare an object with events:
Dim WithEvents MyObject As GardenCompany
Although you need not mark your subroutines or functions as Private in a class, you should note that without the Private keyword, any subroutine or function will default to Public. In many situations, this might not be a serious problem, especially if you are the one person using the class. However, if you plan to share your class with others, you might find them relying on a routine where you accidentally omitted the Private keyword, which means you can’t change the definition of the routine without impacting all the programs that use it.
VBA defines two special events for all classes, the Initialize event and the Terminate event.
The Class_Initialize event contains code that will be run when an object is created based on this class. This event is useful for initializing class-level variables including executing any Set New statements needed to create any objects that are needed by this object.
Set ObjectVar = New MyClass
The Class_Terminate event contains code that will be run just before an object is destroyed. This event is an ideal place to destroy any objects that are local to the class by setting them to Nothing using code like this:
Set ObjectVar = Nothing
Note | The Class_Initialize and Class_Terminate events are fired only when the actual object is created or destroyed. Merely setting one object variable to another will not trigger the Class_Initialize event. If two or more object variables point to the same object, merely setting one object variable to Nothing will not trigger the Class_Terminate event. |
Sometimes you’ll find yourself in a situation where you have a local variable and a class- level variable with the same name. This frequently happens when you want to give a parameter in a method the same name as a property. To differentiate between a class-level variable and a local variable or parameter, you can prefix the class level variable with Me. as in the following example:
If Me.Name <> Name Then
In this statement, the variable Me.Name refers to a class-level variable, whereas the unqualified variable Name refers to a local variable or parameter.
Tip | Identifying Things That Belong to Me |
| < Day Day Up > |
|