VBA Foundations For Microsoft Office
VBA Foundations For Microsoft Office
for Microsoft
Office
Table of Contents
INTRODUCTION .......................................................................................INTRO-1
Courseware Conventions ..............................................................INTRO-2
The Practice Disks.........................................................................INTRO-3
Working with the Office Samples .......................................INTRO-3
About the Author............................................................................INTRO-5
Lab 1 Overview.....................................................................................1-32
Setting Security Levels .........................................................................1-33
Explore an Excel VBA Application ........................................................1-35
Call a Function from the Excel User Interface ......................................1-39
Try Out a Word VBA Application ..........................................................1-41
Record a Macro in Word.......................................................................1-46
Create a Toolbar and Button in Word ...................................................1-51
Call a Function from an Access Query .................................................1-55
Lab 2 Overview.....................................................................................2-30
Create and Rename a VBA Project ......................................................2-31
Add a New Module to a Project ............................................................2-33
Create a Simple Function .....................................................................2-36
Call a VBA Procedure from an Excel Worksheet..................................2-39
Change the Visual Basic Editor Format................................................2-40
Resizing a Control.......................................................................7-8
Working with Multiple Controls....................................................7-9
Deleting Controls ......................................................................7-10
Formatting Controls ..................................................................7-10
Setting Properties at Design Time ........................................................7-11
Working with the Properties Window ........................................7-12
A Few Common Properties.......................................................7-13
Introducing Events ................................................................................7-17
Event Procedures .....................................................................7-17
Creating an Event Procedure....................................................7-18
The Click Event.........................................................................7-19
The Change Event ....................................................................7-20
Setting Properties at Run Time.............................................................7-22
Setting Property Values ............................................................7-22
Retrieving Property Values .......................................................7-23
Setting Control Properties.........................................................7-23
Additional ActiveX Controls ..................................................................7-26
Where Do I Get These Other Controls?....................................7-26
Adding a Control to the Toolbox ...............................................7-26
Organizing the Toolbox.............................................................7-28
Modifying an ActiveX Control’s Properties................................7-28
Using the Calendar Control.......................................................7-30
Working with Methods ..........................................................................7-33
The Show Method.....................................................................7-33
The SetFocus Method...............................................................7-34
Working with List Boxes and Combo Boxes .........................................7-36
Using the AddItem Method or Combo Box ...............................7-36
Using a List Box’s or Combo Box’s List Property......................7-37
What Did the User Choose? .....................................................7-38
HANDLING ERRORS.........................................................................................9-1
Recognizing a Run-Time Error ...............................................................9-2
Different Kinds of Errors..............................................................9-2
Doesn’t VBA Handle Run-Time Errors?......................................9-2
The Error-Handling Standard..................................................................9-4
The Three-Step Program ............................................................9-4
Creating a Standard Error Handler .............................................9-4
Setting the Error Trap .................................................................9-6
Which Error Occurred? ...............................................................9-6
UNDERSTANDING EVENTS...........................................................................11-1
Events and Event Procedures ..............................................................11-2
What Did You Just Do?.............................................................11-3
Where To from Here? ...............................................................11-3
Which Objects Have Events? ...............................................................11-4
User Form Events.................................................................................11-5
The UserForm QueryClose Event.............................................11-5
Event Procedure Arguments.....................................................11-6
Control Events ......................................................................................11-8
Before/AfterUpdate Events .......................................................11-8
Click Event ................................................................................11-9
Product-Specific Events......................................................................11-11
Word’s Open Event.................................................................11-11
The Worksheet Change Event................................................11-13
Outlook’s ItemSend Event ......................................................11-14
Is There More? ...................................................................................11-15
Getting At Other Events ..........................................................11-16
INDEX........................................................................................................INDEX-1
Introduction
Courseware Conventions
We’ve followed several conventions to make this Professional Skills
Development material easy to follow:
The samples are provided in files created in one or more of the Microsoft
Office applications that include VBA. For example, they are saved with a
Microsoft Word file or a Microsoft Excel file.
You must be using a copy of Windows (virtually any version from Windows
98 forward) to be able to use these samples. You must be using a product that
includes VBA to run these samples. Sample files are provided for Office XP,
Office 2000, and Office 97.
2. Open the Visual Basic Editor from the host application by choosing
the following menu items: Tools|Macro|Visual Basic Editor.
3. Select the sample project in the Project Explorer. The samples are
available in the modules and forms beneath this project.
your application. You can then work with them in a VBA project and save
them with your project.
Mastering VBA
Control Structures
Objectives
• Learn about Visual Basic for Application control structures.
• Understand the principles of branching and looping.
Branching Structures
Why Branch?
Any complete programming language must supply some way in which your
code can control the flow of execution, depending on choices made during
execution. For example, a procedure may need to execute one statement or
group of statements if a condition is True, and a different statement or
statements if it’s False.
If...Then...[Else...]End If
You can use the If...Then...[Else...] End If statement to execute one or more
statements if a condition is True, and a different group of statements if it’s not.
In concept, it is logical decision making:
In VBA code, the condition must be some sort of expression that returns a
value. If the returned value is 0, VBA treats it as False. VBA treats anything
besides 0 as True.
For example, you could use the WeekDay() and Date() functions that are built
into VBA to write the condition from the previous example (Date() returns the
current date, and WeekDay() returns an integer indicating the day of the week,
given a date value):
If WeekDay(Date) = vbSunday Or _
WeekDay(Date) = vbSaturday Then
' Do Weekend stuff
End If
The End If statement is crucial; it tells VBA at what point you’re finished
telling it what to do. It ends the block of statements that make up the chunk of
code.
Try out For example, the procedure ValidateData in basIfThen uses the If…Then
ValidateData in statement to validate user input:
basIfThen
NOTE VBA also supplies a special case version of If…Then that can
exist on a single line. In that case, you don’t need to provide the
End If at the end of the block. Most developers seldom use this
construct because it’s difficult to read and limited in use.
TIP If you are checking a value to see whether it’s True or False, you can leave
the comparison operator out of the If…Then statement. That is, the following
two lines of code are equivalent:
If IsDate(dteTest) Then
' is the same as
If IsDate(dteTest) = True Then
If...Then...Else[If]...End If
If you require more than a single condition, and the conditions are mutually
exclusive, you may find that ElseIf may be what you need.
If <condition1> Then
<statement block 1>
ElseIf <condition2> Then
<statement block 2>
...
Else
<statement block 3>
End If
You can have as many ElseIf’s as you want (0, or more) but only a single Else.
The Else clause catches any condition you’ve not checked for explicitly, and is
optional.
Run InputType in As an example, look at the function InputType in basIfThen. This function
basIfThen prompts the user for a value, then checks whether the value is a numeric value,
a date, or an alphanumeric text string.
Select Case
The Select Case control structure compares a condition against a single value,
and based on the value, selects a block of statements to execute.
VBA reads the Case options in order until it finds one that matches your
expression. Even if multiple Case options are True, only the first Case option
is executed.
If you have multiple conditions you must test against, you’ll find the Select
Case structure easier to use than If...Then...ElseIf...End If.
You have several options for how you compare the expression. You can use a
delimited list (separated with commas) of any of the following forms:
• Expression
• Expression To expression
• Is comparisonOperator expression
For example, the following expression is valid, and will match against a vowel,
the digits 0 through 9, and any letter greater than “M”:
Case "A", "E", "I", "O", "U", "0" to "9", Is > "M"
See TestYear in The following function takes an argument of type Date. It evaluates the year
basSelect portion of the date within a Select Case statement.
lngThisYear = Year(Date)
See CalcQuartile in In this application, you want to know how many people you have in the range
basSelect from A-F, G-L, M-S, and T-Z. To do this, you must have a function that, given
a name, will calculate the appropriate quartile value.
GoTo
It’s true; VBA supports the humble GoTo statement. GoTo was nearly the
death of Basic in the 80s. Basic got a bad reputation because in its infancy,
GoTo was Basic’s only branching control structure. This led to ugly, hard-to-
read, and hard-to-maintain code.
However, even with all the different branching methods available, there are
times when GoTo has its place in VBA programming.
The line label must begin with an alphabetical character and end with a colon.
No matter what you would like it to do, GoTo can only jump to a label within
its own procedure.
You’ll seldom have a reason to use GoTo, except to use it for error handling,
which is covered in a later section. One common way to use GoTo is to use it
to jump to an exit point. For example, if your procedure determines early on
that it must exit, rather than continue processing you can use GoTo, as the
following procedure shows:
If someBadCondition Then
GoTo ProcedureExit
End If
ProcedureExit:
' Clean up for exit
End Sub
There are other ways to solve this problem, but GoTo is commonly used in this
situation and offers the advantage of providing a common exit point for the
procedure, no matter what happens when it is running.
Looping Structures
What is a Loop?
A looping structure allows you to repeat a set of statements in code. You
control the number of times your statements execute by using either a
condition or a fixed number that terminates the loop. Figure 1 displays a
schematic diagram of a loop.
VBA has a variety of looping structures that fall into two overall types: Do
loops, and For...Next loops.
Do...Loops
This is the simplest form of the Do…Loop construct:
Do
<statements>
Loop
Do
byt = byt + 1
Debug.Print byt
Loop
End Sub
NOTE We use the Byte data type here simply to facilitate demonstration.
Because a Byte variable can only hold values between 0 and 255,
we don’t need to wait very long to see the results of our infinite
loop. In practice, you don’t typically use the Byte data type to
work with numeric values.
The problem here, of course, is that this loop won’t stop executing until a
memory overflow occurs. In practice, you don’t want a loop to execute until
this happens; you want it to execute a particular number of times, then stop.
In order to jump out of a Do loop early, you need to use the Exit Do statement.
See ExitLoop1 in For example, the following procedure will loop until it hits a specific value,
basLoop and will then jump out of the loop:
Do
byt = byt + 1
Debug.Print byt
If byt = 255 Then
Exit Do
End If
Loop
End Sub
You can also use a Do While or Until loop to exit the loop once a certain
condition is met.
You can check for the condition before you execute the statements, or after.
Table 1 displays the four ways you can loop with Do Loop.
Check Do Do
condition at <statements> <statements>
bottom of loop Loop Until <condition> Loop While <condition>
(always
executes at
least once)
Table 1. Possible Do…Loop syntax options.
See ExitLoop2 - Let’s look at the different ways that you can use a condition to exit a Do loop.
ExitLoop5 in
basLoop
First, you can use the Until statement at the beginning of a loop to loop until a
particular condition is True. In this case, we only enter the loop if the value of
the byt variable is not equal to 255, and loop until it equals 255.
You can also use the While statement to check for the converse condition. In
this case, the loop also executes as long as the byt variable is not equal to 255.
Which one should you use? It really doesn’t matter. Consider the following:
Do you always want to execute the loop at least once? If so, you should place
the condition at the end of the loop, as in one of the following examples:
Do
byt = byt + 1
Debug.Print byt
Loop Until byt = 255
End Sub
' or
Do
byt = byt + 1
Debug.Print byt
Loop While byt <> 255
End Sub
• If you want to execute the statements at least once, no matter how the
condition evaluates, place the condition after the Loop statement. You
might do this if, for example, you’re asking for a password. The code
inside the loop would prompt for the password, and If statement would
check it and exit the loop if the password is correct. If the password is
incorrect, the loop repeats.
• If the loop might never execute, place the condition at the top, next to
the Do statement. For example, if you are looping through a table and
the table might be empty, you can use the condition on the Do
statement to check for an empty table.
• Choose Until or While depending on the truth status of your condition:
∗ If you want to loop while your condition is True, use While.
∗ If you want to loop while your condition is False, use Until.
For...Next
If you want to execute a set of statements a fixed number of times, rather than
checking a condition, use the For...Next control structure. The For...Next
structure uses a counter variable whose value increases or decreases with each
repetition of the loop, automatically. You can set the size of the increment with
the Step directive.
For...Next Syntax
[Exit For]
statement N
Next [variable]
Using For...Next
See SimpleLoop in Here’s a simple procedure that demonstrates how the For…Next loop works.
basLoop
The number that you pass to the function becomes the upper limit for the loop,
and the loop executes lngNum + 1 times. The 1 is added because the loop
begins counting at 0.
Try Factorial in The code uses For...Next to loop backwards, starting at the value you pass to
basLoop the function, accumulating the products. It stops when it gets to 2, because
there’s no need to multiply by 1. That would just be a waste of time.
For Each...Next
Summary
• Execute conditional statements by using the If...Then or the Select
Case statements.
• The Else clause in an If...Then...ElseIf...Else...End If statement, and
the Case Else clause in a Select Case statement handle the “under any
other condition” situation. Make sure that’s what you mean.
• Avoid the GoTo branching construct, for the most part. It can lead to
difficult-to-read code.
• A loop allows you to repeat blocks of statements while or until some
condition is True, or a set number of times.
• After a Do While...Loop construct, you can assert that the test
condition is False. After a Do Until...Loop, you can assert that the test
condition is True.
• You can use Exit Do to exit a Do loop.
• Use For...Next to execute a series of statements a fixed number of
times.
Questions
1. Write an If...Then statement that checks to see if one number is greater
than another (intItem1 and intItem2), and if so, displays a message box
saying “Number 1 is greater than Number 2.” Otherwise, display nothing.
3. Write a For...Next loop that loops from 1 to 100, and prints only the value
50 to the Debug window, at the time when the loop counter becomes 50.
Answers
1. Write an If...Then statement that checks to see if one number is greater
than another (intItem1 and intItem2), and if so, displays a message box
saying “Number 1 is greater than Number 2.” Otherwise, display nothing.
If intItem1 > intItem2 Then
MsgBox “Number1 is greater than Number 2”
End If
3. Write a For...Next loop that loops from 1 to 100, and prints only the value
50 to the Debug window, at the time when the loop counter becomes 50.
For intI = 1 To 100
If intI = 50 Then
Debug.Print intI
End If
Next intI
Lab 5:
Mastering VBA
Control Structures
TIP: Because this lab includes a great deal of typed code, we’ve tried to make it
simpler for you. You’ll find all the code in Mastering VBA Control
Structures.txt, in the same directory as the sample project. To avoid typing
the code, you can cut/paste it from the text file instead.
Lab 5 Overview
In this lab you’ll learn about VBA control structures and how you can use
them to direct the flow of execution.
• Use If…Then/Else…End If
• Use Select Case
• Use a Do…Loop
• Use a For…Next Loop
Each exercise includes an “Objective” section that describes the purpose of the
exercise. You are encouraged to try to complete the exercise from the
information given in the Objective section. If you require more information to
complete the exercise, the Objective section is followed by detailed step-by-
step instructions.
Use If…Then/Else…End If
Objective
In this exercise, you’ll write a function named Max that accepts two Variant
values and returns the value of the one that’s larger. When you test the
function from the Immediate window, it will look like Figure 2.
Figure 2. Your Max function will work with arguments of any type.
Additional Information
You can compare two of almost any data type to determine which is greater.
For this simple function, all you care about is the result of using the “>”
operator to compare two values.
When comparing values, as soon as you determine that the first value is not
greater than the second value, then you know that the second value is either
greater then or equal to the first value. This means that after you check the first
value, you don’t have to explicitly check the second value. If the first value is
not greater than the second value, then it’s safe to assume that you can return
the second value.
Step-by-Step Instructions
1. Open the Control Structures Lab.xls file.
5. Press CTRL+G to move focus to the Immediate window. Try the following
tests to make sure your function works correctly:
? Max(12, -1)
? Max(1, 2)
? Max("Hello", "There")
Objective
In this exercise, you’ll create a sub procedure named TestSelect that displays a
message box with Abort, Retry, and Ignore buttons, and asks the user to select
one. Once the user has selected a value, the procedure should display a
message box indicating which item the user selected. Figure 3 shows how the
message box should look, and Figure 4 shows the response back to the user.
Figure 4. Once you get a response, tell the user what happened.
Additional Information
The MsgBox function returns a value that indicates which button the user
selected. In previous exercises, you’ve ignored the return value. In this
exercise, however, you must store the return value in a variable and then
compare it to each of the possible values using Select Case.
Step-by-Step Instructions
1. Open the basControl module created in the previous step.
Call TestSelect
Use a Do…Loop
Objective
In this exercise, you’ll write a function named GetInput that prompts the user
to enter text into an input box until they cancel the input box. After the user
cancels, display a message box that shows all of the values the user typed.
Additional Information
As you saw in a previous lab, the InputBox function returns a string containing
the user’s input into the dialog box. If the user clicks the Cancel button, or
clicks OK without entering any text, then the InputBox function returns an
empty string.
You can use the InputBox function within a loop to get multiple inputs from
the user. The key is to create a loop that checks for the condition where the
InputBox function returns an empty string. Either a Do While loop or a Do
Until loop will work. When the user clicks Cancel, the loop finishes its current
execution and doesn’t execute again.
You want the loop to execute at least once, so that the user is prompted at least
once; therefore, you should place the condition at the end of the loop.
Within the loop, you can keep track of how many times the loop has executed
by incrementing a counter variable. That way, you can prompt the user to enter
item #1, item #2, and so forth.
The other thing you want to do within the loop is to keep track of all of the
user’s inputs. You can do this by concatenating them into a string. Each time
through the loop, the new input is added to the string. When the loop exits, you
can display this string in a message box to show the user all of their input
values.
Step-by-Step Instructions
1. Open the basControl module created in the previous exercise.
2. Add the following procedure. Keep in mind that you don’t have to type the
comments; they’re there to help you understand the code:
Objective
In this exercise, you’ll write a function named MultiInput that uses a
For…Next loop to prompt the user for a set number of input items. The user is
first prompted for the number of input items, and then prompted for each input
item.
Additional Information
The For…Next loop is useful for repeating a group of statements when you
know exactly how many times you wish to repeat the statements. The loop
begins with a For statement that specifies the number of repetitions and ends
with a Next statement that causes the program to return to the beginning of the
loop until the specified number of repetitions has been completed. The For
statement includes a counter variable which is increased or decreased by a
specified increment with each repetition of the loop. If you do not specify an
increment, a default value of 1 is used.
Step-by-Step Instructions
1. Open the basControl module created in the previous step.
Call MultiInput