Visual Basic Concepts

Public Collection Example: The House of Straw

See Also

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."