Larry W Jordan Jr.
Derik Harris
Microsoft Corporation
Created: July 15, 1996
Revised: August 7, 1996
Larry W Jordan Jr. is a Senior Microsoft Access support engineer. His main focus is VBA, wizard and add-in development and Visual SourceSafe integration.
Derik Harris is a Senior Microsoft Access content engineer. His primary responsibility is writing, editing, and publishing Microsoft Access related material for the Microsoft Knowledge Base and the Microsoft Web site.
Click to open or copy the WIZDESGN project files.
The development of Microsoft® Access add-ins and wizards provides developers and IS professionals with a robust method to implement custom solutions that use the power of Microsoft Access and simplify the steps involved in completing complex tasks. Microsoft Access uses wizards to help users design forms, reports, queries, and other design tasks that would involve many steps to complete.
The Microsoft Access development community and Microsoft's own wizard designers have developed common approaches to the basic design of wizards and how to navigate the various pages used to gather information from the user. This document outlines the basic design of a wizard and discusses how to create a generic template that you can use again and again when you create new wizards and add-ins.
The Main Host form is designed to act as your main interface form for displaying the various pages of your wizard. The form uses an unbound Object Frame to load your wizard pages as subforms into the SourceObject property of the control.
For example, to load the first page of your subform when the Main Host form loads:
Private Sub Form_Load()
On Error GoTo Form_Load_Err
' Load the first page.
intWhatPage = 1
Call SetupNavButtons
Me!frmPage.SourceObject = "samp_WizardPage1"
Form_load_End:
Exit Sub
Form_Load_Err:
MsgBox Err.Description, vbExclamation, WizAppName
End Sub
This makes the Main Host form "lightweight" in nature, and almost all of the code and information gathering is contained within the context of the individual pages, which promotes ease of maintenance and promotes code encapsulation.
The standard components of the Main Host form are as follows.
The Main Host form has a set of standard navigation buttons that guide the user through the information-gathering process and are featured on all multiple-page wizards designed for Microsoft Access for Windows® 95. When you use the same design, you increase the intuitiveness of your wizard and make it easier for users to concentrate on the functionality of your custom add-in.
In the wizard template example, the Help About button will show an About box. A simple form has been created to indicate information, such as the registered user and the company that made the wizard.
Private Sub btnHelpAbout_Click()
' display help about box...
DoCmd.OpenForm "samp_WizardAbout", , , , , , acDialog
End Sub
The Cancel button closes the wizard and performs any clean-up tasks. Your clean up should take into account any allocation of memory issues that may be implemented using Windows API calls, object references that retain scope and lifetime, preconnections to ODBC data sources, and so on.
Private Sub btnCancel_Click()
On Error GoTo btnCancel_Err
DoCmd.Close acForm, Me.Name, Save:=False
btnCancel_Exit:
Exit Sub
btnCancel_Err:
MsgBox Err.Description, vbInformation, WizAppName
Resume btnCancel_Exit
End Sub
The Back button is used to navigate to previous pages in the wizard. You keep track of the currently active page by referencing a variable intWhatPage. Based upon the current value of the intWhatPage variable, you can decide if you want to return to the previous page.
Dim intWhatPage As Integer
Private Sub btnBack_Click()
Dim Msg As String ' For error handling.
On Local Error GoTo btnBack_Click_Err
Select Case intWhatPage
Case 2
' Increment page number.
intWhatPage = intWhatPage - 1
Call SetupNavButtons
Me!frmPage.SourceObject = "samp_WizardPage" & Format$(intWhatPage)
End Select
btnBack_Click_End:
Exit Sub
btnBack_Click_Err:
Msg = "Error #: " & Format$(Err.Number) & vbCrLf
Msg = Msg & Err.Description
MsgBox Msg, vbInformation, "btnBack_Click"
Resume btnBack_Click_End
End Sub
The code in the btnBack routine demonstrates that if the current page equals 2, it is possible to return to the page and to change information. How you decide to implement your wizard's rules regarding navigation is up to you and to the complexity of your wizard design.
The Next button navigates forward through your wizard pages and runs the code associated with the user's selection. This method is somewhat more complex that anything else that has been examined up to this point; therefore, what follows is a more in-depth look.
Dim intWhatPage As Integer
Private Sub btnNext_Click()
Dim Msg As String ' For error handling.
On Local Error GoTo btnNext_Click_Err
Dim f As Form
Select Case intWhatPage
Case 1, 2
' Execute the GoNext/btnNext form method
Set f = Me!frmPage.Form
If f.GoNext() Then
' Increment page number.
intWhatPage = intWhatPage + 1
Call SetupNavButtons
Me!frmPage.SourceObject = "samp_WizardPage" & _
Format$(intWhatPage)
End If
End Select
btnNext_Click_End:
Exit Sub
btnNext_Click_Err:
Msg = "Error #: " & Format$(Err.Number) & vbCrLf
Msg = Msg & Err.Description
MsgBox Msg, vbInformation, "btnNext_Click"
Resume btnNext_Click_End
End Sub
The code in the btnNext routine demonstrates that if the intWhatPage variable equals 1 or 2, it is possible to navigate to the next page. The sample shown here implements a total of two information-gathering pages and a final "Finished" page (in this case, page 3). In the actual code behind forms 1 and 2, a Public function GoNext is defined (this is covered in detail in the section of this document describing the individual pages of the wizard). The GoNext method is called prior to executing the loading of the next wizard page and will allow the SubForm object to save values and complete other tasks associated with that wizard page.
Then a function is called that handles the behavior and setting associated with the navigation buttons of the main wizard host form.
Private Sub SetupNavButtons()
' Enable/disable appropriate parent form buttons.
DoCmd.GoToControl "btnCancel"
Select Case intWhatPage
Case 1 ' Sample text entry.
Me!btnBack.Enabled = False
Me!btnFinish.Enabled = False
Me!btnNext.Enabled = True
DoCmd.GoToControl "btnNext"
Case 2 ' Confirm.
Me!btnBack.Enabled = True
Me!btnFinish.Enabled = True
Me!btnNext.Enabled = False
DoCmd.GoToControl "btnFinish"
Case 3 ' Finished.
Me!btnBack.Enabled = False
Me!btnFinish.Enabled = False
Me!btnNext.Enabled = False
End Select
End Sub
The SetupNavButtons routine will enable and set focus to the buttons, based on what particular wizard page is currently active. The function should be called when moving forward and to previous pages in your wizard.
The Finish button completes the task your wizard is designed to automate. The button should be enabled from the SetupNavButtons function only when the user has supplied enough information that would enable your wizard to complete successfully.
Private Sub btnFinish_Click()
Dim Msg As String ' For error handling.
On Local Error GoTo btnFinish_Click_Err
Dim f As Form
' Execute the GoNext/btnNext form method.
Set f = Me!frmPage.Form
If f.GoNext() Then
' Increment page number.
intWhatPage = intWhatPage + 1
Call SetupNavButtons
Me!frmPage.SourceObject = "samp_WizardPage" & Format$(intWhatPage)
Me!btnCancel.Caption = "&Close"
Else
' Error.
Msg = "Unable to complete wizard processing of Sales Data!"
MsgBox Msg, vbCritical, "Terminating..."
DoCmd.Close acForm, Me.Name
End If
btnFinish_Click_End:
Exit Sub
btnFinish_Click_Err:
Msg = "Error #: " & Format$(Err.Number) & vbCrLf
Msg = Msg & Err.Description
MsgBox Msg, vbInformation, "btnFinish_Click"
Resume btnFinish_Click_End
End Sub
The code in the btnFinish routine assumes that the Finish button is enabled only when the wizard has navigated to page 2 and that the code in the GoNext method of page 2 will complete the wizard's task. You could just as easily execute the GoNext method on whatever page you are on and then execute a Public function to complete the wizard.
The forms used in your wizard to gather the individual steps as the users navigates the wizard are implemented as subforms in the Main Host form container and are referred to as the "pages" of your wizard.
In order for your individual wizard pages to look correct when hosted by the main form, you should set the following properties of the form to these values.
Property | Setting/Value |
Caption | <blank> Do not enter an value for the caption of the form. |
AllowFilters | No |
ViewsAllowed | Form |
ScrollBars | Neither |
RecordSelectors | No |
NavigationButtons | No |
DividingLines | No |
Min/MaxButtons | None |
The settings are arbitrary and, depending on the needs of your wizard, represent the basic items that would be set to implement a clean page design.
The most common size used when creating the individual pages is 3 inches in height by 5 inches in width. The Main Host form implements the subform Object Frame to fit these dimensions. You can size your wizard any way you want, but keep the following considerations in mind when choosing a size.
When you design the pages for your wizard, it is important to focus on how well the pages communicate the request for information from the user. A general rule is that a single wizard page should be dedicated to gathering a single piece of relevant information. The text should be concise and self explanatory. A wizard is designed to make a user's completion of a complicated task easier. Therefore, you should ensure that the user does not have to refer to complicated written instructions or to online Help.
Using graphics to aid the user in page context is a great way to make your wizard visually appealing and intuitive. There are some general rules for sizing and graphic placement on your pages.
If you have a graphic that is used on each page, whether it changes or stays the same, try to keep that graphic in the same place as the user navigates the form.
Size large graphics by height (that is, from top to bottom) instead of from left to right. This improves the readability of the wizard page and is more natural for the user.
Each page of your wizard is loaded into the Main Host form container, the user populates the various information on the page, and then clicks the Next button. The code associated with the Next button on the host form will then execute the GoNext function contained in the current wizard page. A basic GoNext function would look as follows.
Public Function GoNext() As Boolean
On Error GoTo GoNext_Err
Dim Msg As String
Msg = "Executing the GoNext() method of Page #1…"
MsgBox Msg, vbInformation, WizAppName
GoNext = True
GoNextEnd:
Exit Function
GoNext_Err:
MsgBox Err.Description, vbInformation, WizAppName
Resume GoNextEnd
End Function
The code associated with the Main Host form's Next button would call this function by setting a form reference and executing the Public method of the form:
Dim f As Form, boolResult As Boolean
' Execute the GoNext/btnNext form method
Set f = Me!frmPage.Form
boolResult = f.GoNext()
Set f = Nothing
You should design the Host Main form and the associated wizard pages implemented as subforms in such a way as to make the debugging and addition of features simple to implement. This overview has provided you with the basic ideas that you need to accomplish this.