C H A P T E R 1 | Microsoft Office 97/Visual Basic Programmer's Guide |
Programming Basics |
Microsoft Excel 97, Word 97, and PowerPoint 97 come equipped with a fullfeatured development environment called the Visual Basic Editor. Using the Visual Basic Editor, you can create, edit, debug, and run code associated with Microsoft Office documents. To open the Visual Basic Editor, click the Visual Basic Editor button on the Visual Basic toolbar.
A First Look at the Visual Basic Editor
If you're used to writing, editing, and debugging code in a macroediting
window within the Word application window, on an XLM macro sheet,
or on a module in a Microsoft Excel workbook, the Visual Basic
Editor may seem complex to you the first time you open it, with
many windows and buttons you aren't familiar with. This section
explains some of these features of the Visual Basic Editor.
For information about a particular window in the Visual Basic
Editor, click in the window and then press F1
to open the appropriate Help topic. To see the Help topic for
any other element of the Visual Basic Editor, such as a particular
toolbar button, search Help for the name of the element.
The Properties Window
A property is a characteristic of an object, such as the object's
color or caption. You set a property to specify a characteristic
or behavior of an object. For example, you can set the ShowSpellingErrors
property of a Word document to True to show spelling errors
in the document.
You can use the Properties window to set the properties
of an object at design time. The Properties window is very
useful when you're working with custom dialog boxes and ActiveX
controls. For more information about using the Properties
window to set properties of dialog boxes and controls, see Chapter 12,
"ActiveX Controls and Dialog Boxes." For most objects,
however, it's easier to set these properties at design time by
using familiar commands in the user interface. For example, you
can set the ShowSpellingErrors property of a Word document
to True by selecting the Hide spelling errors in this
document check box on the Spelling & Grammar
tab in the Options dialog box (Tools menu).
If you don't think you'll be using the Properties window
right now, you can close it to simplify your work space a little.
You can open it again at any time by clicking Properties Window
on the View menu.
The Project Explorer
All the code associated with a workbook, document, template, or
presentation is stored in a project that's
automatically stored and saved with the workbook, document, template,
or presentation. In the Project Explorer of the Visual
Basic Editor, you can view, modify, and navigate the projects
for every open or referenced workbook, document, template, or
presentation. You can resize the Project Explorer and either
dock it to or undock it from any of the sides of the Visual Basic
Editor window to make it easier to use.
Note In
Word, because the Normal template is available from every Word
document, there's always a project for Normal in the Project Explorer.
Within a project, there can be application objects that have events
associated with them, custom dialog boxes (called forms
in the Project Explorer), standard modules, class modules,
and references.
Tip Folders
in the Project Explorer divide project elements into categories.
If you don't see any folders, click the Toggle Folders
button at the top of the Project Explorer.
In the Project Explorer, there's one project for each open
or referenced workbook, document, template, or presentation. In
each project, you may find objects (such as Document objects,
Workbook objects, and Worksheet objects) that recognize
events; forms (also called UserForms), which
are custom dialog box interfaces and the code that controls how
the user interacts with a particular dialog box; standard modules,
which contain code that isn't associated with a particular object
or form; class modules, which contain information about a custom
object type; and references to other projects. To see the code
in a module or the code associated with an object or form, click
the element in the Project Explorer, and then click the
View Code button at the top of the Project Explorer.
To see the user interface for a particular object or form, click
the object or form in the Project Explorer, and then click
the View Object button at the top of the Project Explorer.
The Code Window
To view the code in a project, go to the Project Explorer,
click the element that contains the code, and then click the View
Code button at the top of the Project Explorer.
Tip If
you want to be able to see more than one procedure in the code
window at a time, select the Default to Full Module View
check box on the Editor tab in the Options dialog
box (Tools menu). To view just one procedure at a time,
clear this check box.
You can navigate the Code window by using the items listed
in the Object and Procedure boxes at the top of
the window. In the Object box, click (General),
and then click a procedure name in the Procedure box to
see a procedure that isn't associated with a specific event. In
the Object box, click an object, and then click an event
in the Procedure box to see the code that runs when a specific
event occurs.
Making Room in the Visual Basic Editor
If all you want to do is write a simple procedure or edit a macro
you've recorded, you may want to forego some of the advanced features
of the Visual Basic Editor in the interest of a simpler workspace.
Here are a few ways you can simplify your coding environment:
Recording a Macro
You can use the macro recorder to translate userinterface
actions into Visual Basic code. Recording a simple macro can give
you a jump start on creating a more complex macro, and can help
you become familiar with the objects, properties, and methods
of an application.
To
record a macro
You can use the Store macro in box to choose where
your macro will be stored. For now, click This Workbook in Microsoft
Excel, All Documents (Normal.dot) in Word, or the name of the
active presentation in PowerPoint.
Your macro has been recorded. To look at the macro code, point
to Macro on the Tools menu, and then click Macros.
In the Macros dialog box, select the appropriate macro
name, and then click Edit.
Getting Around in Your Projects
You use the Project Explorer to navigate to any procedure
in any open project. Start by finding the object that contains
your macro. Most general procedures, including recorded macros,
are stored in a standard module. If you have folders displayed
in the Project Explorer, standard modules are located in
the Modules folder.
Tip If
you don't see folders in the Project Explorer, click the
Toggle Folders button to display them.
After you locate the object that contains your code, doubleclick
the object to view the procedures it contains. You can use this
method to get to either procedures you've written from scratch
or macros you've recorded.
Where a recorded macro is stored depends on what location you
specified in the Store macro in box in the Record Macro
dialog box when you recorded your macro. In Microsoft Excel, if
you clicked This Workbook in the Store macro in
box when you recorded your macro, your macro will be stored in
Module1 in the Modules folder of the project for the workbook
you recorded the macro in. In Word, if you clicked All documents
(Normal.dot) in the Store macro in box when you recorded
your macro, your macro will be stored in the NewMacros module
in the Modules folder of the Normal project. In PowerPoint, if
you clicked the name of the active presentation in the Store
macro in box when you recorded your macro, your macro will
be stored in Module1 in the Modules folder of the project for
the presentation you recorded the macro in.
Tip If
you want to be able to see more than one procedure in the code
window at a time, make sure that the Default to Full Module
View check box is selected on the Editor tab in the
Options dialog box (Tools menu). Otherwise, you
have to use the Procedure box in the code window to move
from one procedure to another.
Writing a New Procedure
If you want to write code that isn't associated with a specific
object or event, you can create a procedure
in a standard module in the Visual Basic Editor. A procedure is
a unit of code enclosed either between the Sub and End
Sub statements or between the Function and End Function
statements.
To create a blank standard module, go to the Project Explorer,
click anywhere in the project you want to add the module to, and
then click Module on the Insert menu.
To open an existing standard module, select the module in the
Project Explorer, and then click the View Code button
in the Project Explorer.
To add a procedure to a module, select the module in the Project
Explorer, click Procedure on the Insert menu,
select whatever options you want in the Add Procedure dialog
box, and then click OK. For more information about the
options in the dialog box, press F1 while
the dialog box is displayed. For example, in the dialog box, type
Test1 in the Name box, click Sub under Type,
click Public under Scope, and then click OK.
The procedure that appears in your module should look like the
following example.
After you've added a procedure to a module, you can add code to
the procedure. The following example adds to the preceding code
a line that displays a message box.
If you want to write code that runs automatically when a certain
event occurs for instance, when a document is
opened, a worksheet is calculated, or a button in a custom dialog
box is clicked you should write a procedure associated
with the event for the object or form. For general information
about writing event procedures, see "Writing Code to Respond to Events" later in this chapter. For specific information
about writing event procedures for custom dialog boxes and ActiveX
controls, see Chapter 12, "ActiveX Controls and Dialog Boxes."
What's the Difference Between a Macro and a Procedure?
Although the terms macro and procedure
are sometimes used interchangeably, they actually have distinct
meanings. Procedure is the broader term; it applies to any unit
of code enclosed either between the Sub and End Sub
statements or between the Function and End Function
statements. Macro is a specific term that applies only to public
Sub procedures that take no arguments. All macros are procedures,
but not all procedures are macros. All procedures you generate
with the macro recorder and all procedures you can run from the
Macros dialog box in the Office application are macros.
Sub Procedures vs. Function Procedures
With Visual Basic, you can create two types of procedures: Sub
procedures and Function procedures.
A Sub procedure is a unit of code enclosed between the
Sub and End Sub statements that performs a task
but doesn't return a value. The following example is a Sub
procedure.
A Function procedure is a unit of code enclosed between
the Function and End Function statements. Like a
Sub procedure, a Function procedure performs a specific
task. Unlike a Sub procedure, however, a Function
procedure also returns a value. The following example is a Function
procedure.
Public Procedures vs. Private Procedures
You can call a public procedure, declared with the Public
keyword, from any procedure in any module in your application.
You can call a private procedure, declared with the Private
keyword, only from other procedures in the same module. Both Sub
procedures and Function procedures can be either public
or private. The following are examples of private procedures.
The following are examples of public procedures.
If you don't use either the Public or Private keyword
to declare a procedure, the procedure will be public by default.
Therefore, the following are also examples of public procedures.
Although it's not necessary to use the Public keyword when
creating a public procedure, including it in procedure declarations
makes it easier to see at a glance which procedures are public
and which are private. For more information, see "Public"
or "Private" in Help.
Using the Value Returned from a Function
For a function to return a value, it must include a function assignment
statement that assigns a value to the name of the function. In
the following example, the value assigned to ConeSurface
will be the value returned by the function.
The information that must be supplied to a Sub procedure
or Function procedure for it to perform its task (radius
and height
in the preceding example) is passed in the form of arguments.
For more information about arguments, see "Passing Arguments to a Procedure" later in this chapter.
When the Function procedure returns a value, this value
can then become part of a larger expression. For example, the
following statement in another procedure incorporates the return
value of the ConeSurface and ScoopSurface functions in its calculations.
Running a Sub Procedure
You can have a Sub procedure run in response to a specific
event, you can run it from the Visual Basic Editor or your application
window, or you can call it from another procedure.
You cannot call a procedure you've declared as private from any
procedure outside the module in which the private procedure resides.
However, you can call a public procedure from outside the module
in which it resides. For an explanation of the terms "public"
and "private" in this context, see "Sub Procedures
vs. Function Procedures" earlier in this chapter.
When you call a public procedure that isn't located in the current
module, Visual Basic searches other modules and runs the first
public procedure it finds that has the name you called. If the
name of a public procedure isn't unique, you can specify the module
it's located in when you call the procedure. The following example
runs a Sub procedure named "DisplayWelcome" that's
stored in a module named "TestTools."
If necessary, you can also specify the project that the procedure
resides in. The following example runs a Sub procedure
named "DisplayWelcome" that's stored in a module named
"TestTools" in a project named "TestDocument."
Public Sub Test1()
End Sub
Public Sub Test1()
MsgBox "This is the Test1 procedure running"
End Sub
Sub DisplayWelcome()
MsgBox "Welcome"
End Sub
Function AddThree(OriginalValue As Long)
AddThree = OriginalValue + 3
End Function
Private Sub Test1()
MsgBox "This is the Test1 procedure running"
End Sub
Private Function AddThree(OriginalValue As Long)
AddThree = OriginalValue + 3
End Function
Public Sub Test1()
MsgBox "This is the Test1 procedure running"
End Sub
Public Function AddThree(OriginalValue As Long)
AddThree = OriginalValue + 3
End Function
Sub Test1()
MsgBox "This is the Test1 procedure running"
End Sub
Function AddThree(OriginalValue As Long)
AddThree = OriginalValue + 3
End Function
Function ConeSurface(radius, height)
Const Pi = 3.14159
coneBase = Pi * radius ^ 2
coneCirc = 2 * Pi * radius
coneSide = Sqr(radius ^ 2 + height ^ 2) * coneCirc / 2
ConeSurface = coneBase + coneSide
End Function
totalSurface = ConeSurface(3, 11) + 2 * ScoopSurface(3)
Sub TestCall()
DisplayWelcome
End Sub
TestTools.DisplayWelcome
TestDocument.TestTools.DisplayWelcome
Note that the name of the project you specify is the project's code name, not the name of the document the project is associated with. You can check and modify the project's code name in the space to the right of (Name) in the Properties window for the project. To see the Properties window, select the project in the Project Explorer, and then click Properties Window on the View menu. You can also change the code name of a project by typing a new name in the Project Name box on the General tab in the Project Properties dialog box. You display this dialog box by rightclicking the project in the Project Explorer, and then clicking Properties on the shortcut menu (the command appears on the shortcut menu preceded by the current name of the project). For more information about the options in the Project Properties dialog box, click a tab and press F1.
Tip If you want to be able to call a procedure from other modules in the same project but not from other projects, declare the procedure as public, but make the module private to the project by adding the Option Private Module statement to the (Declarations) section of the module.
If you want to be able to call procedures in one project from another project, there must be a reference from the project containing the calling code to the project containing the called code. To create a reference to a project, use the References dialog box (Tools menu).
Note If
you get an error when you try to create a reference from one project
to another one, make sure that the project you're trying to reference
doesn't have the same code name as the other project. (Multiple
projects in an application may be given the same default code
name, such as "Project" in Word or "VBAProject"
in Microsoft Excel.) To check a project's code name, click the
project name in the Project Explorer, and then click and then
click Properties Window on the View menu. The text to the right
of (Name) in the Properties window is the project's code name.
To change the code name for a project, select the current code
name and then type a new one. Keep in mind that you cannot have
circular references that is, if you have a reference
to project A from project B, you cannot have a reference from
project B to project A.
Passing Arguments to a Procedure
If your procedure needs information to perform its task that it
cannot get from the context in which it's being run, you can pass
that information to the procedure in the form of arguments. To
indicate that a given procedure takes arguments, include an argument
list between the parentheses that follow the procedure name in
the procedure declaration. The argument list can contain multiple
argument declarations, separated by commas.
When you declare an argument, you can specify the data type of
the argument by using the As keyword (whether or not the
procedure can change the argument's value by using the ByVal
and ByRef keywords), and you can specify whether the argument
is required or optional by using the Optional keyword.
For more information about a specific keyword, see the appropriate
topic in Help. For more information about the available data types
in Visual Basic, see "Visual Basic Data Types" later
in this chapter.
The following example shows the declaration line of a Sub
procedure that takes three arguments.
The second argument, custName,
is a required argument that will be passed as a value of type
String and will be passed by reference.
If you pass an argument by reference when calling a procedure,
the procedure has access to the actual variable in memory. As
a result, the variable's value can be changed by the procedure.
The third argument, custRepeat,
is an optional argument that will be passed as a value of type
Boolean and will be passed by reference
(passing by reference is the default).
The following example calls UpdateRecord.
The first argument, custID, is a required argument that will be passed as a value of type Long and will be passed by value.
If you pass an argument by value when calling a procedure, the called procedure receives only a copy of the variable passed from the calling procedure. If the called procedure changes the value, the change affects only the copy and not the variable in the calling procedure.
Sub UpdateRecord(ByVal custId As Long, ByRef custName As String, _
Optional custRepeat As Boolean)
Dim newId As Long
Dim newName As String
Dim newRepeat As Boolean
newId = 3452
newName = "Mary Boyd"
newRepeat = True
UpdateRecord newId, newName, newRepeat
Note that the name of the variable you pass from the calling procedure doesn't have to match the name of the argument declared in the called procedure.
Using Named Arguments
If either a procedure you create or a builtin function,
statement, or method takes more than one optional argument, you
may want to pass arguments to it by name rather than by position.
For example, the Open method of the Microsoft Excel Workbooks
object, which opens a workbook, takes 13 arguments. If you want
to write code that opens the workbook Book2.xls and adds it to
the list of recently used files, you could write the code shown
in the following example.
Workbooks.Open "book2.xls", , , , , , , , , , , , True
However, this code is difficult to write correctly without introducing bugs, because you have to count the number of commas to insert between the arguments. The code is also very difficult to read, and it gives no clues about what the arguments represent. The following example shows a better way to write this code.
Workbooks.Open FileName:="book2.xls", AddToMru:=True
Because every argument has a name, you can use the name and the := operator to assign a value to an argument. When you use named arguments, you don't have to remember the order of the arguments. For instance, the preceding code could have been written with the order of the arguments reversed, as in the following example.
Workbooks.Open AddToMru:=True, FileName:="book2.xls"
You can also use named arguments with the procedures you create. Visual Basic automatically associates argument names with their corresponding procedures. For instance, assume that you've created a FormatList procedure that takes two required arguments and two optional arguments, as shown in the following declaration.
Sub FormatList(startRow As Integer, startCol As Integer, _
Optional redText, Optional sortList)
The DoList procedure in the following example uses named arguments to call the FormatList procedure.
Sub DoList()
FormatList redText:=True, startCol:=2, startRow:=2
End Sub
The arguments are now out of order, and one of the optional arguments was omitted.
Note Using
named arguments doesn't negate the need to enter required arguments.
Writing Code to Respond to Events
Certain objects in the Office 97 applications recognize a
predefined set of events, which can be triggered either by the
system or by the user. Examples of events recognized by objects
in Office include the Open and Close events for Word documents;
the Open, BeforePrint, BeforeSave, and BeforeClose events for
Microsoft Excel workbooks; the Calculate and SelectionChange events
for Microsoft Excel worksheets; the Click, Initialize, and Terminate
events for custom dialog boxes; and the Click, GotFocus, and LostFocus
events for ActiveX controls. For detailed information about the
events available in Microsoft Excel and Word, see Chapter 7,
"Microsoft Word Objects," and Chapter 4, "Microsoft
Excel Objects." For detailed information about using custom
dialog boxes and ActiveX controls, see Chapter 12, "ActiveX
Controls and Dialog Boxes."
You can control how your application responds to a recognized
event by writing code in the Code window for the object.
Every time an event occurs, the code, or event procedure,
associated with that event runs. For instance, if you write a
procedure that's associated with the Open event for a Word document,
every time that document is opened, the procedure automatically
runs.
Where Event Code Is Stored
An event procedure is stored in the document, workbook, worksheet,
slide, or UserForm where the event can be triggered. For example,
the procedure that runs when you calculate the worksheet named
"Last Quarter" in the workbook named "Sales"
would be stored in the Last Quarter worksheet in the project associated
with the Sales workbook. To view the code in a document, workbook,
worksheet, slide, or UserForm, click the object in the Project
Explorer, and then click the View Code button to open
the Code window.
Note PowerPoint
presentations and slides don't recognize events. Therefore, unless
you can place ActiveX controls (which recognize events) on a PowerPoint
slide, there can be no event procedures associated with the slide,
and you won't see the slide in the Project Explorer. For more
information about adding ActiveX controls to documents, see Chapter 12,
"ActiveX Controls and Dialog Boxes."
How Event Procedures Are Named
The name of an event procedure is the name of the object that
recognizes the event such as "Document,"
"Worksheet," "UserForm," or "CommandButton1"
followed by an underscore (_), followed by the name of the event
that the procedure runs in response to such as "Open,"
"Calculate," or "Click." For example, the
procedure that runs when you open a Word document is Document_Open.
Note Whereas
the name of an event procedure for most objects is linked to the
class name (such as Document, Worksheet, or UserForm), the name
of an event procedure for an ActiveX control is linked to the
control's code name either the default name or
a name you assign. If you change the code name of a control after
writing event procedures, you must rename your procedures to match;
otherwise, they will never run in response to the events for that
control.
To view an event procedure, open the Code window for the
document, workbook, worksheet, slide, or UserForm where the event
can be triggered; select the name of the object that recognizes
the event (this can be either the object where the event can be
triggered itself or an ActiveX control contained in the object)
in the Object box; and then select the name of the specific
event you want to respond to in the Procedure box.
Note If
you want a procedure to be associated with a specific document,
workbook, worksheet, slide, or custom dialog box, but not with
a specific event for instance, if you want to
be able to call the procedure from several different event procedures
store it in the (General) section of the document, workbook, worksheet,
or slide module.
Timesaving Tools for Writing Code
Many keywords used in Visual Basic are extremely long and difficult
to type without making mistakes. To reduce the time you spend
typing and the number of typing errors in your code, Visual Basic
includes tools that complete words and build expressions for you.
When you've typed enough letters for Visual Basic to recognize
a word, press CTRL+SPACE or click the Complete
Word button on the Edit toolbar to have Visual Basic
automatically complete the word for you.
In the Options dialog box (Tools menu), you can
turn on tools that automatically do the following after you enter
a line of code: verify correct syntax, display information, and
give you appropriate options to choose from at each stage of building
your expression.
You can also use the List Properties/Methods, List Constants,
Quick Info, Parameter Info, and Complete Word
buttons on the Edit toolbar to get help completing a word
or an expression at any time. For more information about using
a specific tool to help you complete words and statements, see
the Help topic for that button or option. For information about
using these tools to build statements using Office properties
and methods, see Chapter 2, "Understanding Object Models."
Writing Code That's Easy to Read and Navigate
There are many ways to make your Visual Basic code more readable,
as described in the following paragraphs.
Add comments to your code by using an apostrophe (').
At run time, Visual Basic ignores everything between the apostrophe
and the end of the line. Each line in the following example includes
a comment.
To add the comment character to the beginning of each line in
a selected block of code, click the Comment Block button
on the Edit toolbar. To remove the comment character from
the beginning of each line in a selected block of code, click
the Uncomment Block button.
Break a long statement into multiple lines in the Code window
by using the linecontinuation character,
which is a space followed by an underscore (
_). The following example shows the same statement
expressed two different ways: on a single line, and continued
over two lines:
Note that you cannot use the linecontinuation character
in the middle of a literal string. If you have to break the line
within a literal string, break the string with the concatenation
character (&),
as shown in the following example.
You cannot follow a linecontinuation character with a comment
on the same line.
Use indentation levels to show logical levels in your code. Press
TAB or click the Indent button on the
Edit toolbar to shift each line in a selected block of
code one indentation level to the right. Lines within the selection
retain their indentation levels relative to one another. Press
SHIFT+TAB or click the Outdent button
on the Edit toolbar to shift each line in a selected block
of code one indentation level to the right.
Use bookmarks to mark key areas in your code that you want to
be able to move between quickly without having to navigate manually.
Add a bookmark to a line by clicking the Toggle Bookmark
button on the Edit toolbar. A blue, rounded rectangle appears
in the margin to indicate a bookmark. To navigate between bookmarks,
click the Next Bookmark or Previous Bookmark button
on the Edit toolbar.
For more information about a specific feature, see the appropriate
topic in Help.
Document Projects vs. Template Projects
If you're writing procedures that are specifically designed to
be run on a single document, workbook, or presentation, you can
store the code in the project associated with that document, workbook,
or presentation.
If, however, you want to be able to get to a procedure from more
than one document, workbook, or presentation, you can store the
code in the project associated with a particular template.
When you apply a template to a Word document, the template is
attached to the Word document. All procedures in the attached
template are available to the document. If you change the code
in a template, the changed code is available for use in all documents
based on that template. If you want a procedure to be available
to all Word documents, regardless of which templates they're based
on, store the procedure in Normal.dot, which is automatically
referenced by all documents.
When you apply a template to a workbook or a presentation, any
code in the template project is copied to the project for the
workbook or presentation. Unlike Word, Microsoft Excel and PowerPoint
don't attach the template to the workbook, so changes you make
to the code in the template project won't be reflected in the
workbook or presentation projects after the template has been
applied. If you want a procedure to be available to all Microsoft
Excel workbooks, regardless of which templates they're based on,
store the procedure in Personal.xls.
Class Modules
You use class modules to create your own custom objects when you
want to create encapsulated, reusable units of code. The Sub
and Function procedures you define in a class module become
methods of the custom object. The properties you define with the
Property Get, Property Let, and Property Set
statements become properties of the custom object. For more information
about creating and using custom classes, see Mastering Office 97
Development, a CDROM product available from Microsoft.
If you've added class modules to your project, either by clicking
Class Module on the Insert menu or by copying modules
from another project, you'll see a Class Modules folder under
the project name in the Project Explorer. You get to the
code for a particular class by clicking the class name and then
clicking the View Code button at the top of the Project
Explorer.
In Visual Basic, as in all highlevel programming languages,
you use variables and constants to store values. Variables can
contain data represented by any supported data type.
Visual Basic Data Types
The following table lists the fundamental data types that Visual
Basic supports.
1.401298E 45 to 3.402823E38 (positive values).
4.94065645841247E 324 to 1.79769313486231E308 (positive values).
Numeric values: same range as Double.
String values: same range as String.
Can also contain Error or Null values.
Declaring a Constant, Variable, or Array
You declare a constant for use in place of a literal value by
using the Const statement. You can specify private or public
scope, specify a data type, and assign a value to the constant,
as shown in the following declarations.
If you don't specify scope, the constant has private scope by
default. If you don't explicitly specify a data type when you
declare a constant, Visual Basic gives the constant the data type
that best matches the expression assigned to the constant. For
more information, see "Const Statement," "Public
Statement," "Private Statement," and "As"
in Help.
You declare a variable by using the Dim, Private,
Public, or Static keyword. Use the As keyword
to explicitly specify a data type for the variable, as shown in
the following declarations.
If you don't declare a variable as static, when a procedure that
contains it ends, the variable's value isn't preserved and the
memory that the variable used is reclaimed. If you don't explicitly
declare a data type, Visual Basic gives the variable the Variant
data type by default.
Note Not
all variables in the same declaration statement have the same
specified type. For example, the variables Test and Amount in
the last line in the preceding example are of the Variant data
type.
The steps you take to declare an array are very similar to the
steps you take to declare a variable. You use the Private,
Public, Dim, and Static keywords to declare
the array, you use integer values to specify the upper and lower
bounds for each dimension, and you use the As keyword to
specify the data type for the array elements. You must explicitly
declare an array before you can use it; you cannot implicitly
declare an array.
When you declare an array, you specify the upper and lower bounds
for each dimension within the parentheses following the array
name. If you specify only one value for a dimension, Visual Basic
interprets the value as the upper bound and supplies a default
lower bound. The default lower bound is 0 (zero) unless you set
it to 1 by using the Option Base statement. The following
declarations declare onedimensional arrays containing 15
and 21 elements, respectively.
You can also specify the lower bound of a dimension explicitly.
To do this, separate the lower and upper bounds with the To
keyword, as in the following declarations.
In the preceding declarations, the index numbers of counters
range from 1 to 15, and the index numbers of sums
range from 100 to 120.
Tip You
can use the LBound and UBound functions to determine
the existing lower and upper bounds of an array.
You can declare arrays of up to 60 dimensions. The following declaration
creates an array with three dimensions, whose sizes are 4, 10,
and 15. The total number of elements is the product of these three
dimensions, or 600.
Tip When
you start adding dimensions to an array, the total amount of storage
needed by the array increases dramatically, so use multidimensional
arrays with care. Be especially careful with Variant arrays,
because they're larger than arrays of other data types.
You declare a dynamic array just as you would declare a fixedsize
array, but without specifying dimension sizes within the parentheses
following the array name, as in the following declaration.
Somewhere in a procedure, allocate the actual number of elements
with a ReDim statement, as in the following example.
Use the Preserve keyword to change the size of an array
without losing the data in it. You can enlarge an array by one
element without losing the values of the existing elements, as
in the following example.
For more information, see "ReDim Statement" in Help.
Setting an Object Variable
You declare an object variable by specifying for the data type
either the generic Object type or a specific class name
from a referenced object library. The following declaration declares
an object variable of the generic type Object.
When an object variable is declared as the generic type Object,
Visual Basic doesn't know what type of object the variable will
later be used with. Therefore, Visual Basic cannot verify at compile
time that the object exists, cannot verify that any properties
or methods used with the object are specified correctly, and cannot
bind this information to the object variable in
other words, Visual Basic cannot early bind the
object variable. Not until the code runs and actually assigns
an object to the object variable can Visual Basic verify this
information and late bind the object variable.
Generic object variables are useful when you don't know the specific
type of object that the variable will contain, or when the variable
must at different times contain objects from several different
classes. If possible, however, you should provide a specific class
name when declaring an object variable, as shown in the following
declarations.
'This procedure calculates the burdened cost
'of the specified employee
Dim baseSalary As Currency 'salary not including benefits or bonuses
baseSalary = employeeLevel * 2500 'employeeLevel passed as argument
Set myField = ActiveDocument.Fields.Add(Range:=Selection.Range, Type:=wdFieldDate)
Set myField = ActiveDocument.Fields.Add(Range:=Selection.Range, _
Type:=wdFieldDate)
MsgBox "This is a string that I have to break up " & _
"so that I can continue it on another line"
Data type Description
Range Byte
1-byte binary data
0 to 255. Integer
2-byte integer 32,768 to 32,767.
Long
4-byte integer 2,147,483,648 to 2,147,483,647.
Single
4-byte floating-point number
3.402823E38 to 1.401298E 45 (negative values).
Double
8-byte floating-point number
1.79769313486231E308 to 4.94065645841247E 324 (negative values).
Currency
8-byte number with a fixed decimal point
922,337,203,685,477.5808 to 922,337,203,685,477.5807.
String
String of characters
Zero to approximately two billion characters.
Variant
Date/time, floating-point number, integer, string, or object. 16 bytes, plus 1 byte for each character if the value is a string value.
Date values: January 1, 100 to December 31, 9999.
Boolean
2 bytes True or False.
Date
8-byte date/time value
January 1, 100 to December 31, 9999.
Object
4 bytes Any object reference.
Const MyVar = 459
Public Const MyString = "HELP"
Private Const MyInt As Integer = 5
Const MyStr = "Hello", MyDouble As Double = 3.4567
Private I
Dim Amt
Static YourName As String
Public BillsPaid As Currency
Private YourName As String, BillsPaid As Currency
Private Test, Amount, J As Integer
Dim counters(14) As Integer
Dim sums(20) As Double
Dim counters(1 To 15) As Integer
Dim sums(100 To 120) As String
Dim multiD(4, 1 To 10, 1 To 15)
Dim dynArray() As Integer
ReDim DynArray(X + 1)
ReDim Preserve myArray(UBound(myArray) + 1)
Dim mySheet As Object
Dim mySheet As Worksheet
Dim myPres As Presentation
Dim myRange As Range
Dim myApp As Application
In addition to providing a specific class name, you may want to qualify the object variable type with the name of the application that's supplying the object, as in the following declarations. This is useful if you write code using the objects from more than one library, especially if the different libraries contain objects with the same name.
Dim wndXL As Excel.Window
Dim wndWD As Word.Window
Dim appWD As Word.Application
To assign an object to an object variable, use the Set statement, as shown in the following example.
Dim myRange As Excel.Range
Set myRange = Worksheets("Sheet1").Range("A1")
If you don't explicitly declare an object variable and you forget
the Set statement in your assignment, Visual Basic attempts
to use the default property of the object to assign a value to
the variable. The following example assigns to the variable myRange
the value of the default property of the Range object (which
is the Value property) rather than the Range object
itself.
myRange = Worksheets("Sheet1").Range("A1") ' forgot the Set statement!
Using Builtin Constants
The object library in each Office 97 application provides
a set of builtin constants, which you can use to set properties
or pass arguments to properties or methods. An enumerated type
is a set of builtin constants that represent the possible
values that a specific property can be set to or that a specific
property or method can accept as an argument. In the Object Browser,
many properties or methods will display the name of an enumerated
type for a return type or an argument type instead of displaying
a basic data type. To open the Object Browser in the Visual Basic
Editor, press F2. You can use the Object Browser
to see which constants are included in an enumerated type and
what literal value each constant represents. For example, click
Application in the Classes box in the Object Browser,
and click DisplayAlerts in the Members of box. In
the pane at the bottom of the Object Browser, you see the following
phrase:
Property DisplayAlerts As WdAlertLevel
WdAlertLevel is an enumerated type that contains a set
of constants that represent all the valid values for the DisplayAlerts
property. You can recognize an enumerated type name because it
begins with a prefix that indicates the object library that supplied
it such as Mso, Wd, Xl, Ac,
Pp, VB, or Fm just as builtin
constant names do. To see the constants included in this enumerated
type, click WdAlertLevel. Builtin constant names
begin with the same prefixes as enumerated types. The Classes
box in the Object Browser will scroll to the WdAlertLevel
enumerated type, and you'll see the constants of this type listed
in the Members of box. If you click one of the constants,
you'll see the literal value that it represents in the pane at
the bottom of the Object Browser. For more information about using
the Object Browser, see Chapter 2, "Understanding Object
Models."
You use builtin constants to replace literal values in your
code. The two lines of code in the following example, each of
which sets Word to display all alerts and message boxes when it's
running a procedure, are equivalent to one another.
Application.DisplayAlerts = -1
Application.DisplayAlerts = wdAlertsAll
Code that uses these constants instead of literal values is easier to read. In addition, code that uses builtin constants is less likely to need to be updated if values are remapped in future versions. That is, whereas the literal value 1 might not always represent the option of displaying all alerts and message boxes, the constant wdAlertsAll always will.
Using control structures, you can control the flow of your program's execution. If left unchecked by controlflow statements, a program's logic will flow through statements from left to right, and from top to bottom. Although you can write very simple programs with only this unidirectional flow, and although you can control a certain amount of flow by using operators to regulate precedence of operations, most of the power and utility of any programming language comes from its ability to change statement order with structures and loops.
Decision Structures
Visual Basic procedures can test conditions and then, depending
on the results of that test, perform different operations. The
Visual Basic decision structures are listed in the following table.
If...Then
Notice that the singleline form of
the If...Then statement doesn't use an End If statement.
If you want to run more than one line of code when the condition
is True, you must use the multipleline If...Then...End
If syntax.
Note When
the condition you're evaluating contains two expressions joined
by an Or operator for example, If (thisVal >
5 Or thatVal < 9) both expressions are
tested, even if the first one is True. In rare circumstances,
this behavior can affect the outcome of the statement; for example,
it can cause a runtime error if a variable in the second
expression contains an error value.
If...Then...Else
Use the If...Then...Else statement
to define two blocks of statements, as in the following example.
One of the statements runs when the specified condition is True,
and the other one runs when the condition is False.
If...Then...ElseIf
You can add ElseIf statements to test
additional conditions without using nested If...Then statements,
thus making your code shorter and easier to read. For example,
suppose that you need to calculate employee bonuses using bonus
rates that vary according to job classification. The Function
procedure in the following example uses a series of ElseIf
statements to test the job classification before calculating the
bonus.
The If...Then...ElseIf statement block
is very flexible. You can start with a simple If...Then
statement and add Else and ElseIf clauses as necessary.
However, this approach is unnecessarily tedious if each ElseIf
statement compares the same expression with a different value.
For this situation, you can use the Select Case statement.
Select Case
Notice that the Select Case structure evaluates a single
expression at the top of the structure. In contrast, the If...Then...ElseIf
structure can evaluate a different expression for each ElseIf
statement. You can replace an If...Then...ElseIf structure
with a Select Case structure only if each ElseIf
statement evaluates the same expression.
Looping Structures
You can use loop structures to repeatedly run a section of your
procedure. The Visual Basic loop structures are listed in the
following table.
Note Visual
Basic also includes the While
Wend statement, but it's a
good idea to use the more flexible variations of the Do
Loop
statement (such as Do While
Loop or Do
Loop While) instead.
Do...Loop
Note If
you want to run a block of statements a specific number of times,
use a For
Next loop.
Do While...Loop
Use the Do While...Loop statement
when you want to test a condition before you run the loop and
then continue to run the loop while the
condition is True.
Note The
statements in a Do While
Loop structure must eventually cause
the condition to become False, or the loop will run forever (this
is called an infinite loop). To stop an infinite loop, press CTRL+BREAK.
Do Until...Loop
Use the Do Until
Loop statement
if you want to test the condition at the beginning of the loop
and then run the loop until the test condition becomes True.
If the condition is initially True, the statements inside
the loop never run. With the test at the beginning of the
loop in the following example, the loop won't run if Response
is equal to vbNo.
Do...Loop While
When you want to make sure that the statements
in a loop will run at least once, use Do
Loop While
to put the test at the end of the loop . The statements will run
as long as the condition is True. In the following
Microsoft Excel example, the loop runs only if the Find
method finds a cell that contains "test." If the text
is found, the loop sets the color of the cell, and then searches
for the next instance of "test." If no other instance
is found, the loop ends.
Do...Loop Until
For...Next
When you know that you must run the statements
a specific number of times, use a For...Next loop. Unlike
the many variations of Do
Loop, a For...Next
loop uses a counter variable that increases or decreases in value
during each repetition of the loop. Whereas the variations of
Do
Loop end when a test condition becomes True
or False, a For...Next loop ends when the counter
variable reaches a specified value.
The Sub procedure in the following
example sounds a tone however many times you specify.
Because you didn't specify otherwise, the
counter variable in the preceding example increases by 1 each
time the loop repeats. You can use the Step keyword to
specify a different increment for the counter variable (if you
specify a negative number, the counter variable decreases by the
specified value each time through the loop). In the following
Sub procedure, which replaces every other value in an array
with 0 (zero), the counter variable increases by 2 each time the
loop repeats.
Note The
variable name after the Next statement is optional, but it can
make your code easier to read, especially if you have several
nested For loops.
For Each...Next
A For Each...Next loop is similar
to a For...Next loop, except that it repeats a group of
statements for each element in a collection of objects or in an
array, instead of repeating the statements a specified number
of times. This is especially useful if you don't know how many
elements are in a collection, or if the contents of the collection
might change as your procedure runs. The For Each
Next
statement uses the following syntax.
For Each element In group
Next element
When Visual Basic runs a For Each...Next
loop, it follows these steps:
The following Microsoft Excel example examines each cell in the
current region for cell A1 on the worksheet named "Sheet3"
and formats its contents as red if its value is less than 1.
The following Word example loops through all the revisions in
the current selection and accepts each one.
The variable name after the Next statement
c in the Microsoft
Excel example and myRev
in the Word example is optional, but it can make
your code easier to read, especially if you have several nested
For Each loops.
Important If
you want to delete all the objects in a collection, use a For...Next
loop instead of a For Each...Next loop. The following example
deletes all the slides in the active PowerPoint presentation.
The code in the following example, on the other hand, won't work
(it will delete every other slide in the presentation).
Keep the following restrictions in mind when using the For
Each...Next statement:
Nesting Control Structures
You can place control structures inside other control structures;
for instance, you can place an If...Then block within a
For Each...Next loop within another If...Then block,
and so on. A control structure placed inside another control structure
is said to be nested.
Exiting Loops and Procedures
Usually, your macros will run through loops and procedures from
beginning to end. There may be situations, however, in which leaving,
or exiting, a loop or procedure earlier than normal can save you
time by avoiding unnecessary repetition.
For example, if you're searching for a value in an array using
a For...Next loop and you find the value the first time
through the loop, there's no reason to search the rest of the
array you can stop repeating the loop and continue
with the rest of the procedure immediately. If an error occurs
in a procedure that makes the remainder of the procedure unnecessary,
you can exit the procedure immediately. You can cut a control
structure off early by using one of the Exit statements.
Although the Exit statements can be convenient, you should
use them only when it's absolutely necessary and only as a response
to an extraordinary condition (not in the normal flow of a loop
or procedure). Overusing Exit statements can make your
code difficult to read and debug.
Also , there may be a better way to skip portions of your macro.
For instance, instead of using an Exit statement inside
a For...Next loop while searching for a value in an array,
you could use a Do
Loop to search the array only while
an incremented index value is smaller than the array's upper bound
and a Boolean variable value is False, as shown
in the following example. When you find the array value, setting
the Boolean value to True causes the loop to stop.
You use the Exit Do statement
to exit directly from a Do
Loop, and you use the Exit
For statement to exit directly from a For loop, as
shown in the following example.
You use the Exit Sub and Exit
Function statements to exit a procedure. The following example
demonstrates the use of Exit Function.
To test Use
A single condition and run a single statement or a block of statements
If...Then
A single condition and choose between two statement blocks
If...Then...Else
More than one condition and run one of several statement blocks
If...Then...ElseIf
A single condition and run one of several statement blocks
Select Case
If thisVal < 0 Then thisVal = 0
If thisVal > 5 Then
thatVal = thisVal + 25
thisVal = 0
End If
If age < 16 Then
MsgBox "You are not old enough for a license."
Else
MsgBox "You can be tested for a license."
End If
Function Bonus(jobClass, salary, rating)
If jobClass = 1 Then
Bonus = salary * 0.1 * rating / 10
ElseIf jobClass = 2 Then
Bonus = salary * 0.09 * rating / 10
ElseIf jobClass = 3 Then
Bonus = salary * 0.07 * rating / 10
Else
Bonus = 0
End If
End Function
Function Bonus(jobClass, salary, rating)
Select Case jobClass
Case 1
Bonus = salary * 0.1 * rating / 10
Case 2
Bonus = salary * 0.09 * rating / 10
Case 3
Bonus = salary * 0.07 * rating / 10
Case 4, 5 'The expression list can contain several values...
Bonus = salary * 0.05 * rating / 5
Case 6 To 8 '...or be a range of values
Bonus = 150
Case Is > 8 '...or be compared to other values
Bonus = 100
Case Else
Bonus = 0
End Select
End Function
To Use
Test a condition at the start of the loop, run the loop only if the condition is True, and continue until the condition becomes False
Do While...Loop
Test a condition at the start of the loop, run the loop only if the condition is False, and continue until the condition becomes True
Do Until...Loop
Always run the loop once, test a condition at the end of the loop, continue while the condition is True, and stop when the condition becomes False
Do...Loop While
Always run the loop once, test a condition at the end of the loop, continue while the condition is False, and stop when the condition becomes True
Do...Loop Until
Run a loop a set number of times, using a loop counter that starts and ends at specified values and that changes value by a specified amount each time through the loop
For...Next
Run a loop once for each object in a collection
For Each...Next
Function CountStrings(longstring, target)
position = 1
Do While InStr(position, longstring, target) 'Returns True/False
position = InStr(position, longstring, target) + 1
Count = Count + 1
Loop
CountStrings = Count
End Function
Response = MsgBox("Do you want to process more data?", vbYesNo)
Do Until Response = vbNo
ProcessUserData 'Call procedure to process data
Response = MsgBox("Do you want to process more data?", vbYesNo)
Loop
Sub MakeBlue()
Set rSearch = Worksheets("sheet1").Range("a1:a10")
Set c = rSearch.Find("test")
If Not c Is Nothing Then
first = c.Address
Do
c.Font.ColorIndex = 5
Set c = rSearch.FindNext(c)
Loop While (Not c Is Nothing) And (c.Address <> first)
Else
MsgBox "not found"
End If
End Sub
Do
ProcessUserData 'Call procedure to process data
response = MsgBox("Do you want to process more data?", vbYesNo)
Loop Until response = vbNo
Sub BeepSeveral()
numBeeps = InputBox("How many beeps?")
For counter = 1 To numBeeps
Beep
Next counter
End Sub
Sub ClearArray(ByRef ArrayToClear())
For i = LBound(ArrayToClear) To UBound(ArrayToClear) Step 2
ArrayToClear(i) = 0
Next i
End Sub
statements
For Each c In Worksheets("sheet3").Range("a1").CurrentRegion.Cells
If c.Value < -1 Then c.Font.ColorIndex = 3
Next c
For Each myRev In Selection.Range.Revisions
myRev.Accept
Next myRev
Set allSlides = ActivePresentation.Slides
For s = allSlides.Count To 1 Step -1
allSlides.Item(s).Delete
Next
For Each s In ActivePresentation.Slides
s.Delete
Next
Function CountValues(rangeToSearch, searchValue)
If TypeName(rangeToSearch) <> "Range" Then
MsgBox "You can search only a range of cells."
Else
For Each c in rangeToSearch.cells
If c.Value = searchValue Then
counter = counter + 1
End If
Next c
End If
CountValues = counter
End Function
i = LBound(searchArray)
ub = UBound(searchArray)
foundIt = False
Do
If searchArray(i) = findThis Then foundIt = True
i = i + 1
Loop While i <= ub And Not foundIt
For Each c in rangeToSearch
If c.Value = searchValue Then
found = True
Exit For
End If
Next
For Each c in rangeToSearch
If c.Value = searchValue Then
counter = counter + 1
ElseIf c.Value = "Bad Data" Then
countValues = Null
Exit Function 'Stop testing and exit immediately.
End If
Next c