Programming Fundamentals
Programming Fundamentals
Programming Fundamentals
This chapter introduces the essential components of the Visual Basic language. After creating
the interface for your application using forms and controls, you will need to write the code that
defines the application's behavior. As with any modern programming language, Visual Basic
supports a number of common programming constructs and language elements.
Visual Basic is an object-based programming language. The mere mention of objects may cause
undue anxiety in many programmers. Don't worry: whether you realize it or not, you've been
dealing with objects most of your life. Once you understand a few basic concepts, objects
actually help to make programming easier than ever before.
If you've programmed in other languages, much of the material covered in this chapter will
seem familiar. While most of the constructs are similar to other languages, the event-driven
nature of Visual Basic introduces some subtle differences. Try and approach this material with
an open mind; once you understand the differences you can use them to your advantage.
If you're new to programming, the material in this chapter will serve as an introduction to the
basic building blocks for writing code. Once you understand the basics, you will be able to
create powerful applications using Visual Basic.
Topics
The Structure of a Visual Basic Application
An introduction to the various components or modules that make up a Visual Basic
application.
Before You Start Coding
A brief discussion of some of the considerations in designing an application.
Code Writing Mechanics
An introduction to the features of the Code Editor, plus the rules and regulations for
writing code.
Introduction to Variables, Constants and Data Types
An introduction to the basic elements of the Visual Basic language.
Introduction to Procedures
An introduction to Sub and Function procedures.
Introduction to Control Structures
An introduction to decision structures and loops.
Sample application
Vcr.vbp
Many of the code samples in this chapter are taken from the Vcr.vbp sample application
which is listed in the Samples directory.
An application is really nothing more than a set of instructions directing the computer to
perform a task or tasks. The structure of an application is the way in which the instructions are
organized; that is, where the instructions are stored and the order in which instructions are
executed.
Simple applications such as the classic "hello world" example have a simple structure;
organization isn't very important with a single line of code. As applications become more
complex, the need for organization or structure becomes obvious. Imagine the chaos that
would result if your application's code was allowed to execute in random order. In addition to
controlling the execution of an application, the structure is important to the programmer: how
easily can you find specific instructions within your application?
Because a Visual Basic application is based on objects, the structure of its code closely models
its physical representation on screen. By definition, objects contain data and code. The form
that you see on screen is a representation of the properties that define its appearance and
intrinsic behavior. For each form in an application, there is a related form module (with file
name extension .frm) that contains its code.
Figure 5.1
Each form module contains event procedures sections of code where you place the
instructions that will execute in response to specific events. Forms can contain controls. For
each control on a form, there is a corresponding set of event procedures in the form module. In
addition to event procedures, form modules can contain general procedures that are executed
in response to a call from any event procedure.
Code that isn't related to a specific form or control can be placed in a different type of module,
a standard module (.BAS). A procedure that might be used in response to events in several
different objects should be placed in a standard module, rather than duplicating the code in the
event procedures for each object.
A class module (.CLS) is used to create objects that can be called from procedures within your
application. Whereas a standard module contains only code, a class module contains both code
and data you can think of it as a control without a physical representation.
While "Managing Projects" describes which components you can add to an application, this
chapter explains how to write code in the various components that make up an application. By
default, your project contains a single form module. You can add additional form, class, and
standard modules, as needed. Class modules are discussed in "Programming with Objects."
z
Perhaps the most important (and often overlooked) part of creating an application in Visual
Basic is the design phase. While it's obvious that you need to design a user interface for your
application, it may not be as obvious that you need to design the structure of the code. The
way you structure your application can make a difference in its performance as well as in the
maintainability and usability of your code.
The code in a Visual Basic application is organized in a hierarchical fashion. A typical application
consists of one or more modules: a form module for each form in the application, optional
standard modules for shared code, and optional class modules. Each module contains one or
more procedures that contain the code: event procedures, Sub or Function procedures, and
Property procedures.
Determining which procedures belong in which module depends somewhat on the type of
application that you are creating. Because Visual Basic is based on objects, it helps to think of
your application in terms of the objects that it represents. The design of the sample application
for this chapter, Vcr.vbp, is based on the objects that comprise a video cassette recorder and a
television. The VCR application consists of two form modules, a standard module, and two class
modules. You can use the Object Browser to examine the structure of the project (Figure 5.2).
Figure 5.2
The main form for the VCR application (frmVCR) is a visual representation of a combination VCR
and television screen (Figure 5.3). It is composed of several objects that model those found in
the real world version. A group of Command buttons (cmdPlay, cmdRecord, and so on) mimic
the buttons used to operate a VCR. The software VCR also contains a clock (lblTime), a channel
indicator (lblChannel), function indicators (shpPlay, shpRecord, and so on), and a "picture
tube" (picTV). The event procedures for all of these objects are contained in the Vcr.frm form
module.
Figure 5.3
In many cases there are repetitive procedures that are shared by more than one object. For
example, when the Play, Rewind, or Record buttons are "pushed," the Pause and Stop buttons
need to be enabled. Rather than repeat this code in each button's Click event procedure, it's
better to create a shared Sub procedure that can be called by any button. If these procedures
need to be modified in the future, all of the modifications can be done in one place. This and
other shared procedures are contained in the standard module, Vcr.bas.
Some parts of a VCR aren't visible, such as the tape transport mechanism or the logic for
recording a television program. Likewise, some of the functions of the software VCR have no
visual representation. These are implemented as two class modules: Recorder.cls and Tape.cls.
Code to initiate the "recording" process is contained in the clsRecorder module; code to control
the direction and speed of the "tape" is contained in the clsTape module. The classes defined in
these modules have no direct references to any of the objects in the forms. Because they are
independent code modules, they could easily be reused to build an audio recorder without any
modifications.
In addition to designing the structure of your code, it's important to establish naming
conventions. By default, Visual Basic names the first form in a project Form1, the second
Form2, and so on. If you have several forms in an application, it's a good idea to give them
meaningful names to avoid confusion when writing or editing your code. Some suggested
naming conventions are presented in "Visual Basic Coding Conventions."
As you learn more about objects and writing code, you can refer to the VCR sample application
for examples of various different coding techniques.
Before you begin, it's important to understand the mechanics of writing code in Visual Basic.
Like any programming language, Visual Basic has its own rules for organizing, editing, and
formatting code.
The following topics introduce code modules and procedures, discuss the basics of using the
Code Editor, and cover basic rules for writing code.
z
Code Modules An introduction to the different types of code modules and the procedures
that they contain.
Code Basics
Code Modules
Code in Visual Basic is stored in modules. There are three kinds of modules: form, standard,
and class.
Simple applications can consist of just a single form, and all of the code in the application
resides in that form module. As your applications get larger and more sophisticated, you add
additional forms. Eventually you might find that there is common code you want to execute in
several forms. You don't want to duplicate the code in both forms, so you create a separate
module containing a procedure that implements the common code. This separate module
should be a standard module. Over time, you can build up a library of modules containing
shared procedures.
Each standard, class, and form module can contain:
z
Declarations. You can place constant, type, variable, and dynamic-link library (DLL)
procedure declarations at the module level of form, class or standard modules.
Procedures. A Sub, Function, or Property procedure contains pieces of code that can be
executed as a unit. These are discussed in the section "Procedures" later in this chapter.
Form Modules
Form modules (.FRM file name extension) are the foundation of most Visual Basic applications.
They can contain procedures that handle events, general procedures, and form-level
declarations of variables, constants, types, and external procedures. If you were to look at a
form module in a text editor, you would also see descriptions of the form and its controls,
including their property settings. The code that you write in a form module is specific to the
particular application to which the form belongs; it might also reference other forms or objects
within that application.
Standard Modules
Standard modules (.BAS file name extension) are containers for procedures and declarations
commonly accessed by other modules within the application. They can contain global (available
to the whole application) or module-level declarations of variables, constants, types, external
procedures, and global procedures. The code that you write in a standard module isn't
necessarily tied to a particular application; if you're careful not to reference forms or controls
by name, a standard module can be reused in many different applications.
Class Modules
Class modules (.CLS file name extension) are the foundation of object-oriented programming in
Visual Basic. You can write code in class modules to create new objects. These new objects can
include your own customized properties and methods. Actually, forms are just class modules
that can have controls placed on them and can display form windows.
For More Information For information about writing code in class modules, see
"Programming with Objects."
Note The Professional and Enterprise editions of Visual Basic also include ActiveX
Documents, ActiveX Designers, and User Controls. These introduce new types of modules
with different file name extensions. From the standpoint of writing code, these modules
should be considered the same as form modules.
The Visual Basic Code Editor is a window where you write most of your code. It is like a highly
specialized word processor with a number of features that make writing Visual Basic code a lot
easier. The Code Editor window is shown in Figure 5.4.
Figure 5.4
Because you work with Visual Basic code in modules, a separate Code Editor window is opened
for each module you select from the Project Explorer. Code within each module is subdivided
into separate sections for each object contained in the module. Switching between sections is
accomplished using the Object Listbox. In a form module, the list includes a general section, a
section for the form itself, and a section for each control contained on the form. For a class
module, the list includes a general section and a class section; for a standard module only a
general section is shown.
Each section of code can contain several different procedures, accessed using the Procedure
Listbox. The procedure list for a form module contains a separate section for each event
procedure for the form or control. For example, the procedure list for a Label control includes
sections for the Change, Click, and DblClick events, among others. Class modules list only the
event procedures for the class itself Initialize and Terminate. Standard modules don't list any
event procedures, because a standard module doesn't support events.
The procedure list for a general section of a module contains a single selection the
Declarations section, where you place module-level variable, constant, and DLL declarations. As
you add Sub or Function procedures to a module, those procedures are added in the Procedure
Listbox below the Declarations section.
Two different views of your code are available in the Code Editor window. You can choose to
view a single procedure at a time, or to view all of the procedures in the module with each
procedure separated from the next by a line (as shown in Figure 5.4). To switch between the
two views, use the View Selection buttons in the lower left-hand corner of the editor window.
The Auto Quick Info feature displays the syntax for statements and functions (Figure 5.6).
When you enter the name of a valid Visual Basic statement or function the syntax is shown
immediately below the current line, with the first argument in bold. After you enter the first
argument value, the second argument appears in bold. Auto Quick Info can also be accessed
with the CTRL+I key combination.
Figure 5.6
Bookmarks
Bookmarks can be used to mark lines of code in the Code Editor so that you can easily return to
them later. Commands to toggle bookmarks on or off as well as to navigate existing bookmarks
are available from the Edit, Bookmarks menu item, or from the Edit toolbar
For More Information For more information on key combinations to access these and other
functions in the Code Editor window, see "Code Window Keyboard Shortcuts."
Code Basics
This section presents information on code writing mechanics, including breaking and combining
lines of code, adding comments to your code, using numbers in code, and following naming
conventions in Visual Basic.
You can't follow a line-continuation character with a comment on the same line. There are also
In order to make your code more readable, however, it's better to place each statement on a
separate line.
For More Information
and File Formats."
Comments can follow a statement on the same line or can occupy an entire line. Both are
illustrated in the preceding code. Remember that comments can't follow a line-continuation
character on the same line.
Note You can add or remove comment symbols for a block of code by selecting two or
more lines of code and choosing the Comment Block or Uncomment Block buttons on the
Edit toolbar.
Octal
Hexadecimal
&O11
&H9
15
&O17
&HF
16
&O20
&H10
20
&O24
&H14
255
&O377
&HFF
You generally don't have to learn the hexadecimal or octal number system yourself because the
computer can work with numbers entered in any system. However, some number systems lend
themselves to certain tasks, such as using hexadecimals to set the screen and control colors.
A restricted keyword is a word that Visual Basic uses as part of its language. This includes
predefined statements (such as If and Loop), functions (such as Len and Abs), and operators
(such as Or and Mod).
For More Information
Your forms and controls can have the same name as a restricted keyword. For example, you
can have a control named Loop. In your code you cannot refer to that control in the usual way,
however, because Visual Basic assumes you mean the Loop keyword. For example, this code
causes an error:
Loop.Visible = True
To refer to a form or control that has the same name as a restricted keyword, you must either
qualify it or surround it with square brackets: [ ]. For example, this code does not cause an
error:
MyForm.Loop.Visible = True
[Loop].Visible = True
You can use square brackets in this way when referring to forms and controls, but not when
declaring a variable or defining a procedure with the same name as a restricted keyword.
Square brackets can also be used to force Visual Basic to accept names provided by other type
libraries that conflict with restricted keywords.
Note Because typing square brackets can get tedious, you might want to refrain from
using restricted keywords as the name of forms and controls. However, you can use this
technique if a future version of Visual Basic defines a new keyword that conflicts with an
existing form or control name when you update your code to work with the new version.
You often need to store values temporarily when performing calculations with Visual Basic. For
example, you might want to calculate several values, compare them, and perform different
operations on them, depending on the result of the comparison. You need to retain the values if
you want to compare them, but you don't need to store them in a property.
Visual Basic, like most programming languages, uses variables for storing values. Variables
have a name (the word you use to refer to the value the variable contains) and a data type
(which determines the kind of data the variable can store). Arrays can be used to store indexed
collections of related variables.
Constants also store values, but as the name implies, those values remain constant throughout
the execution of an application. Using constants can make your code more readable by
providing meaningful names instead of numbers. There are a number of built-in constants in
Visual Basic, but you can also create your own.
Data types control the internal storage of data in Visual Basic. By default, Visual Basic uses the
Variant data type. There are a number of other available data types that allow you to optimize
your code for speed and size when you don't need the flexibility that Variant provides.
For more detailed information, see:
z
Variables
Static Variables
Constants
Data Types
Arrays
Dynamic Arrays
Variables
In Visual Basic, you use variables to temporarily store values during the execution of an
application. Variables have a name (the word you use to refer to the value the variable
contains) and a data type (which determines the kind of data the variable can store).
You can think of a variable as a placeholder in memory for an unknown value. For example,
imagine you are creating a program for a fruit stand to track the sales of apples. You don't
know the price of an apple or the quantity sold until the sale actually occurs. You can use two
variables to hold the unknown values let's name them ApplePrice and ApplesSold. Each time
the program is run, the user supplies the values for the two variables. To calculate the total
sales and display it in a Textbox named txtSales, your code would look like this:
txtSales.txt = ApplePrice * ApplesSold
The expression returns a different total each time, depending on what values the user provides.
The variables allow you to make a calculation without having to know in advance what the
actual inputs are.
In this example, the data type of ApplePrice is Currency; the data type of ApplesSold is an
integer. Variables can represent many other values as well: text values, dates, various numeric
types, even objects.
Note that the equal sign in this example is an assignment operator, not an equality operator;
the value (10) is being assigned to the variable (ApplesSold).
Declaring Variables
To declare a variable is to tell the program about it in advance. You declare a variable with the
Dim statement, supplying a name for the variable:
Must be unique within the same scope, which is the range from which the variable can be
referenced a procedure, a form, and so on.
The optional As type clause in the Dim statement allows you to define the data type or object
type of the variable you are declaring. Data types define the type of information the variable
stores. Some examples of data types include String, Integer, and Currency. Variables can also
contain objects from Visual Basic or other applications. Examples of Visual Basic object types,
or classes, include Object, Form1, and TextBox.
For More Information For more information on objects, see "Programming with Objects"
and "Programming with Components." Data types are discussed in detail in the section, "Data
Types," later in this chapter.
There are other ways to declare variables:
z
Implicit Declaration
You don't have to declare a variable before using it. For example, you could write a function
where you don't need to declare TempVal before using it:
Function SafeSqr(num)
TempVal = Abs(num)
SafeSqr = Sqr(TempVal)
End Function
Visual Basic automatically creates a variable with that name, which you can use as if you had
explicitly declared it. While this is convenient, it can lead to subtle errors in your code if you
misspell a variable name. For example, suppose that this was the function you wrote:
Function SafeSqr(num)
TempVal = Abs(num)
SafeSqr = Sqr(TemVal)
End Function
At first glance, this looks the same. But because the TempVal variable was misspelled on the
next-to-last line, this function will always return zero. When Visual Basic encounters a new
name, it can't determine whether you actually meant to implicitly declare a new variable or you
just misspelled an existing variable name, so it creates a new variable with that name.
Explicit Declaration
To avoid the problem of misnaming variables, you can stipulate that Visual Basic always warn
you whenever it encounters a name not declared explicitly as a variable.
To explicitly declare variables
z
Place this statement in the Declarations section of a class, form, or standard module:
Option Explicit
or
From the Tools menu, choose Options, click the Editor tab and check the Require
Variable Declaration option. This automatically inserts the Option Explicit statement in
any new modules, but not in modules already created; therefore, you must manually add
Option Explicit to any existing modules within a project.
Had this statement been in effect for the form or standard module containing the SafeSqr
function, Visual Basic would have recognized TempVal and TemVal as undeclared variables
and generated errors for both of them. You could then explicitly declare TempVal:
Function SafeSqr(num)
Dim TempVal
TempVal = Abs(num)
SafeSqr = Sqr(TemVal)
End Function
Now you'd understand the problem immediately because Visual Basic would display an error
message for the incorrectly spelled TemVal. Because the Option Explicit statement helps you
catch these kinds of errors, it's a good idea to use it with all your code.
Note The Option Explicit statement operates on a per-module basis; it must be placed in
the Declarations section of every form, standard, and class module for which you want
Visual Basic to enforce explicit variable declarations. If you select Require Variable
Declaration, Visual Basic inserts Option Explicit in all subsequent form, standard, and class
modules, but does not add it to existing code. You must manually add Option Explicit to any
existing modules within a project.
The scope of a variable defines which parts of your code are aware of its existence. When you
declare a variable within a procedure, only code within that procedure can access or change the
value of that variable; it has a scope that is local to that procedure. Sometimes, however, you
need to use a variable with a broader scope, such as one whose value is available to all the
procedures within the same module, or even to all the procedures in your entire application.
Visual Basic allows you to specify the scope of a variable when you declare it.
Scoping Variables
Depending on how it is declared, a variable is scoped as either a procedure-level (local) or
module-level variable.
Scope
Private
Public
Procedure-level
Module-level
or
Static intPermanent As Integer
Values in local variables declared with Static exist the entire time your application is running
while variables declared with Dim exist only as long as the procedure is executing.
Local variables are a good choice for any kind of temporary calculation. For example, you can
create a dozen different procedures containing a variable called intTemp. As long as each
intTemp is declared as a local variable, each procedure recognizes only its own version of
intTemp. Any one procedure can alter the value in its local intTemp without affecting
intTemp variables in other procedures.
At the module level, there is no difference between Private and Dim, but Private is preferred
because it readily contrasts with Public and makes your code easier to understand.
To make a module-level variable available to other modules, use the Public keyword to declare
the variable. The values in public variables are available to all procedures in your application.
Like all module-level variables, public variables are declared in the Declarations section at the
top of the module. For example:
Public intTemp As Integer
Note You can't declare public variables within a procedure, only within the Declarations
section of a module.
For More Information
Topics."
intX, is declared in the first standard module, Module1. The Test procedure sets
The second variable, which has the same name, intX, is declared in the second standard
module, Module2. Again, a procedure named Test sets its value:
Public intX As Integer
' Declare Module2's intX.
Sub Test()
' Set the value for the intX variable in Module2.
intX = 2
End Sub
The third intX variable is declared in the form module. And again, a procedure named Test
sets its value.
Sub Test()
' Set the value for the intX variable in the form.
intX = 3
End Sub
Each of the three command buttons' Click event procedures calls the appropriate Test
procedure and uses MsgBox to display the values of the three variables.
Private Sub Command1_Click()
Module1.Test
MsgBox Module1.intX
End Sub
Run the application and click each of the three command buttons. You'll see the separate
references to the three public variables. Notice in the third command button's Click event
procedure, you don't need to specify Form1.Test when calling the form's Test procedure, or
Form1.intX when calling the value of the form's Integer variable. If there are multiple
procedures and variables with the same name, Visual Basic takes the value of the more local
variable, which in this case, is the Form1 variable.
In general, when variables have the same name but different scope, the more local variable
always shadows (that is, it is accessed in preference to) less local variables. So if you also had
a procedure-level variable named Temp, it would shadow the public variable Temp within that
module.
Static Variables
In addition to scope, variables have a lifetime, the period of time during which they retain their
value. The values in module-level and public variables are preserved for the lifetime of your
application. However, local variables declared with Dim exist only while the procedure in which
they are declared is executing. Usually, when a procedure is finished executing, the values of
its local variables are not preserved and the memory used by the local variables is reclaimed.
The next time the procedure is executed, all its local variables are reinitialized.
However, you can preserve the value of a local variable by making the variable static. Use the
Static keyword to declare one or more variables inside a procedure, exactly as you would with
the Dim statement:
Static Depth
For example, the following function calculates a running total by adding a new value to the total
of previous values stored in the static variable Accumulate:
Function RunningTotal(num)
Static ApplesSold
ApplesSold = ApplesSold + num
RunningTotal = ApplesSold
End Function
If ApplesSold was declared with Dim instead of Static, the previous accumulated values
would not be preserved across calls to the function, and the function would simply return the
same value with which it was called.
You can produce the same result by declaring ApplesSold in the Declarations section of the
module, making it a module-level variable. Once you change the scope of a variable this way,
however, the procedure no longer has exclusive access to it. Because other procedures can
access and change the value of the variable, the running totals might be unreliable and the
code would be more difficult to maintain.
This makes all the local variables in the procedure static regardless of whether they are
declared with Static, Dim, Private, or declared implicitly. You can place Static in front of any
Sub or Function procedure heading, including event procedures and those declared as Private.
Constants
Often you'll find that your code contains constant values that reappear over and over. Or you
may find that the code depends on certain numbers that are difficult to remember numbers
that, in and of themselves, have no obvious meaning.
In these cases, you can greatly improve the readability of your code and make it easier to
maintain by using constants. A constant is a meaningful name that takes the place of a
number or string that does not change. Although a constant somewhat resembles a variable,
you can't modify a constant or assign a new value to it as you can to a variable. There are two
sources for constants:
z
In Visual Basic, constant names are in a mixed-case format, with a prefix indicating the object
library that defines the constant. Constants from the Visual Basic and Visual Basic for
applications object libraries are prefaced with "vb" for instance, vbTileHorizontal.
The prefixes are intended to prevent accidental collisions in cases where constants have
identical names and represent different values. Even with prefixes, it's still possible that two
object libraries may contain identical constants representing different values. Which constant is
referenced in this case depends on which object library has the higher priority. For information
on changing the priority of object libraries, see the "References Dialog Box."
To be absolutely sure you avoid constant name collisions, you can qualify references to
constants with the following syntax:
[libname.][modulename.]constname
Libname is usually the class name of the control or library. Modulename is the name of the
module that defines the constant. Constname is the name of the constant. Each of these
elements is defined in the object library, and can be viewed in the Object Browser.
You can place more than one constant declaration on a single line if you separate them with
commas:
Public Const conPi = 3.14, conMaxPlanets = 9, _
conWorldPop = 6E+09
The expression on the right side of the equal sign ( = ) is often a number or literal string, but it
can also be an expression that results in a number or string (although that expression can't
contain calls to functions). You can even define constants in terms of previously defined
constants:
Const conPi2 = conPi * 2
Once you define constants, you can place them in your code to make it more readable. For
example:
Static SolarSystem(1 To conMaxPlanets)
If numPeople > conWorldPop Then Exit Sub
To create a constant that exists only within a procedure, declare it within that procedure.
To create a constant available to all procedures within a module, but not to any code
outside that module, declare it in the Declarations section of the module.
To create a constant available throughout the application, declare the constant in the
Declarations section of a standard module, and place the Public keyword before Const.
Public constants cannot be declared in a form or class module.
For More Information For more information regarding scope, see "Understanding the Scope
of Variables" earlier in this chapter.
If a cycle occurs, Visual Basic generates an error when you attempt to run your application. You
cannot run your code until you resolve the circular reference. To avoid creating a cycle, restrict
all your public constants to a single module or, at most, a small number of modules.
Data Types
Variables are placeholders used to store values; they have names and data types. The data
type of a variable determines how the bits representing those values are stored in the
computer's memory. When you declare a variable, you can also supply a data type for it. All
variables have a data type that determines what kind of data they can store.
By default, if you don't supply a data type, the variable is given the Variant data type. The
Variant data type is like a chameleon it can represent many different data types in different
situations. You don't have to convert between these types of data when assigning them to a
Variant variable: Visual Basic automatically performs any necessary conversion.
If you know that a variable will always store data of a particular type, however, Visual Basic can
handle that data more efficiently if you declare a variable of that type. For example, a variable
to store a person's name is best represented as a string data type, because a name is always
composed of characters.
Data types apply to other things besides variables. When you assign a value to a property, that
value has a data type; arguments to functions also have data types. In fact, just about
anything in Visual Basic that involves data also involves data types.
You can also declare arrays of any of the fundamental types.
For More Information For more information, see the section, "Arrays," later in this chapter.
Selecting data types to improve your application's performance is discussed in "Designing for
Performance and Compatibility."
Note If you do not supply a data type, the variable is given the default type. In the
preceding example, the variables Test and Amount are of the Variant data type. This may
surprise you if your experience with other programming languages leads you to expect all
variables in the same declaration statement to have the same specified type (in this case,
Integer).
Writing to files
Calling DLLs
All operators that work on integers work with the Byte data type except unary minus. Since
Byte is an unsigned type with the range 0-255, it cannot represent a negative number. So for
unary minus, Visual Basic coerces the Byte to a signed integer first.
All numeric variables can be assigned to each other and to variables of the Variant type. Visual
Basic rounds off rather than truncates the fractional part of a floating-point number before
assigning it to an integer.
For More Information
Issues."
You can then assign strings to this variable and manipulate it using string functions:
S = "Database"
S = Left(S, 4)
By default, a string variable or argument is a variable-length string; the string grows or shrinks
as you assign new data to it. You can also declare strings that have a fixed length. You specify
a fixed-length string with this syntax:
String * size
For example, to declare a string that is always 50 characters long, use code like this:
Dim EmpName As String * 50
If you assign a string of fewer than 50 characters, EmpName is padded with enough trailing
spaces to total 50 characters. If you assign a string that is too long for the fixed-length string,
Visual Basic simply truncates the characters.
Because fixed-length strings are padded with trailing spaces, you may find the Trim and RTrim
functions, which remove the spaces, useful when working with them.
Fixed-length strings in standard modules can be declared as Public or Private. In forms and
class modules, fixed-length strings must be declared Private.
For More Information
Reference.
intX = strY
Visual Basic will automatically coerce the variables to the appropriate data type. You should use
caution when exchanging strings and numbers; passing a non-numeric value in the string will
cause a run-time error to occur.
When other numeric data types are converted to Date, values to the left of the decimal
represent date information, while values to the right of the decimal represent time. Midnight is
0, and midday is 0.5. Negative whole numbers represent dates before December 30, 1899.
When declaring object variables, try to use specific classes (such as TextBox instead of
Control or, in the preceding case, Database instead of Object) rather than the generic
Object. Visual Basic can resolve references to the properties and methods of objects with
specific types before you run an application. This allows the application to perform faster at run
time. Specific classes are listed in the Object Browser.
When working with other applications' objects, instead of using a Variant or the generic Object,
declare objects as they are listed in the Classes list in the Object Browser. This ensures that
Visual Basic recognizes the specific type of object you're referencing, allowing the reference to
be resolved at run time.
For More Information For more information on creating and assigning objects and object
variables, see "Creating Objects" later in this chapter.
Conversion
function
Converts an expression to
Cbool
Boolean
Cbyte
Byte
Ccur
Currency
Cdate
Date
CDbl
Double
Cint
Integer
CLng
Long
CSng
Single
CStr
String
Cvar
Variant
CVErr
Error
Note Values passed to a conversion function must be valid for the destination data type or
an error occurs. For example, if you attempt to convert a Long to an Integer, the Long must
be within the valid range for the Integer data type.
For More Information
While you can perform operations on Variant variables without much concern for the kind of
data they contain, there are some traps you must avoid.
z
If you perform arithmetic operations or functions on a Variant, the Variant must contain
something that is a number. For details, see the section, "Numeric Values Stored in
Variants," in "Advanced Variant Topics."
If you are concatenating strings, use the & operator instead of the + operator. For
details, see the section, "Strings Stored in Variants," in "Advanced Variant Topics."
In addition to being able to act like the other standard data types, Variants can also contain
three special values: Empty, Null, and Error.
When a Variant contains the Empty value, you can use it in expressions; it is treated as either 0
or a zero-length string, depending on the expression.
The Empty value disappears as soon as any value (including 0, a zero-length string, or Null) is
assigned to a Variant variable. You can set a Variant variable back to Empty by assigning the
keyword Empty to the Variant.
Expressions involving Null always result in Null. Thus, Null is said to "propagate" through
expressions; if any part of the expression evaluates to Null, the entire expression
evaluates to Null.
Passing Null, a Variant containing Null, or an expression that evaluates to Null as an
argument to most functions causes the function to return Null.
Null values propagate through intrinsic functions that return Variant data types.
You can use the IsNull function to test if a Variant variable contains Null:
If IsNull(X) And IsNull(Y) Then
Z = Null
Else
Z = 0
End If
If you assign Null to a variable of any type other than Variant, a trappable error occurs.
Assigning Null to a Variant variable doesn't cause an error, and Null will propagate through
expressions involving Variant variables (though Null does not propagate through certain
functions). You can return Null from any Function procedure with a Variant return value.
Variables are not set to Null unless you explicitly assign Null to them, so if you don't use Null in
your application, you don't have to write code that tests for and handles it.
For More Information
Language Reference.
A variant always takes up 16 bytes, no matter what you store in it. Objects, strings,
and arrays are not physically stored in the Variant; in these cases, four bytes of the Variant
are used to hold either an object reference, or a pointer to the string or array. The actual
data are stored elsewhere.
Most of the time, you don't have to be concerned with what internal representation Visual Basic
is using for a particular variable; Visual Basic handles conversions automatically. If you want to
know what value Visual Basic is using, however, you can use the VarType function.
For example, if you store values with decimal fractions in a Variant variable, Visual Basic always
uses the Double internal representation. If you know that your application does not need the
high accuracy (and slower speed) that a Double value supplies, you can speed your calculations
by converting the values to Single, or even to Currency:
If VarType(X) = 5 Then X = CSng(X)
With an array variable, the value of VarType is the sum of the array and data type return
values. For example, this array contains Double values:
Private Sub Form_Click()
Dim dblSample(2) As Double
MsgBox VarType(dblSample)
End Sub
Future versions of Visual Basic may add additional Variant representations, so any code you
write that makes decisions based on the return value of the VarType function should gracefully
handle return values that are not currently defined.
For More Information For information about the VarType function, see "VarType Function"
in the Language Reference. To read more about arrays, see "Arrays" later in this chapter. For
details on converting data types, see "Data Types" earlier in this chapter.
When Visual Basic converts a representation that is not numeric (such as a string containing a
number) to a numeric value, it uses the Regional settings (specified in the Windows Control
Panel) to interpret the thousands separator, decimal separator, and currency symbol.
Thus, if the country setting in the Windows Control Panel is set to United States, Canada, or
Australia, these two statements would return true:
IsNumeric("$100")
IsNumeric("1,560.50")
However, the reverse would be the case the first two would return false and the second two
true if the country setting in the Windows Control Panel was set to Germany.
If you assign a Variant containing a number to a string variable or property, Visual Basic
converts the representation of the number to a string automatically. If you want to explicitly
convert a number to a string, use the CStr function. You can also use the Format function to
convert a number to a string that includes formatting such as currency, thousands separator,
and decimal separator symbols. The Format function automatically uses the appropriate
symbols according to the Regional Settings Properties dialog box in the Windows Control Panel.
For More Information See "Format Function" and topics about the conversion functions in
the Language Reference. For information on writing code for applications that will be distributed
in foreign markets, see "International Issues."
X = 6
Print X + Y, X & Y
End Sub
67
67
Note Visual Basic stores strings internally as Unicode. For more information on Unicode,
see "International Issues."
You can also perform math on date/time values. Adding or subtracting integers adds or
subtracts days; adding or subtracting fractions adds or subtracts time. Therefore, adding 20
adds 20 days, while subtracting 1/24 subtracts one hour.
The range for dates stored in Variant variables is January 1, 0100, to December 31, 9999.
Calculations on dates don't take into account the calendar revisions prior to the switch to the
Gregorian calendar, however, so calculations producing date values earlier than the year in
which the Gregorian calendar was adopted (1752 in Britain and its colonies at that time; earlier
or later in other countries) will be incorrect.
You can use date/time literals in your code by enclosing them with the number sign (#), in the
same way you enclose string literals with double quotation marks (""). For example, you can
compare a Variant containing a date/time value with a literal date:
If SomeDate > #3/6/93# Then
Similarly, you can compare a date/time value with a complete date/time literal:
If SomeDate > #3/6/93 1:20pm# Then
If you do not include a time in a date/time literal, Visual Basic sets the time part of the value to
midnight (the start of the day). If you do not include a date in a date/time literal, Visual Basic
sets the date part of the value to December 30, 1899.
Visual Basic accepts a wide variety of date and time formats in literals. These are all valid
date/time values:
SomeDate
SomeDate
SomeDate
SomeDate
=
=
=
=
#3-6-93 13:20#
#March 27, 1993 1:20am#
#Apr-2-93#
#4 April 1993#
In the same way that you can use the IsNumeric function to determine if a Variant variable
contains a value that can be considered a valid numeric value, you can use the IsDate function
to determine if a Variant contains a value that can be considered a valid date/time value. You
can then use the CDate function to convert the value into a date/time value.
For example, the following code tests the Text property of a text box with IsDate. If the
property contains text that can be considered a valid date, Visual Basic converts the text into a
date and computes the days left until the end of the year:
Dim SomeDate, daysleft
If IsDate(Text1.Text) Then
SomeDate = CDate(Text1.Text)
daysleft = DateSerial(Year(SomeDate) + _
1, 1, 1) - SomeDate
Text2.Text = daysleft & " days left in the year."
Else
MsgBox Text1.Text & " is not a valid date."
End If
For More Information For information about the various date/time functions, see "Date
Function" in the Language Reference.
Arrays
If you have programmed in other languages, you're probably familiar with the concept of
arrays. Arrays allow you to refer to a series of variables by the same name and to use a
number (an index) to tell them apart. This helps you create smaller and simpler code in many
situations, because you can set up loops that deal efficiently with any number of cases by using
the index number. Arrays have both upper and lower bounds, and the elements of the array are
contiguous within those bounds. Because Visual Basic allocates space for each index number,
avoid declaring an array larger than necessary.
Note
The arrays discussed in this section are arrays of variables, declared in code. They
are different from the control arrays you specify by setting the Index property of controls at
design time. Arrays of variables are always contiguous; unlike control arrays, you cannot
load and unload elements from the middle of the array.
All the elements in an array have the same data type. Of course, when the data type is Variant,
the individual elements may contain different kinds of data (objects, strings, numbers, and so
on). You can declare an array of any of the fundamental data types, including user-defined
types (described in the section, "Creating Your Own Data Types," in "More About
Programming") and object variables (described in "Programming with Objects").
In Visual Basic there are two types of arrays: a fixed-size array which always remains the same
size, and a dynamic array whose size can change at run-time. Dynamic arrays are discussed in
more detail in the section "Dynamic Arrays" later in this chapter.
To create a public array, use the Public statement in the Declarations section of a module
to declare the array.
To create a module-level array, use the Private statement in the Declarations section of a
module to declare the array.
To create a local array, use the Private statement in a procedure to declare the array.
' 15 elements.
' 21 elements.
The first declaration creates an array with 15 elements, with index numbers running from 0 to
14. The second creates an array with 21 elements, with index numbers running from 0 to 20.
The default lower bound is 0.
To specify a lower bound, provide it explicitly (as a Long data type) using the To keyword:
Dim Counters(1 To 15) As Integer
Multidimensional Arrays
Sometimes you need to keep track of related information in an array. For example, to keep
track of each pixel on your computer screen, you need to refer to its X and Y coordinates. This
can be done using a multidimensional array to store the values.
With Visual Basic, you can declare arrays of multiple dimensions. For example, the following
statement declares a two-dimensional 10-by-10 array within a procedure:
Static MatrixA(9, 9) As Double
You can extend this to more than two dimensions. For example:
Dim MultiD(3, 1 To 10, 1 To 15)
This declaration creates an array that has three dimensions with sizes 4 by 10 by 15. The total
number of elements is the product of these three dimensions, or 600.
Note
When you start adding dimensions to an array, the total storage needed by the array
increases dramatically, so use multidimensional arrays with care. Be especially careful with
Variant arrays, because they are larger than other data types.
Dynamic Arrays
Sometimes you may not know exactly how large to make an array. You may want to have the
capability of changing the size of the array at run time.
A dynamic array can be resized at any time. Dynamic arrays are among the most flexible and
convenient features in Visual Basic, and they help you to manage memory efficiently. For
example, you can use a large array for a short time and then free up memory to the system
when you're no longer using the array.
The alternative is to declare an array with the largest possible size and then ignore array
elements you don't need. However, this approach, if overused, might cause the operating
environment to run low on memory.
To create a dynamic array
1. Declare the array with a Public statement (if you want the array to be public) or Dim
statement at the module level (if you want the array to be module level), or a Static or
Dim statement in a procedure (if you want the array to be local). You declare the array as
dynamic by giving it an empty dimension list.
Dim DynArray()
The ReDim statement can appear only in a procedure. Unlike the Dim and Static statements,
ReDim is an executable statement it makes the application carry out an action at run time.
The ReDim statement supports the same syntax used for fixed arrays. Each ReDim can change
the number of elements, as well as the lower and upper bounds, for each dimension. However,
the number of dimensions in the array cannot change.
ReDim DynArray(4 to 12)
The ReDim statement shown here allocates a matrix of 20 by 30 integers (at a total size of 600
elements). Alternatively, the bounds of a dynamic array can be set using variables:
ReDim Matrix1(X, Y)
Note You can assign strings to resizable arrays of bytes. An array of bytes can also be
assigned to a variable-length string. Be aware that the number of bytes in a string varies
among platforms. On Unicode platforms the same string contains twice as many bytes as it
does on a non-Unicode platform.
Only the upper bound of the last dimension in a multidimensional array can be changed when
you use the Preserve keyword; if you change any of the other dimensions, or the lower bound
of the last dimension, a run-time error occurs. Thus, you can use code like this:
ReDim Preserve Matrix(10, UBound(Matrix, 2) + 1)
For More Information For information about dynamic arrays, see "ReDim Statement" in the
Language Reference. To learn more about object arrays, see "Programming with Objects."
Introduction to Procedures
You can simplify programming tasks by breaking programs into smaller logical components.
These components called procedures can then become building blocks that let you
enhance and extend Visual Basic.
Procedures are useful for condensing repeated or shared tasks, such as frequently used
calculations, text and control manipulation, and database operations.
There are two major benefits of programming with procedures:
z
Procedures allow you to break your programs into discrete logical units, each of which
you can debug more easily than an entire program without procedures.
Procedures used in one program can act as building blocks for other programs, usually
with little or no modification.
Property procedures can return and assign values, and set references to objects.
To learn more about Sub and Function procedures, see the following topics:
z
Sub Procedures
Function Procedures
Sub Procedures
A Sub procedure is a block of code that is executed in response to an event. By breaking the
code in a module into Sub procedures, it becomes much easier to find or modify the code in
your application.
The syntax for a Sub procedure is:
General Procedures
A general procedure tells the application how to perform a specific task. Once a general
procedure is defined, it must be specifically invoked by the application. By contrast, an event
procedure remains idle until called upon to respond to events caused by the user or triggered
by the system.
Why create general procedures? One reason is that several different event procedures might
need the same actions performed. A good programming strategy is to put common statements
in a separate procedure (a general procedure) and have your event procedures call it. This
eliminates the need to duplicate code and also makes the application easier to maintain. For
example, the VCR sample application uses a general procedure called by the click events for
several different scroll buttons. Figure 5.7 illustrates the use of a general procedure. Code in
the Click events calls the ButtonManager Sub procedure, which runs its own code, and then
returns control to the Click event procedure.
Figure 5.7
Event Procedures
When an object in Visual Basic recognizes that an event has occurred, it automatically invokes
the event procedure using the name corresponding to the event. Because the name establishes
an association between the object and the code, event procedures are said to be attached to
forms and controls.
z
An event procedure for a control combines the control's actual name (specified in the
Name property), an underscore (_), and the event name. For instance, if you want a
command button named cmdPlay to invoke an event procedure when it is clicked, use the
procedure cmdPlay_Click.
An event procedure for a form combines the word "Form," an underscore, and the event
name. If you want a form to invoke an event procedure when it is clicked, use the
procedure Form_Click. (Like controls, forms do have unique names, but they are not used
in the names of event procedures.) If you are using the MDI form, the event procedure
combines the word "MDIForm," an underscore, and the event name, as in
MDIForm_Load.
End Sub
Although you can write event procedures from scratch, it's easier to use the code procedures
provided by Visual Basic, which automatically include the correct procedure names. You can
select a template in the Code Editor window by selecting an object from the Object box and
then selecting a procedure from the Procedure box.
It's also a good idea to set the Name property of your controls before you start writing event
procedures for them. If you change the name of a control after attaching a procedure to it, you
must also change the name of the procedure to match the new name of the control. Otherwise,
Visual Basic won't be able to match the control to the procedure. When a procedure name does
not match a control name, it becomes a general procedure.
For More Information
Visual Basic recognizes a variety of events for each kind of form and
Function Procedures
Visual Basic includes built-in, or intrinsic functions, like Sqr, Cos or Chr. In addition, you can
use the Function statement to write your own Function procedures.
The syntax for a Function procedure is:
Generally, you call a function by including the function procedure name and arguments on
the right side of a larger statement or expression (returnvalue = function()).
Function procedures have data types, just as variables do. This determines the type of
the return value. (In the absence of an As clause, the type is the default Variant type.)
You return a value by assigning it to the procedurename itself. When the Function
procedure returns a value, this value can then become part of a larger expression.
For example, you could write a function that calculates the third side, or hypotenuse, of a right
triangle, given the values for the other two sides:
Function Hypotenuse (A As Integer, B As Integer) _
As String
Hypotenuse = Sqr(A ^ 2 + B ^ 2)
End Function
You call a Function procedure the same way you call any of the built-in functions in Visual
Basic:
Label1.Caption = Hypotenuse(CInt(Text1.Text), _
CInt(Text2.Text))
strX = Hypotenuse(Width, Height)
For More Information For additional details about the Function procedure, see "Function
Statement" in the Language Reference. The techniques for calling all types of procedures are
discussed in the section, "Calling Procedures," later in this chapter.
Type a procedure heading in the Code window and press ENTER. The procedure heading
can be as simple as Sub or Function followed by a name. For example, you can enter
either of the following:
Sub UpdateForm ()
Function GetCoord ()
Visual Basic responds by completing the template for the new procedure.
To view an existing general procedure, select "(General)" from the Object box in the Code
window, and then select the procedure in the Procedure box.
or
To view an event procedure, select the appropriate object from the Object box in the
Code window, and then select the event in the Procedure box.
Calling Procedures
The techniques for calling procedures vary, depending on the type of procedure, where it's
located, and how it's used in your application. The following sections describe how to call Sub
and Function procedures.
A Sub procedure differs from a Function procedure in that a Sub procedure cannot be called by
using its name within an expression. A call to a Sub is a stand-alone statement. Also, a Sub
does not return a value in its name as does a function. However, like a Function, a Sub can
modify the values of any variables passed to it.
There are two ways to call a Sub procedure:
' Both of these statements call a Sub named MyProc.
Call MyProc (FirstArgument, SecondArgument)
MyProc FirstArgument, SecondArgument
Note that when you use the Call syntax, arguments must be enclosed in parentheses. If you
omit the Call keyword, you must also omit the parentheses around the arguments.
It's also possible to call a function just like you would call a Sub procedure. The following
statements both call the same function:
Call Year(Now)
Year Now
When you call a function this way, Visual Basic throws away the return value.
Procedures in Forms
All calls from outside the form module must point to the form module containing the procedure.
If a procedure named SomeSub is in a form module called Form1, then you can call the
procedure in Form1 by using this statement:
Call Form1.SomeSub(arguments)
However, unlike a form, the class name cannot be used as the qualifier when referencing an
instance of the class. The instance of the class must be first be declared as an object variable
(in this case, DemoClass) and referenced by the variable name.
For More Information You can find details on object variables and class modules in
"Programming with Objects."
Usually the code in a procedure needs some information about the state of the program to do
its job. This information consists of variables passed to the procedure when it is called. When a
variable is passed to a procedure, it is called an argument.
For More Information Details on Visual Basic data types are presented earlier in this
chapter. You can also see the Language Reference for specific data types.
In the case where an optional argument is not provided, the argument is actually assigned as a
variant with the value of Empty. The example above shows how to test for missing optional
arguments using the IsMissing function.
Dim x As Integer
Dim y As Integer
Dim intSum As Integer
Sub Sum(ParamArray intNums())
For Each x In intNums
y = y + x
Next x
intSum = y
End Sub
Private Sub Command1_Click()
Sum 1, 3, 5, 7, 8
List1.AddItem intSum
End Sub
This is especially useful if your procedures have several optional arguments that you do not
always need to specify.
Named arguments are not supported by methods on objects in the Visual Basic (VB)
object library. They are supported by all language keywords in the Visual Basic for
applications (VBA) object library.
In syntax, named arguments are shown as bold and italic. All other arguments are shown
in italic only.
Important You cannot use named arguments to avoid entering required arguments. You
can omit only the optional arguments. For Visual Basic (VB) and Visual Basic for applications
(VBA) object libraries, the Object Browser encloses optional arguments with square brackets
[ ].
For More Information
Reference.
Control structures allow you to control the flow of your program's execution. If left unchecked
by control-flow statements, a program's logic will flow through statements from left to right,
and top to bottom. While some very simple programs can be written with only this
unidirectional flow, and while some flow can be controlled 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.
To learn more about specific control structures, see the following topics:
z
Decision Structures
Loop Structures
Decision Structures
Visual Basic procedures can test conditions and then, depending on the results of that test,
perform different operations. The decision structures that Visual Basic supports include:
z
If...Then
If...Then...Else
Select Case
If...Then
Use an If...Then structure to execute one or more statements conditionally. You can use either
a single-line syntax or a multiple-line block syntax:
If condition Then
statements
End If
The condition is usually a comparison, but it can be any expression that evaluates to a numeric
value. Visual Basic interprets this value as True or False; a zero numeric value is False, and any
nonzero numeric value is considered True. If condition is True, Visual Basic executes all the
statements following the Then keyword. You can use either single-line or multiple-line syntax to
execute just one statement conditionally (these two examples are equivalent):
If anyDate < Now Then anyDate = Now
If anyDate < Now Then
anyDate = Now
End If
Notice that the single-line form of If...Then does not use an End If statement. If you want to
execute more than one line of code when condition is True, you must use the multiple-line
block If...Then...End If syntax.
If anyDate < Now Then
anyDate = Now
Timer1.Enabled = False
End If
If...Then...Else
Use an If...Then...Else block to define several blocks of statements, one of which will execute:
If condition1 Then
[statementblock-1]
[ElseIf condition2 Then
[statementblock-2]] ...
[Else
[statementblock-n]]
End If
Visual Basic first tests condition1. If it's False, Visual Basic proceeds to test condition2, and so
on, until it finds a True condition. When it finds a True condition, Visual Basic executes the
corresponding statement block and then executes the code following the End If. As an option,
you can include an Else statement block, which Visual Basic executes if none of the conditions
are True.
If...ThenElseIf is really just a special case of If...Then...Else. Notice that you can have any
number of ElseIf clauses, or none at all. You can include an Else clause regardless of whether
you have ElseIf clauses.
For example, your application could perform different actions depending on which control in a
menu control array was clicked:
Private Sub mnuCut_Click (Index As Integer)
If Index = 0 Then
CopyActiveControl
ClearActiveControl
ElseIf Index = 1 Then
CopyActiveControl
ElseIf Index = 2 Then
ClearActiveControl
Else
PasteActiveControl
End If
End Sub
Notice that you can always add more ElseIf parts to your If...Then structure. However, this
syntax can get tedious to write when each ElseIf compares the same expression to a different
value. For this situation, you can use a Select Case decision structure.
For More Information
Select Case
Visual Basic provides the Select Case structure as an alternative to If...Then...Else for
selectively executing one block of statements from among multiple blocks of statements. A
Select Case statement provides capability similar to the If...Then...Else statement, but it makes
code more readable when there are several choices.
A Select Case structure works with a single test expression that is evaluated once, at the top of
the structure. Visual Basic then compares the result of this expression with the values for each
Case in the structure. If there is a match, it executes the block of statements associated with
that Case:
Notice that the Select Case structure evaluates an expression once at the top of the structure.
In contrast, the If...Then...Else structure can evaluate a different expression for each ElseIf
statement. You can replace an If...Then...Else structure with a Select Case structure only if the
If statement and each ElseIf statement evaluates the same expression.
Loop Structures
Loop structures allow you to execute one or more lines of code repetitively. The loop structures
that Visual Basic supports include:
z
Do...Loop
For...Next
For Each...Next
Do...Loop
Use a Do loop to execute a block of statements an indefinite number of times. There are several
variations of the Do...Loop statement, but each evaluates a numeric condition to determine
whether to continue execution. As with If...Then, the condition must be a value or expression
that evaluates to False (zero) or to True (nonzero).
In the following Do...Loop, the statements execute as long as the condition is True:
Do While condition
statements
Loop
When Visual Basic executes this Do loop, it first tests condition. If condition is False (zero), it
skips past all the statements. If it's True (nonzero), Visual Basic executes the statements and
then goes back to the Do While statement and tests the condition again.
Consequently, the loop can execute any number of times, as long as condition is nonzero or
True. The statements never execute if condition is initially False. For example, this procedure
counts the occurrences of a target string within another string by looping as long as the target
string is found:
Function CountStrings (longstring, target)
Dim position, count
position = 1
Do While InStr(position, longstring, target)
position = InStr(position, longstring, target)_
+ 1
count = count + 1
Loop
CountStrings = count
End Function
If the target string doesn't occur in the other string, then InStr returns 0, and the loop doesn't
execute.
Another variation of the Do...Loop statement executes the statements first and then tests
condition after each execution. This variation guarantees at least one execution of statements:
Do
statements
Loop While condition
Two other variations are analogous to the previous two, except that they loop as long as
condition is False rather than True.
Loop zero or more times
Do Until condition
statements
Loop
Do
statements
Loop Until condition
For...Next
Do loops work well when you don't know how many times you need to execute the statements
in the loop. When you know you must execute the statements a specific number of times,
however, a ForNext loop is a better choice. Unlike a Do loop, a For loop uses a variable called
a counter that increases or decreases in value during each repetition of the loop. The syntax is:
start must be less than or equal to end or the statements in the loop will not execute. If
increment is negative, start must be greater than or equal to end for the body of the loop to
execute. If Step isn't set, then increment defaults to 1.
In executing the For loop, Visual Basic:
1. Sets counter equal to start.
2. Tests to see if counter is greater than end. If so, Visual Basic exits the loop.
(If increment is negative, Visual Basic tests to see if counter is less than end.)
3. Executes the statements.
4. Increments counter by 1 or by increment, if it's specified.
5. Repeats steps 2 through 4.
This code prints the names of all the available Screen fonts:
Private Sub Form_Click ()
Dim I As Integer
For i = 0 To Screen.FontCount
Print Screen.Fonts(i)
Next
End Sub
In the VCR sample application, the HighlightButton procedure uses a For...Next loop to step
through the controls collection of the VCR form and show the appropriate Shape control:
Sub HighlightButton(MyControl As Variant)
Dim i As Integer
For i = 0 To frmVCR.Controls.Count - 1
If TypeOf frmVCR.Controls(i) Is Shape Then
If frmVCR.Controls(i).Name = MyControl Then
frmVCR.Controls(i).Visible = True
Else
frmVCR.Controls(i).Visible = False
End If
End If
Next
End Sub
For Each...Next
A For Each...Next loop is similar to a For...Next loop, but 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 helpful if you don't know how many elements are
in a collection.
Here is the syntax for the For Each...Next loop:
For example, the following Sub procedure opens Biblio.mdb and adds the name of each table to
a list box.
Sub ListTableDefs()
Dim objDb As Database
Dim MyTableDef as TableDef
Set objDb = OpenDatabase("c:\vb\biblio.mdb", _
True, False)
For Each MyTableDef In objDb.TableDefs()
List1.AddItem MyTableDef.Name
Next MyTableDef
End Sub
z
z
For collections, element can only be a Variant variable, a generic Object variable, or an
object listed in the Object Browser.
For arrays, element can only be a Variant variable.
You cannot use For Each...Next with an array of user-defined types because a Variant
cannot contain a user-defined type.
Notice that the first Next closes the inner For loop and the last For closes the outer For loop.
Likewise, in nested If statements, the End If statements automatically apply to the nearest
prior If statement. Nested Do...Loop structures work in a similar fashion, with the innermost
Loop statement matching the innermost Do statement.
As this example illustrates, an Exit statement almost always appears inside an If statement or
Select Case statement nested inside the loop.
When you use an Exit statement to break out of a loop, the value of the counter variable
differs, depending on how you leave the loop:
z
When you complete a loop, the counter variable contains the value of the upper bound
When you exit a loop prematurely, the counter variable retains its value subject to the
usual rules on scope.
When you iterate off the end of a collection, the counter variable contains Nothing if it's
an Object data type, and contains Empty if it's a Variant data type.
When you create an application in Visual Basic, you work with objects. You can use objects
provided by Visual Basic such as controls, forms, and data access objects. You can also
control other applications' objects from within your Visual Basic application. You can even
create your own objects, and define additional properties and methods for them.
The following topics discuss objects in detail:
z
z
What is an Object?
What is an Object?
An object is a combination of code and data that can be treated as a unit. An object can be a
piece of an application, like a control or a form. An entire application can also be an object. The
following table describes examples of the types of objects you can use in Visual Basic.
Example
Description
Command button
Form
Database
Chart
The controls on the Toolbox in Visual Basic represent classes. The object known as a
control doesn't exist until you draw it on a form. When you create a control, you're
creating a copy or instance of the control class. That instance of the class is the object
you refer to in your application.
The form you work with at design time is a class. At run time, Visual Basic creates an
instance of the form's class.
The Properties window displays the class and Name property of objects in your Visual Basic
application, as shown in Figure 5.8.
Figure 5.8
All objects are created as identical copies of their class. Once they exist as individual objects,
their properties can be changed. For example, if you draw three command buttons on a form,
each command button object is an instance of the CommandButton class. Each object shares a
common set of characteristics and capabilities (properties, methods, and events), defined by
the class. However, each has its own name, can be separately enabled and disabled, can be
placed in a different location on the form, and so on.
For simplicity, most of the material outside of this chapter won't make many references to an
object's class. Just remember that the term "list box control," for example, means "an instance
of the ListBox class."
An object provides code you don't have to write. For example, you could create your own File
Open and File Save dialog boxes, but you don't have to. Instead, you can use the common
dialog control (an object) provided by Visual Basic. You could write your own scheduling and
resource management code, but you don't have to. Instead, you can use the Calendar,
Resources, and Task objects provided by Microsoft Project.
You could use these objects to create a checkbook application like the one shown in Figure 5.9.
This saves you time because you don't have to write the code to reproduce the functionality
provided by the Microsoft Excel and Word objects.
Figure 5.9
Visual Basic objects support properties, methods, and events. In Visual Basic, an object's data
(settings or attributes) are called properties, while the various procedures that can operate on
the object are called its methods. An event is an action recognized by an object, such as
clicking a mouse or pressing a key, and you can write code to respond to that event.
You can change an object's characteristics by changing its properties. Consider a radio: One
property of a radio is its volume. In Visual Basic, you might say that a radio has a "Volume"
property that you can adjust by changing its value. Assume you can set the volume of the radio
from 0 to 10. If you could control a radio with Visual Basic, you might write code in a procedure
that changes the value of the "Volume" property from 3 to 5 to make the radio play louder:
Radio.Volume = 5
In addition to properties, objects have methods. Methods are a part of objects just as
properties are. Generally, methods are actions you want to perform, while properties are the
attributes you set or retrieve. For example, you dial a telephone to make a call. You might say
that telephones have a "Dial" method, and you could use this syntax to dial the seven-digit
number 5551111:
Phone.Dial 5551111
Objects also have events. Events are triggered when some aspect of the object is changed. For
example, a radio might have a "VolumeChange" event. A telephone might have a "Ring" event.
object.property = expression
The following statements demonstrate how you set properties:
Text1.Top = 200
' Sets the Top property to 200 twips.
Text1.Visible = True
' Displays the text box.
Text1.Text = "hello"
' Displays 'hello' in the text
' box.
You get the value of a property when you want to find the state of an object before your code
performs additional actions (such as assigning the value to another object). For example, you
can return the Text property of a text box control to determine the contents of the text box
before running code that might change the value.
In most cases, to get the value of a property, you use the following syntax:
variable = object.property
You can also get a property value as part of a more complex expression, without assigning the
property to a variable. In the following code example, the Top property of the new member of a
control array is calculated as the Top property of the previous member, plus 400:
Private Sub cmdAdd_Click()
' [statements]
optButton(n).Top = optButton(n-1).Top + 400
' [statements]
End Sub
Tip If you're going to use the value of a property more than once, your code will run faster
if you store the value in a variable.
object.method
In this example, the Refresh method repaints the picture box:
Picture1.Refresh
Some methods, such as the Refresh method, don't have arguments and don't return values.
If the method takes more than one argument, you separate the arguments with a comma. For
example, the Circle method uses arguments specifying the location, radius, and color of a circle
on a form:
' Draw a blue circle with a 1200-twip radius.
Form1.Circle (1600, 1800), 1200, vbBlue
If you keep the return value of a method, you must enclose the arguments in parentheses. For
example, the GetData method returns a picture from the Clipboard:
Picture = Clipboard.GetData (vbCFBitmap)
If there is no return value, the arguments appear without parentheses. For example, the
AddItem method doesn't return a value:
List1.AddItem "yourname"
For More Information See the Language Reference for the syntax and arguments for all
methods provided by Visual Basic.
When you put two command buttons on a form, they are separate objects with distinct Name
property settings (Command1 and Command2), but they share the same class
CommandButton.
They also share the characteristic that they're on the same form. You've seen earlier in this
chapter that a control on a form is also contained by the form. This puts controls in a hierarchy.
To reference a control you may have to reference the form first, in the same way you may have
to dial a country code or area code before you can reach a particular phone number.
The two command buttons also share the characteristic that they're controls. All controls have
common characteristics that make them different from forms and other objects in the Visual
Basic environment. The following sections explain how Visual Basic uses collections to group
objects that are related.
Object Hierarchies
An object hierarchy provides the organization that determines how objects are related to each
other, and how you can access them. In most cases, you don't need to concern yourself with
the Visual Basic object hierarchy. However:
z
When manipulating another application's objects, you should be familiar with that
application's object hierarchy. For information on navigating object hierarchies, see
"Programming with Components."
When working with data access objects, you should be familiar with the Data Access
Object hierarchy.
There are some common cases in Visual Basic where one object contains others. These are
described in the following sections.
sequentially beginning at 0; this is the member's index number. For example, the Controls
collection contains all the controls on a given form, as shown in Figure 5.10. You can use
collections to simplify code if you need to perform the same operation on all the objects in a
collection.
Figure 5.10
Controls collection
For example, the following code scrolls through the Controls collection and lists each member's
name in a list box.
Dim MyControl as Control
For Each MyControl In Form1.Controls
' For each control, add its name to a list box.
List1.AddItem MyControl.Name
Next MyControl
Specify the name of the member. The following expressions are equivalent:
Controls("List1")
Controls!List1
Once you're able to address all the members collectively, and single members individually, you
can apply properties and methods using either approach:
' Set the Top property of the list box control to 200.
Controls!List1.Top = 200
or
Dim MyControl as Control
For Each MyControl In Form1.Controls()
' Set the Top property of each member to 200.
MyControl.Top = 200
Next MyControl
Two different forms can contain controls that have the same name
Both forms can have a list box named lstAcctNo. You can specify exactly which one you want to
use by referring to the form containing the list box:
frmReceivable.lstAcctNo.AddItem 1201
or
frmPayable.lstAcctNo.AddItem 1201
Description
Forms
Controls
Printers
and Graphics." For details on the forms and controls collections, see the Language Reference.
Frame control
This example demonstrates moving a command button around from container to container on a
form. Open a new project, and draw a frame control, picture box control and a command
button on the form.
The following code in the form's click event increments a counter variable, and uses a Select
Case loop to rotate the command button from container to container.
Private Sub Form_Click()
Static intX as Integer
Select Case intX
Case 0
Set Command1.Container = Picture1
Command1.Top= 0
Command1.Left= 0
Case 1
Set Command1.Container = Frame1
Command1.Top= 0
Command1.Left= 0
Case 2
Set Command1.Container = Form1
Command1.Top= 0
Command1.Left= 0
End Select
intX = intX + 1
End Sub
Creating Objects
The easiest way to create an object is to double-click a control in the Toolbox. However, to
realize the full benefit of all the objects available in Visual Basic and from other applications,
you can use Visual Basic's programmability features to create objects at run time.
z
You can create your own objects "from scratch" with class modules.
You can create your own collections with the Collection object.
For More Information Other chapters show you how to access objects. The CreateObject
and GetObject functions, for example, are discussed in "Programming with Components."
z
z
Variable names are often shorter and easier to remember than the values they contain
(or, in this case, the objects they refer to).
Variables can be changed to refer to other objects while your code is running.
Referring to a variable that contains an object is more efficient than repeatedly referring
to the object itself.
Using an object variable is similar to using a conventional variable, but with one additional step
assigning an object to the variable:
z
For example, you can declare an object variable that refers to a form in the application called
frmMain:
Dim FormVar As New frmMain
You can also declare an object variable that can refer to any form in the application:
Dim anyForm As Form
Similarly, you can declare an object variable that can refer to any text box in your application:
Dim anyText As TextBox
You can also declare an object variable that can refer to a control of any type:
Dim anyControl As Control
Notice that you can declare a form variable that refers to a specific form in the application, but
you cannot declare a control variable that refers to a particular control. You can declare a
control variable that can refer to a specific type of control (such as TextBox or ListBox), but not
to one particular control of that type (such as txtEntry or List1). However, you can assign
a particular control to a variable of that type. For example, for a form with a list box called
lstSample, you could write:
Dim objDemo As ListBox
Set objDemo = lstSample
frmAccountDisplay!txtAccountBalance
You can shorten this code significantly if you use a control variable:
Dim Bal As TextBox
Set Bal = frmAccountDisplay!txtAccountBalance
If Bal.Text < 0 Then
Bal.BackColor = 0
Bal.ForeColor = 255
End If
Specific object variables must refer to one specific type of object or class. A specific form
variable can refer to only one form in the application (though it can refer to one of many
instances of that form). Similarly, a specific control variable can refer to only one particular
type of control in your application, such as TextBox or ListBox. To see an example, open a new
project and place a text box on a form. Add the following code to the form:
Private Sub Form_Click()
Dim anyText As TextBox
Set anyText = Text1
anyText.Text = "Hello"
End Sub
Run the application, and click the form. The Text property of the text box will be changed to
"Hello."
Generic object variables can refer to one of many specific types of objects. A generic form
variable, for example, can refer to any form in an application; a generic control variable can
refer to any control on any form in an application. To see an example, open a new project and
place several frame, label, and command button controls on a form, in any order. Add the
following code to the form:
Private Sub Form_Click()
Dim anyControl As Control
Set anyControl = Form1.Controls(3)
anyControl.Caption = "Hello"
End Sub
Run the application, and click the form. The caption of the control you placed third in sequence
on the form will be changed to "Hello."
There are four generic object types in Visual Basic:
Generic Object
Type
Object referenced
Form
Any form in the application (including MDI children and the MDI
form).
Control
MDIForm
The MDI form in the application (if your application has one).
Object
Any object.
Generic object variables are useful when you don't know the specific type of object a variable
will refer to at run time. For example, if you want to write code that can operate on any form in
the application, you must use a generic form variable.
Note Because there can be only one MDI form in the application, there is no need to use
the generic MDIForm type. Instead, you can use the specific MDIForm type (MDIForm1, or
whatever you specified for the Name property of the MDI form) whenever you need to
declare a form variable that refers to the MDI form. In fact, because Visual Basic can resolve
references to properties and methods of specific form types before you run your application,
you should always use the specific MDIForm type.
The generic MDIForm type is provided only for completeness; should a future version of
Visual Basic allow multiple MDI forms in a single application, it might become useful.
Forms as Objects
Forms are most often used to make up the interface of an application, but they're also objects
that can be called by other modules in your application. Forms are closely related to class
modules. The major difference between the two is that forms can be visible objects, whereas
class modules have no visible interface.
You can call the LateJobsCount procedure from another module using this statement:
Form1.LateJobsCount
Creating a new property for a form can be as simple as declaring a public variable in the form
module:
Public IDNumber As Integer
You can set and return the value of IDNumber on Form1 from another module using these two
statements:
Form1.IDNumber = 3
Text1.Text = Form1.IDNumber
You can also use Property procedures to add custom properties to a form.
For More Information
Objects."
Note You can call a variable, a custom method, or set a custom property on a form without
loading the form. This allows you to run code on a form without loading it into memory.
Also, referencing a control without referencing one of its properties or methods does not load
the form.
Each form you create at design time is a class. The New keyword can be used to create new
instances of that class. To see how this works, draw a command button and several other
controls on a form. Set the form's Name property to Sample in the Properties window. Add the
following code to your command button's Click event procedure:
Dim x As New Sample
x.Show
Run the application, and click the command button several times. Move the front-most form
aside. Because a form is a class with a visible interface, you can see the additional copies. Each
form has the same controls, in the same positions as on the form at design time.
Note To make a form variable and an instance of the loaded form persist, use a Static or
Public variable instead of a local variable.
You can also use New with the Set statement. Try the following code in a command button's
Click event procedure:
Dim f As Form1
Set f = New Form1
f.Caption = "hello"
f.Show
Using New with the Set statement is faster and is the recommended method.
The ShowFrm procedure in the class module creates a new instance of the class Form1, shows
the form, and then minimizes it.
Sub ShowFrm()
Dim frmNew As Form1
Set frmNew = New Form1
frmNew.Show
frmNew.WindowState = 1
End Sub
To use the example, run the application, and click the command button several times. You'll see
a minimized form icon appear on your desktop as each new instance of the ShowMe class is
created.
It's also possible to pass an object to an argument by reference and then, inside the procedure,
set the argument to a new object. To see how this works, open a project, and insert a second
form. Place a picture box control on each form. The following table shows the property settings
that need changes:
Object
Property
Setting
Name
Picture2
Picture
c:\vb\icons\arrows\arw01dn.ico
The Form1_Click event procedure calls the GetPicture procedure in Form2, and passes the
empty picture box to it.
Private Sub Form_Click()
Form2.GetPicture Picture1
End Sub
The GetPicture procedure in Form2 assigns the Picture property of the picture box on Form2 to
the empty picture box on Form1.
Private objX As PictureBox
Public Sub GetPicture(x As PictureBox)
' Assign the passed-in picture box to an object
' variable.
Set objX = x
' Assign the value of the Picture property to Form1
' picture box.
objX.Picture = picture2.Picture
End Sub
To use the example, run the application, and click Form1. You'll see the icon from Form2
appear in the picture box on Form1.
For More Information The previous topics are intended to serve as an introduction to
objects. To learn more, see "Programming with Objects" and "Programming with Components."