Managing the Wizard

We'll build two classes to help us manage our wizard application. The first is a very simple class that will hold configuration data for each step. Then we'll create a class that will hold a collection of these "wizard step" objects. This class will manage the operation of the wizard process for us.

Insert a new class module and name it cStep. Add the following code:

Private m_iOrder As Integer Private m_iPage As Integer Private m_sCaption As String

Public Property Get Order() As Integer

Order = m_iOrder End Property

Public Property Let Order(newOrder As Integer)

m_iOrder = newOrder End Property

= m_oEmployee.Access.Building = m_oEmployee.Access.NetworkLevel = m_oEmployee.Access.RemoteYN = m_oEmployee.Access.ParkingSpot

Public Property Get Page() As Integer

Page = m_iPage End Property

Public Property Let Page(newPage As Integer)

m_iPage = newPage End Property

Public Property Get Caption() As String

Caption = m_sCaption End Property

Public Property Let Caption(newCaption As String)

m_sCaption = newCaption End Property

The HRWizard.xlms workbook contains a worksheet named UFormConfig. This worksheet holds information about each step in the wizard. This is where we can change the order of the steps or insert a new step. This class will hold that information for us. How will it do that when it (apparently) only holds information on one step?

Table 4-9 lists the cStep class's properties and describes them.

Table 4-9. cStep Properties Property Description

Order Holds the step's place in the wizard process's order

Page Holds the page number corresponding to a page in the MultiPage control

Caption The text to display on the currently active Page control

We are now going to design a class to manage the steps in the wizard. In that class, we'll create a collection of cStep objects that we'll use to keep track of where we are in the process and how many steps we have.

Insert a new class module and name it cStepManager. Add the following module-level variable declarations:

Dim m_oStep As cStep Dim m_iNumSettings As Integer Dim m_iNumSteps As Integer Dim m_iCurrentPage As Integer Dim m_iPreviousPage As Integer Dim m_iNextPage As Integer

Dim WithEvents m_oPreviousButton As MSForms.CommandButton Dim WithEvents m_oNextButton As MSForms.CommandButton Dim m_oWorksheet As Worksheet

We have a cStep object, m_oStep, that we'll be using to populate a collection of steps for the wizard, followed by a few Integer variables. These tell us how many steps we have and how many properties each step has, and they track the current, next, and previous steps based on where in the wizard the user might be.

We then have a couple variables that are set to the MSForms.CommandButton object type. These are declared WithEvents. We are going to let our cStepManager class maintain the state of these buttons. The WithEvents declaration lets us trap their Click event and act on it inside of our class. We will use the Click event to determine whether the button should be enabled based on where the user is in the wizard process. Add the following properties to cStepManager:

Public Property Get NumberOfSettings() As Integer

NumberOfSettings = m_iNumSettings End Property

Public Property Let NumberOfSettings(newNum As Integer)

m_iNumSettings = newNum End Property

'Worksheet Property: Gets/Sets the sheet containing the step information Public Property Get Worksheet() As Worksheet

Set Worksheet = m_oWorksheet End Property

Public Property Set Worksheet(newWorksheet As Worksheet)

Set m_oWorksheet = newWorksheet End Property

Public Property Get CurrentPage() As Integer

CurrentPage = m_iCurrentPage End Property

Public Property Let CurrentPage(newPage As Integer)

m_iCurrentPage = newPage End Property

Public Property Get PreviousPage() As Integer

PreviousPage = m_iCurrentPage - 1 End Property

Public Property Get NextPage() As Integer

NextPage = m_iCurrentPage + 1 End Property

Public Property Set PreviousButton(newPreviousBtn As MSForms.CommandButton)

Set m_oPreviousButton = newPreviousBtn End Property

Public Property Set NextButton(newNextBtn As MSForms.CommandButton)

Set m_oNextButton = newNextBtn End Property

Table 4-10 lists the cStepManager class's properties and describes them.

Table 4-10. cStepManager Properties

Property

Description

NumberOfSettings

Contains the number of columns in our step configuration worksheet,

UFormConfig

Worksheet

Tells the class where to find the information for each step of the wizard

CurrentPage

Stores the value of the current step in the wizard

PreviousPage

Calculated based on the CurrentPage property; returns the value of the

preceding step in the wizard

NextPage

Calculated based on the CurrentPage property; returns the value of the

next step in the wizard

PreviousButton

Stores a pointer to the button on the UserForm that will navigate to the

preceding step in the wizard

NextButton

Stores a pointer to the button on the UserForm that will navigate to the

next step in the wizard

We need to add one more property to our class. This read-only property will contain the collection of cStep objects that hold the information on each step of the wizard.

The PageSettings property will store this collection for us. It returns a Collection object that we will use in the client code behind our HRWizard UserForm. The code for the PageSettings property looks like this:

Public Property Get PageSettings() As Collection

Dim colReturn As Collection

Dim numrows As Integer

Dim row As Integer

Dim col As Integer

Dim sKey As String

Set colReturn = New Collection numrows = m_oWorksheet.Cells(Rows.Count, 1).End(xlUp).row For row = 2 To numrows Set m_oStep = New cStep For col = 1 To m_iNumSettings Select Case col Case 1

m_oStep.Order = m_oWorksheet.Cells(row, col).Value sKey = CStr(m_oStep.Order) Case 2

m_oStep.Page = m_oWorksheet.Cells(row, col).Value

Case 3

m_oStep.Caption = m_oWorksheet.Cells(row, col).Value End Select Next col colReturn.Add m_oStep, sKey Next row m_iNumSteps = colReturn.Count Set PageSettings = colReturn End Property

The first thing we're doing is getting the number of rows in the used area on the worksheet:

numrows = m_oWorksheet.Cells(Rows.Count, 1).End(xlUp).Row

Note Although Excel's Worksheet object has a Rows.Count method, we cannot use that here (m_oWorksheet.Rows.Count). That would return the total number of rows in the worksheet, which would not only give us an incorrect value, but would also overflow our Integer variable.

Next we're using the number-of-used-rows value just returned in a loop that will populate the collection of cStep objects. Let's look at that code:

For row = 2 To numrows Set m_oStep = New cStep For col = 1 To m_iNumSettings Select Case col Case 1

m_oStep.Order = m_oWorksheet.Cells(row, col).Value sKey = CStr(m_oStep.Order) Case 2

m_oStep.Page = m_oWorksheet.Cells(row, col).Value Case 3

m_oStep.Caption = m_oWorksheet.Cells(row, col).Value End Select Next col colReturn.Add m_oStep, sKey Next row

The first thing we do is instantiate a new cStep object. Then we move into an inner loop to walk through the columns on the configuration worksheet, and assign them to the corresponding property in the internal cStep object. The m_iNumSettings value will have already been set via the NumberOfSettings property before this code is run.

Finally, we add the cStep object to our internal collection, colReturn, passing in the Order value as the key in the collection.

Note It is important to note the first line of code inside the outer loop, Set m_oStep = New cStep.If this is omitted, you will end up with four identical cStep objects in your collection (all containing the data from the last configuration item read from the worksheet). This is because the m_oStep object reference is still active, so every call to it modifies any existing instances. By using the New keyword, you create a new, separate instance of the object.

The last thing we're doing is setting the internal m_iNumSteps variable that is used to track our Previous and Next CommandButton availability, and finally we're returning the collection:

m_iNumSteps = colReturn.Count Set PageSettings = colReturn

Now we will turn our attention to our PreviousButton and NextButton properties. You'll recall that our internal variables for these properties were declared WithEvents. When you declare an object WithEvents, you have access to that object's event code via the VB code window's Object box, as shown in Figure 4-27.

(General)

-

(General)

Class

m oNextButton

m ┬ęPreviousButton

Figure 4-27. The Object box lists objects declared WithEvents.

Select m_oNextButton and m_oPreviousButton from the Object box to insert their event-handler stubs into the class module. Add the following code to each:

Private Sub m_oNextButton_Click()

m_oNextButton.Enabled = Me.NextPage <> m_iNumSteps + 1 m_oPreviousButton.Enabled = Me.PreviousPage <> 0 End Sub

Private Sub m_oPreviousButton_Click()

m_oPreviousButton.Enabled = Me.PreviousPage <> 0 m_oNextButton.Enabled = Me.NextPage <> m_iNumSteps + 1 End Sub

This code controls whether each button is enabled based on the value of the NextPage or PreviousPage properties of our cStepManager class. We'll add one more method to initialize the buttons when the class is first created in client code:

Public Sub HandleControls()

m_oPreviousButton.Enabled = Me.PreviousPage <> 0 m_oNextButton.Enabled = Me.NextPage <> m_iNumSteps + 1 End Sub

We've created a fair amount of code here, all stored in objects across many class modules. By compartmentalizing our functionality, we've made our job of maintaining this code very easy. If we need to bind lists to data sources we may not be currently handling, it is trivial to add a new method to the cListManger class. If we need to add a screen to our process, we design a new page on the MultiPage control, create a new class to store that screen's information, and add a row to our configuration table.

Your Class Modules folder in the Project Explorer should look like Figure 4-28 after all the classes have been added and coded.

Figure 4-28. HRWizard class module list
0 0

Post a comment