Visual Basic Concepts
Public Collection Example: The House of Straw
To create the example, open a new project and insert two class modules. Draw five command buttons, a list box, two text boxes, and two labels on the form, as shown in Figure 9.13.
Figure 9.13 Employees collection example
The following table lists the property values you need to set for this example.
Object | Property | Setting |
Class module | Name | Employee |
Class module | Name | SmallBusiness |
Form | Caption | Employees Collection |
First command button | Caption Name |
Add cmdAddEmployee |
Second command button | Caption Name |
Delete cmdDeleteEmployee |
Third command button | Caption Name |
Refresh List cmdListEmployees |
Fourth command button | Caption Name |
Trouble cmdTrouble |
Fifth command button | Caption Name |
Close cmdClose |
First label control | Caption | Name |
Second label control | Caption | Salary |
First text box | Name Text |
txtName (blank) |
Second text box | Name Text |
txtSalary (blank) |
List Box | Name | lstEmployees |
In the Employee class module, add the following declarations and property procedures:
Option Explicit
' Properties of the Employee class.
Public Name As String
Public Salary As Long
' Private data for the write-once ID property.
Private mstrID As String
Property Get ID() As String
ID = mstrID
End Property
' The first time the ID property is set, the static
' Boolean is also set. Subsequent calls do nothing.
' (It would be better to raise an error, instead.)
Property Let ID(strNew As String)
Static blnAlreadySet As Boolean
If Not blnAlreadySet Then
blnAlreadySet = True
mstrID = strNew
End If
End Property
The ID property is the key for retrieving or deleting an Employee object from the collection, so it must be set once and never changed. This is accomplished with a Static Boolean variable that is set to True the first time the property is set. The property can always be read, because there is a Property Get.
In the SmallBusiness class module, add the following declaration. The collection object will be created the first time the Employees
variable is referred to in code.
Option Explicit
Public Employees As New Collection
The Form Does All the Work
All of the remaining code goes into the form module. Add the following declaration in the Declarations section.
Option Explicit
Public sbMain As New SmallBusiness
The code in the cmdEmployeeAdd_Click event adds a member to the collection.
Private Sub cmdEmployeeAdd_Click()
Dim empNew As New Employee
Static intEmpNum As Integer
' Using With makes your code faster and more
' concise (.ID vs. empNew.ID).
With empNew
' Generate a unique ID for the new employee.
intEmpNum = intEmpNum + 1
.ID = "E" & Format$(intEmpNum, "00000")
.Name = txtName.Text
.Salary = CDbl(txtSalary.Text)
' Add the Employee object reference to the
' collection, using the ID property as the key.
sbMain.Employees.Add empNew, .ID
End With
txtName.Text = ""
txtSalary.Text = ""
' Click the Refresh List button.
cmdListEmployees.Value = True
End Sub
The code in the cmdListEmployees_Click event procedure uses a For Each ... Next statement to add all the employee information to the ListBox control.
Private Sub cmdListEmployees_Click()
Dim emp As Employee
lstEmployees.Clear
For Each emp In sbMain.Employees
lstEmployees.AddItem emp.ID & ", " & emp.Name _
& ", " & emp.Salary
Next
End Sub
The cmdEmployeeDelete_Click event uses the Collection object's Remove method to delete the collection member currently selected in the ListBox control.
Private Sub cmdEmployeeDelete_Click()
' Check to make sure there's an employee selected.
If lstEmployees.ListIndex > -1 Then
' The first six characters are the ID.
sbMain.Employees.Remove _
Left(lstEmployees.Text, 6)
End If
' Click the Refresh List button.
cmdListEmployees.Value = True
End Sub
Add the following code to the Trouble button.
Private Sub cmdTrouble_Click()
' Say what!?
sbMain.Employees.Add Me
End Sub
The cmdClose_Click event closes the application. When you close projects that use objects, do so by unloading all the forms, to ensure that any Terminate event procedures in your class modules will get executed. By contrast, using the End statement stops a program abruptly, without executing Terminate events.
Private Sub cmdClose_Click()
Unload Me
End Sub
To add employees in the example, run the application, enter values in the two text boxes, and then choose the Add button. Add a few employees, and then experiment with the delete and list buttons.
Robust as a Straw House
This simple implementation is not very robust. Because the Employees property is just a public Collection object, you could inadvertently access it from anywhere in your program. Furthermore, the Add method of the Collection object doesn't do any type checking. For example, the code in the Trouble button's Click event blithely inserts an object reference to the form into the collection of employees.
Click the Trouble button, and notice that no error occurs. Now click the Refresh List button. When the For Each ... Next loop encounters the unexpected object type, it causes error 13, Type mismatch.
This is an example of the kind of error you're exposed to when you build an object model with public Collection objects. Objects can be added from anywhere in your project, and there's no guarantee that they'll be properly initialized. If a programmer clones the code to add an employee, and the original code is later changed, the resulting errors can be very difficult to track down.
For More Information The example begun in this topic is continued in "Private Collection Example: The House of Sticks."