You can't use Excel very long without being exposed to dialog boxes. Excel, like most Windows programs, uses dialog boxes to obtain information, clarify commands, and display messages. If you develop VBA macros, you can create your own dialog boxes that work very much like those that are built into Excel. These dialog boxes are known as UserForms.
Some macros that you create behave the same every time that you execute them. For example, you may develop a macro that enters a list of your sales regions into a worksheet range. This macro always produces the same result and requires no additional user input. You may develop other macros, however, that perform differently under different circumstances or that offer options for the user. In such cases, the macro may benefit from a custom dialog box.
The following is an example of a simple macro that makes each cell in the selected range uppercase (but skips cells that have a formula). The procedure uses VBA's built-in StrConv function:
Sub ChangeCase()
For Each cell In Selection
If Not cell.HasFormula Then
cell.Value = StrConv(cell.Value, vbUpperCase)
End If
Next Cell
End Sub
This macro is useful, but it can be improved. For example, the macro would be more helpful if it could also change the cells to lowercase or proper case (only the first letter of each word is uppercase). This modification is not difficult to make, but if you make this change to the macro, you need some method of asking the user what type of change to make to the cells. The solution is to present a dialog box like the one shown in Figure 41.1. This dialog box is a UserForm that was created by using the Visual Basic Editor (VBE), and it's displayed by a VBA macro.
Another solution is to develop three macros—one for each type of text case change. Combining these three operations into a single macro and using a UserForm is a more efficient approach, however. We discuss this example, including how to create the UserForm, in “Looking at Another UserForm Example” later in the chapter.
After you get the hang of it, developing UserForms isn't difficult. But sometimes using the tools that are built into VBA is easier. For example, VBA includes two functions (InputBox and MsgBox) that enable you to display simple dialog boxes without having to create a UserForm in the VBE. You can customize these dialog boxes in some ways, but they certainly don't offer the number of options that are available in a UserForm.
The InputBox function is useful for obtaining a single input from the user. A simplified version of the function's syntax follows:
InputBox(prompt[,title][,default])
The elements are defined as follows:
The following is an example of how you can use the InputBox function:
CName = InputBox("Customer name?","Customer Data")
When this VBA statement is executed, Excel displays the dialog box shown in Figure 41.2. Notice that this example uses only the first two arguments for the InputBox function and does not supply a default value. When the user enters a value and clicks OK, the value is assigned to the variable CName. Your VBA code can then use that variable.
The VBA MsgBox function is a handy way to display information and to solicit simple input from users. We use the VBA MsgBox function in many of this book's examples to display a variable's value. A simplified version of the MsgBox syntax is as follows:
MsgBox(prompt[,buttons][,title])
The elements are defined as follows:
You can use the MsgBox function by itself or assign its result to a variable. If you use it by itself, don't include parentheses around the arguments. The following example displays a message and does not return a result:
Sub MsgBoxDemo()
MsgBox "Click OK to continue"
End Sub
Figure 41.3 shows how this message box appears.
To get a response from a message box, you can assign the result of the MsgBox function to a variable. The following code uses some built-in constants (described in Table 41.1) to make it easier to work with the values that are returned by MsgBox:
Sub GetAnswer()
Ans = MsgBox("Continue?", vbYesNo)
Select Case Ans
Case vbYes
' ...[code if Ans is Yes]...
Case vbNo
' ...[code if Ans is No]...
End Select
End Sub
When this procedure is executed, the Ans variable contains a value that corresponds to vbYes or vbNo. The Select Case statement determines the action to take based on the value of Ans.
You can easily customize your message boxes because of the flexibility of the buttons argument. Table 41.1 lists the most common built-in constants that you can use for the buttons argument. You can specify which buttons to display, whether an icon appears, and which button is the default.
TABLE 41.1 Constants Used in the MsgBox Function
Constant | Value | Description |
---|---|---|
vbOKOnly | 0 | Displays OK button |
vbOKCancel | 1 | Displays OK and Cancel buttons |
vbAbortRetryIgnore | 2 | Displays Abort, Retry, and Ignore buttons |
vbYesNoCancel | 3 | Displays Yes, No, and Cancel buttons |
vbYesNo | 4 | Displays Yes and No buttons |
vbRetryCancel | 5 | Displays Retry and Cancel buttons |
vbCritical | 16 | Displays Critical Message icon |
vbQuestion | 32 | Displays Query icon (a question mark) |
VBExclamation | 48 | Displays Warning Message icon |
vbInformation | 64 | Displays Information Message icon |
vbDefaultButton1 | 0 | First button is default |
vbDefaultButton2 | 256 | Second button is default |
vbDefaultButton3 | 512 | Third button is default |
The following example uses a combination of constants to display a message box with a Yes button and a No button (vbYesNo) and a question mark icon (vbQuestion). The second button (the No button) is designated as the default button (vbDefaultButton2), which is the one that is executed if the user presses Enter. For simplicity, these constants are assigned to the Config variable, and Config is then used as the second argument in the MsgBox function.
Sub GetAnswer()
Config = vbYesNo + vbQuestion + vbDefaultButton2
Ans = MsgBox("Process the monthly report?", Config)
If Ans = vbYes Then RunReport
If Ans = vbNo Then Exit Sub
End Sub
Figure 41.4 shows how this message box appears when the GetAnswer procedure is executed. If the user clicks the Yes button, the routine executes the procedure named RunReport (which is not shown). If the user clicks the No button (or presses Enter), the procedure is ended with no action. Because the title argument was omitted in the MsgBox function, Excel uses the default title (Microsoft Excel).
The procedure that follows is another example of using the MsgBox function:
Sub GetAnswer2()
Msg = "Do you want to process the monthly report?"
Msg = Msg & vbNewLine & vbNewLine
Msg = Msg & "Processing the monthly report will take approximately "
Msg = Msg & "15 minutes. It will generate a 30-page report for all "
Msg = Msg & "sales offices for the current month."
Title = "XYZ Marketing Company"
Config = vbYesNo + vbQuestion
Ans = MsgBox(Msg, Config, Title)
If Ans = vbYes Then RunReport
If Ans = vbNo Then Exit Sub
End Sub
This example demonstrates an efficient way to specify a longer message in a message box. A variable (Msg) and the concatenation operator (&) are used to build the message in a series of statements. vbNewLine is a constant that represents a line break character. (Using two line breaks will insert a blank line.) The title argument is also used to display a different title in the message box. The Config variable stores the constants that generate Yes and No buttons and a question mark icon. Figure 41.5 shows how this message box appears when the procedure is executed.
The InputBox and MsgBox functions are adequate for many situations, but if you need to obtain more information, you need to create a UserForm.
The following is a list of the general steps that you typically take to create a UserForm:
The following sections offer more details on creating a UserForm.
To create a dialog box, you must first insert a new UserForm in the VBE. To activate the VBE, choose Developer ➪ Code ➪ Visual Basic (or press Alt+F11). Make sure that the correct workbook is selected in the Project window and then choose Insert ➪ UserForm. The VBE displays an empty UserForm, as shown in Figure 41.6. When you activate a UserForm, the VBE displays the Toolbox, which is used to add controls to the UserForm.
The Toolbox, also shown in Figure 41.6, contains ActiveX controls that you can add to your UserForm. If the Toolbox is not visible, choose View ➪ Toolbox.
When you move the mouse pointer over a control in the Toolbox, the control's name appears. To add a control, select the control in Toolbox and either click in the form to get the default size or drag the desired size onto the form. After adding a control, you can move it or change its size.
Table 41.2 lists the Toolbox controls.
TABLE 41.2 Toolbox Controls
Control | Description |
---|---|
Select Objects | Lets you select other controls by dragging |
Label | Adds a label (a container for text) |
TextBox | Adds a text box, which allows the user to type text |
ComboBox | Adds a combo box (a drop-down list) |
ListBox | Adds a list box, which allows the user to select an item from a list |
CheckBox | Adds a check box to control Boolean options |
OptionButton | Adds an option button to allow the user to select from multiple options |
ToggleButton | Adds a toggle button to control Boolean options |
Frame | Adds a frame (a container for other objects) |
CommandButton | Adds a command button (a clickable button) |
TabStrip | Adds a tab strip (a container for other objects) |
MultiPage | Adds a multipage control (a container for other objects) |
ScrollBar | Adds a scrollbar, which allows the user to specify a value by dragging a bar |
SpinButton | Adds a spin button, which allows the user to specify a value by clicking up or down arrows |
Image | Adds a control that can contain an image |
Every control that you add to a UserForm has several properties that determine the way the control looks and behaves. You can change some of these properties (such as Height and Width) by clicking and dragging the control's border. To change other properties, use the Properties window.
To display the Properties window, choose View ➪ Properties Window (or press F4). The Properties window displays a list of properties for the selected control. (Each type of control has a different set of properties.) If you click the UserForm itself, the Properties window displays properties for the form. Figure 41.7 shows the Properties window for a CommandButton control.
To change a property, select the property in the Properties window and then enter a new value. Some properties (such as BackColor) let you select a value from a list. The top of the Properties window contains a drop-down list of all the controls on the form. You can also click a control to select it and display its properties.
When you set properties via the Properties window, you're setting properties at design time. You can also use VBA to change the properties of controls while the UserForm is displayed (that is, at runtime).
A complete discussion of all the properties is well beyond the scope of this book—and it would indeed be dull reading. To find out about a particular property, select it in the Properties window and press F1 for help.
When you insert a UserForm, that form can also hold VBA Sub procedures to handle the events that are generated by the UserForm. An event is something that occurs when the user manipulates a control. For example, clicking a button causes a Click event. Selecting an item in a list box control also triggers a Click event, as well as a Change event. To make a UserForm useful, you must write VBA code to do something when an event occurs.
Event handler procedures have names that combine the control with the event. The general form is the control's name, followed by an underscore and then the event name. For example, the procedure that is executed when the user clicks a button named MyButton is MyButton_Click. You don't have to remember how they're named, however. Just right-click the control and choose View Code. The Private Sub and End Sub keywords will be inserted for you, and the correct name of one of the control's events will already be constructed. Use the drop-downs at the top of the code pane to change the event from the default.
Figure 41.8 shows the result of right-clicking on a CommandButton control named CommandButton1 and choosing View Code. The CommandButton's default event, the Click event, is inserted into the code module. The figure also shows some of the other events available using the code pane's drop-down.
You also need to write a procedure to display the UserForm. You use the Show method of the UserForm object. The following procedure displays the UserForm named UserForm1:
Sub ShowDialog()
UserForm1.Show
End Sub
This procedure should be stored in a regular VBA module (not the code module for the UserForm). If your VB project doesn't have a regular VBA module, choose Insert ➪ Module to add one.
When the ShowDialog procedure is executed, the UserForm is displayed. What happens next depends on the event handler procedures that you create.
The preceding sections are, admittedly, rudimentary. The following sections demonstrate, in detail, how to develop a UserForm. This example is rather simple. The UserForm displays a message to the user—something that can be accomplished more easily by using the MsgBox function. However, a UserForm gives you more flexibility in terms of formatting and layout of the message.
If you're following along on your computer, start with a new workbook. Then follow these steps:
Property | Change to |
---|---|
Name | AboutBox |
Caption | About This Workbook |
2 - fmTextAlignCenter
Property | Change to |
---|---|
Name | OKButton |
Caption | OK |
Default | True |
At this point, the UserForm has all the necessary controls. What's missing is a way to display the UserForm. While you're developing the UserForm, you can press F5 to display it and see how it looks. To close the UserForm, click the Close button (X) in the dialog box title bar.
This section explains how to write a VBA procedure to display the UserForm when Excel is active:
Sub ShowAboutBox()
AboutBox.Show
End Sub
If you click the OK button, notice that it doesn't close the UserForm as you may expect. This button needs to have an event handler procedure for it to do anything when it's clicked. To dismiss the UserForm, click the Close button (X) in its title bar.
An event handler procedure is executed when an event occurs. In this case, you need a procedure to handle the Click event that's generated when the user clicks the OK button.
Unload Me
This statement simply dismisses the UserForm by using the Unload statement. The complete event handler procedure is as follows:
Private Sub OKButton_Click()
Unload Me
End Sub
After you add the event procedure, clicking the OK button closes the form.
This example is an enhanced version of the ChangeCase procedure presented at the beginning of the chapter. Recall that the original version of this macro changes the text in the selected cells to uppercase characters. This modified version asks the user what type of case change to make: uppercase, lowercase, or proper case (initial capitals).
This UserForm needs one piece of information from the user: the type of change to make to the text. Because only one option can be selected, OptionButton controls are appropriate. Start with an empty workbook and follow these steps to create the UserForm:
Property | Change to |
---|---|
Name
| UChangeCase |
Caption
| Change Case |
Property | Change to |
---|---|
Name
| OKButton |
Caption
| OK |
Default
| True |
Property | Change to |
---|---|
Name
| CancelButton |
Caption
| Cancel |
Cancel
| True |
Property | Change to |
---|---|
Name
| OptionUpper |
Caption
| Upper Case |
Value
| True |
Property | Change to |
---|---|
Name
| OptionLower |
Caption
| Lower Case |
Property | Change to |
---|---|
Name
| OptionProper |
Caption
| Proper Case |
The next step is to create two event handler procedures: one to handle the Click event for the CancelButton CommandButton and the other to handle the Click event for the OKButton CommandButton. Event handlers for the OptionButton controls are not necessary. The VBA code can determine which of the three OptionButton controls is selected, but it does not need to react when the choice is changed—only when OK or Cancel is clicked.
Event handler procedures are stored in the UserForm code module. To create the procedure to handle the Click event for the CancelButton, follow these steps:
Unload Me
That's all there is to it. The following is a listing of the entire procedure that's attached to the Click event for the CancelButton:
Private Sub CancelButton_Click()
Unload Me
End Sub
This procedure is executed when the CancelButton is clicked. It consists of a single statement that unloads the form.
Next, add the code to handle the Click event for the OKButton control. Follow these steps:
Private Sub OKButton_Click()
' Exit if a range is not selected
If TypeName(Selection) <> "Range" Then Exit Sub
' Upper case
If Me.OptionUpper.Value Then
For Each cell In Selection
If Not cell.HasFormula Then
cell.Value = StrConv(cell.Value, vbUpperCase)
End If
Next cell
End If
' Lower case
If Me.OptionLower.Value Then
For Each cell In Selection
If Not cell.HasFormula Then
cell.Value = StrConv(cell.Value, vbLowerCase)
End If
Next cell
End If
' Proper case
If Me.OptionProper.Value Then
For Each cell In Selection
If Not cell.HasFormula Then
cell.Value = StrConv(cell.Value, vbProperCase)
End If
Next cell
End If
Unload Me
End Sub
The macro starts by checking the type of selection. If a range is not selected, the procedure ends. The remainder of the procedure consists of three separate blocks. Only one block is executed, determined by which OptionButton is selected. The selected OptionButton has a Value of True. Finally, the UserForm is unloaded (dismissed).
At this point, the UserForm has all the necessary controls and event procedures. All that's left is a way to display the form. This section explains how to write a VBA procedure to display the UserForm:
Sub ShowUserForm()
UChangeCase.Show
End Sub
To try the UserForm from Excel, follow these steps:
Try it with a few more selections, including noncontiguous cells. Notice that if you click Cancel, the UserForm is dismissed and no changes are made.
The code does have a problem, though: if you select one or more entire columns, the procedure processes every cell, which can take a long time. The version of the workbook on the website corrects this problem by working with a subset of the selection that intersects with the workbook's used range.
At this point, everything should be working properly. However, you have no quick and easy way to execute the macro. A good way to execute this macro would be from a button on the worksheet. You can use the following steps:
After you perform the preceding steps, clicking the button executes the macro and displays the UserForm.
If you'd like to use this macro while other workbooks are active, you may want to add a button to your Quick Access Toolbar. Follow these steps:
Creating UserForms can make your macros much more versatile. You can create custom commands that display dialog boxes that look exactly like those that Excel uses. The following sections contain some additional information to help you develop custom dialog boxes that work like those that are built into Excel.
All Excel dialog boxes work well with a mouse and a keyboard because each control has an associated accelerator key. The user can press Alt plus the accelerator key to work with a specific dialog box control.
Your custom dialog boxes should also have accelerator keys for all controls. You add accelerator keys in the Properties window by entering a character for the Accelerator property.
Your accelerator key can be any letter, number, or punctuation, regardless of whether that character appears in the control's caption. It's a good practice to use a letter that is in the control's caption, though, because that letter will be underlined—a visual cue for the user. (See Figure 41.12 for an example of option buttons with accelerator keys.) Another common convention is to use the first letter of the control's caption. But don't duplicate accelerator keys. If the first letter is already taken, use a different letter, preferably one that is easy to associate with the word (like a hard consonant). If you have duplicate accelerator keys, the accelerator key acts on the next control in the tab order of the UserForm. Then, pressing the accelerator key again takes you to the second control with that accelerator.
Some controls (such as text boxes) don't have a Caption property and other controls (such as labels) can't have the focus. You can assign an accelerator key to a label that describes the control and put that label right before your target control in the tab order. Pressing the accelerator key for a control that can't take the focus activates the next control in the tab order.
The previous section refers to a UserForm's tab order. When you're working with a UserForm, pressing Tab and Shift+Tab cycles through the dialog box's controls. When you create a UserForm, you should make sure that the tab order is correct. Usually, it means that tabbing should move through the controls in a logical sequence.
To view or change the tab order in a UserForm, choose View ➪ Tab Order to display the Tab Order dialog box (see Figure 41.13). You can then select a control from the list; use the Move Up and Move Down buttons to change the tab order for the selected control.
Mastering UserForms takes practice. You should closely examine the dialog boxes that Excel uses to get a feel for the way dialog boxes are designed. You can duplicate many of the dialog boxes that Excel uses.
The best way to learn more about creating dialog boxes is by using the VBA Help system. Pressing F1 is the quickest way to display the Help window.