Sie sind auf Seite 1von 81

Chapter 2

Visual Basic for Applications


Excel 2007
2.1

Writing VBA Code

When an EXCEL workbook is opened, a project is created which consists of


Worksheets, modules of various types and any forms created by the programmer.
Code is written in modules. There is a module for each sheet and a general
module, but user-defined code is most often written in separate modules.
The code can then be exported and saved to a file, and imported into other
workbooks. Modules are written in the Visual Basic Editor (VBE). The VBE
can be called up from Excel by Alt-F11. Pressing Alt-F11 again gets one back
to Excel. The Menu item in Excel Developer | Codes | Visual Basic can also
be used to transfer to the IDE from Excel.
A code module consists of two parts, a Declarations section right at the top,
followed by a line and a remaining part below the line where code for routines
is written. The Declarations section can be blank. It contains options and
declarations of global properties of variables.
The VBA Project Window in the VBE shows a tree of the various parts of
your current project. The Project Window can be loaded into the VBE from
the View menu button.
To create a module in the project click an item in the project and use the
Insert menu.
1

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

When working with both EXCEL sheets and the VBE, it is sometimes convenient to press the middle button at the top right of each of these windows
and to tile the two one above the other by moving them and adjusting the
borders. Double clicking at the top bar of one of the windows expands (or
contracts) the window.
Three useful windows which can be included in the VBE display are:
Locals Window shows how all the variables in procedures change during
runtime
Immediate Window commands entered here are immediately executed
Watch Window allows you to monitor specific variables during execution.
These windows can be docked into your VBE window from the View menu.
If it becomes undocked, it can be redocked by double clicking the bar at the
top of the window.

Figure 2.1: The VBE Screen

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

2.2

Functions, Subroutines and Variables

Contents: Functions, Subroutines, Variables, Examples of a function and Sub,


Built-In Functions, Looping, Conditional Statements, Arguments and return
values of functions.

There are two types of user-definable procedures: functions and subroutines


(subs).
Functions. A function can return a value (if it does not, there is a default
value that it returns). User defined functions are defined (programmed) in a
module. Once defined, a function can be used to enter values in EXCEL cells,
in the same way as e.g. =SIN(180), or it can be used in other functions and
subs. In addition, there are system defined functions like LOG(). There are
such functions in both EXCEL and VBA. Many of the EXCEL functions are
also available in VBA. A function may NOT directly alter the characteristics
of the spreadsheet (colour, value, ...) other than by using it as a formula in
a cell (by inserting =fn(x).) The purpose of a function is to calculate a value
(and possibly to write it to EXCEL.)
Subs A subroutine does NOT return a value through its name as is the case
with functions. It MAY alter the characteristics of a spreadsheet, and can be
called from the spreadsheet, for example by going to the Developer | Code |
Macro menu. (Subs are also called macros.)
A at the beginning of a line indicates that the line is a comment.
A space followed by an underscore at the end of a line indicates that the
line is continued on the next line.

2.2.1

Variables

Variable names begin with a letter (uppercase or lowercase) and continue with
letters or numbers or underscore . Variable names are not case sensitive.
Each variable has a type. Some of the principal types are Integer, Long, Single,
Double, Boolean, String, Variant. (Long is an integer type, Double is a
real number type with double precision, Boolean can take values True, False).
The Variant type is a sort of hold-all, and all the other types can be accommodated in it. The type of a variable need not be declared (unless

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Option Explicit is set - see below), and if the type is not declared, it is
automatically of type Variant. The Variant type sets aside more memory
space than other types. At some stage, it is converted to house the actual
variable (of whatever type.) A useful application of Variant types is when
data is requested from a user which could be text or numeric. Putting it into
a Variant typed variable allows either format.
The Declarations (first section) of a module can contain Option statements
and certain variable declarations. A very useful option is
Option Explicit
This makes it compulsory for a variable to be either an argument of a function or sub, a function name or to be declared in a Dim dimension statement.
(Note that a function name is automatically declared (without a Dim statement), with type as stated at the end of the function declaration line and
the arguments are also automatically declared but a sub name is NOT.) The
dimension statement is of the form
Dim Str,Int,Rl
where Str,Int,Rl are variable names the types of the variables are not declared in this form so the three variables are of Variant type. Alternatively
Dim Str As String, Int As Integer, Dbl As Double, Var
types all the variables except for Var, which is then of Variant type by default.
Dbl is a double precision real number.
Note: You cannot use

Dim Str1,Str2,Str3 As String.

Scope of variables: If a variable is declared in the Declaration section it is


global to whole module. If it is declared in a function/subroutine it is local
to the subroutine. If it is declared as Public in the Declaration section, for
example by
Public Dim Rope As String
then it can be used in other modules/workbooks. If it is declared as Private
in the Declaration section then it can be used only by the routines in the
module. If it is declared as Static, it persists between calls of functions in
the module, and maintains its value.
Variables have default initial values (0 for numeric variables, the empty string
"" for strings, and so on.)
Note: 1. Option Explicit can be made to appear automatically in all modules
by setting the VBE menu Tools|Options|Editor tab, and ticking the checkbox

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

Require Variable Declaration.


2. It is often good practice to have one or more capital letters in a variable
name when typing it in the VBE, type it in small letters and the VBE
changes it to the form with capital(s) enabling you to guard against mistakes
(there will be no change if you have misspelled the variable name.)

2.2.2

An example of a user-defined function

The procedure QMinus below calculates the solution of the quadratic equation
Ax2 + Bx + C = 0
given by

B 2 4AC
2A
for the case A 6= 0, B 2 4AC 0. Very little error checking is done. QPlus
below calculates the other root. A more complete quadratic equation solver
will be the subject of a later exercise.
x=

Function QMinus(A As Double, B As Double, C As Double) As Double


Dim Delta As Double
Delta = B*B4*A*C
If Delta >= 0 Then QMinus = (BSQR(Delta))/2*A
Else QMinus = 999999
End Function
Variables A,B,C need not be declared in a Dim statement, and have types
double here.
The same holds for the variable QMinus (typed As Double at the end of
line 1). Omission of the typing results in Variant variables.
This is a one-line If-Then-Else statement - a multiline version will appear later.
SQR is a VBA function doing the same work as SQRT in Excel.
SQR is not available in Excel, and SQRT is not available in VBA.

QMinus, the function name, is assigned a value and this is the return value of
the function. If you use the function, (for example =QMinus(1,2,3) in an
Excel cell), then the final value of the variable QMinus is the value returned.

CHAPTER 2.
Function

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

QPlus(A As Double, B As Double, C As Double) As Double

Dim

Delta As Double
Delta = B*B4*A*C
If Delta >= 0 Then QPlus = QMinus(A,B,C) + B/A
Else QMinus = 999999
End Function

To test the function, tile EXCEL and VBE and enter in the Immediate Window
Range("C1") = QMinus(1,-3,2)
Range("D1") = QPlus(1,-3,2)
Debug.Print QPlus(1,-3,2)
MsgBox QMinus(1,-3,2)
Enter in the EXCEL sheet
=QMinus(1,-3,2) in C2
=QPlus(1,-3,2) in D2
If there are errors, the program will stop. Try to correct them and then
press the button with a triangle in the VBE to continue or the button with a
square to stop. You can stop before a line by clicking in the left margin next
to the line and running the function. A dot appears in the margin next to
the stoppage line. You can watch the variables at that time by looking in the
Locals window or setting a watch in the Watch window. Click the triangle
to run the function in which the cursor is sitting, or to continue. You can
run the function step by step by successively pressing F8. See the section on
Debugging for further information.
To exit from a function before the last statement use:
Exit Function
The words Public or Private before the word Function in the declaration
indicates, in the case of Public, that the function is usable outside the code
module and in the case of Public that it is not. The default is Public.

2.2.3

User-defined sub procedures

To access and change the WorkBook cells, we must use the object-oriented
aspects of VBA. This can be done by sub procedures. Function procedures
have limited ability to change the spreadsheet.

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

For Help on an identifier (e.g. Pattern or ColorIndex), place the cursor on


the identifier in the VBE and press F1.
A Subroutine has the form
Sub

MySub(A As Double, B As String)


Dim C As Integer
Range("A1").Value = "Value"

"Value" is a string

End Sub
More generally, there can be more than one Dim statement and more than
one line assigning to variables and evaluating functions and subs and using
methods and setting properties.
Remember that MySub is not available immediately as a variable, in contrast
to the case of functions.
For examples of manipulating ranges and cells see the forthcoming section on
working with ranges and cells in VBA.
To exit from a sub before the last statement:
Exit Sub
to call or run a sub from within another sub use:
MySub 2.34,"fine"
or
MySub A:=2.34,B:="fine"
There are other ways of calling subs. There is a method using Call but this
is undesirable. Sometimes subs (or methods) must be run using a bracket
notation for the arguments. This is discussed further in the section on Objects
below.
The sub can be declared as Public or Private as for functions, with default
Public.

2.2.4

Built-In functions

There are built-in functions in both VBA and Excel.


One can use both, in VBA, except for a few Excel functions that are in
both VBA and Excel, and for which only the VBA version can be used.

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

To find a list of built-in VBA functions. Click Help, the Index tab
and type Math in the box. Then press Enter and click on Math Functions.
There is also an item Derived Math Functions, but these must be entered
by the user as composites of the standard functions - they do not exist on
their own. Another route:
Help|Contents|VisualBasic Language References|Groups|Maths Functions.
Using EXCEL Functions in VBA. The correct way is to prefix the
function by
Application.WorksheetFunction
and then use the EXCEL function name. It will also work if WorksheetFunction
is omitted or if Application is replaced by Excel. Such a prefix is lengthy.
If you need to use it several times in a module, you can put the following
in the Declarations section:
Dim WSF as WorksheetFunction
In any function which uses EXCEL functions, you can put the statement
Set WSF = Application.WorksheetFunction
Then, for example,
WSF.cosh(2)
will give you the value of cosh 2. If you get some error, check that the
function you use is actually allowable for use in VBA.
To enter a Formula into a Cell from VBA
It is often necessary to do calculations on the worksheet rather than in
VBA. An example of this is in the use of Solver routines, which require
its inputs to be calculated by EXCEL formulae evaluated in cells.
To enter a formula from VBA which will output to a single cell, use the
following format:
Activesheet.Range("A1").Formula = "=NormSInv(Rand())
The formula is evaluated and the result placed in cell A1.
To enter a formula from VBA which will output an array, use the following
format:
Activesheet.Range("A1:A5").FormulaArray = "=MMult(C1:G5,I1:I5)"
The formula is evaluated and the result placed in range A1:A5.

2.2.5

Looping

The following is the most common looping structure:

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

Dim i as Integer, a As Double


For i = 1 to 10
a = a + i
(other statements)
Next i
The i in Next i may be omitted. Other structures are
Do
Do
Do
Do

While (condition) ... Loop


Until (condition) ... Loop
... Loop Until (condition)
... Loop While (condition)

where (condition) is an expression which must evaluate to either True or


False.
For looping through object collections (see later) use
For Each . . . Next

2.2.6

Conditional Statements

The following illustrate the multiline If-Then-Else statement, the single line
version and the Select Case statement.
Multiline If-Then-Else
Dim Number, Digits, MyString
Number = 53
Initialize variable.
If Number < 10 Then
Digits = 1
ElseIf Number < 100 Then
Condition evaluates to True so the next statement is executed.
Digits = 2
Else
Digits = 3
End If
Single Line If-Then-Else
Assign a value using the single-line form of syntax.
If Digits = 1 Then MyStr = "One"
OR
If Digits = 1 Then MyStr = "One" Else MyStr = "More than one"
Select Case

10

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Dim Number
Number = 8
Initialize variable
Select Case Number
Evaluate Number
Case 1 To 5
Number between 1
Debug.Print "Between 1 and 5"
The following is
Case 6, 7, 8
Number between 6
Debug.Print "Between 6 and 8"
Case 9
Debug.Print "Number is 9"
Case Else
Other values
Debug.Print "Not between 1 and
End Select

and 5, inclusive
the only Case clause that evaluates to True.
and 8

9"

Note: In the phrase Select Case Number we could replace Number by any
variable or expression that evaluates to a number or a character string.

2.2.7

Arguments and Return Values of Functions

A function returns a value, and this can be used in a cell to assign a value,
e.g. =f(q). You may want to return several values from a function or sub for
use in another function or sub.
A function declaration is of the form
Function functionname(var1 As Integer, var2, var3() As Single,
Optional var4 As Double) As Boolean
If the type is not declared, then a variable is of type Variant.
functionname, var1, var2, var3, var4 are all available for use in the
body of the function, and cannot be dimensioned with Dim or ReDim.
Variable var3() is an array argument which takes its dimension from the
input array at runtime - see the section on arrays later.
functionname can be assigned a value in a function - in this case a
Boolean value. If we had omitted As Boolean then functionname would
have been of type variant. See below for discussion of optional variables.
If we have a sub declaration, then it must be of the form:

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

11

Sub subname(var1 As Integer, var2, var3() As Single, Optional


var4 As Double)
subname is not automatically a variable which can be used, and need
NOT be assigned a value.
When using a function, make sure that the constants or variables assigned
to each argument are of the correct type as given in the declaration. For
example, it cannot be that one is of type Double and the other type
Variant.
Calling arguments by Reference and by Value
Function or Sub arguments are called by Reference. This means that the
addresses of the arguments are passed to the function. Whatever is in these
addresses is used. If the values of the variables are changed by the function
or sub, then these new values are stored in the addresses, whose values as a
result are changed. In this way you can return values to another function or
sub - set the variable to contain the returned values in the calling sub with
Dim statements, and make them arguments to the function or sub called.
If you do not want the argument in the calling function or sub to change
then call the arguments by value:
Sub gh (ByVal N As Integer) . . . End Sub
This passes only the values (in a temporary copy) to the calling procedure.
Since the function does not know the address of the variable that is passed,
the value of the variable cannot be changed by the function. Arrays cannot be passed as ByVal arguments to a function or sub. In the following
example, the values of a,b,c at the end of the sub tt are 3.1, 0 and 7.1
respectively. (Note that since call by reference is the default, the inclusion
of ByRef in the first line of function tt is unnecessary.)
Function tf(ByRef a As Double, ByVal b As Double) As Double
a=3.1
b=4.1
tt=7.1
End Function
Sub
Dim
a =
b =
c =
c =
End

tt()
a As Double, b As Double, c As Double
0
0
0
tf(a,b)
Sub

12

CHAPTER 2.

2.2.8

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Optional Arguments

In the functions we have been writing, all arguments are compulsory, that is,
they must be supplied. It is possible to make some arguments optional by
using declarations of the form:
Function Opt(intNumber As Integer, Optional strWord As String)
Then legal calls are of the form var=Opt(1,"go") and var=Opt(1). If Opt is
a sub, then use
Sub Opt(intNumber As Integer, Optional strWord As String)
Opt intNumber:= 1, strWord:= "go"
Opt intNumber:= 1
All compulsory arguments should go before the optional ones, to enable one
to use the Opt(1) form, since the called arguments must appear in order, and
it may not be clear what is omitted.
To test whether an optional argument has been used, the IsMissing boolean
function can be used in the function or sub provided that the variable
has Variant type:
If IsMissing(strWord) Then GoTo Stop
If the variable does not have type Variant then one can assign a default value
to the variable and then check in the procedure whether the variable still has
the default, in which case it is missing:
Function Opt2(intN As Integer, Optional strW As String = "Default1")
If strW="Default1" Then GoTo Stop
It is also possible to have as arguments a variable number of parameters by
using the ParamArray argument. See below.
Parameter Arrays as Arguments - Passing a Variable Number of
Arguments
This section requires arrays and should be read after the later section on
arrays, but the material is relevant to this section. A parameter array can
be used to pass an array of arguments to a procedure. One does not have to
know the number of elements in the array when you define the procedure.

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

13

One uses the ParamArray keyword to denote a parameter array. The array
must be declared as an array of type Variant, and it must be the last argument
in the procedure definition.
The following example shows how one might define a procedure with a parameter array.
Sub AnyNumberArgs(strName As String, ParamArray intScores() As
Variant)
Dim i As Integer
Debug.Print strName; "
Scores"
Use UBound function to determine upper limit of array.
For i = 0 To UBound(intScores())
Debug.Print "
"; intScores(i)
Next
End Sub
The following examples show how you can call this procedure.
AnyNumberArgs "Jamie", 10, 26, 32, 15, 22, 24, 16
AnyNumberArgs "Kelly", "High", "Low", "Average", "High"
Note: Another way of passing a variable length argument list is to declare say
the last argument of a function or sub as a Variant. Then feed the arguments
into the variable by feeding in an array. One can then use the above procedure
with Ubound to find out how many arguments have been passed and access
them as above. This has many advantages as a range object can be passed
to the variant and its values are then available to the function. However, see
the function maxRange below for another method.
Further Examples
The function maximum illustrates the writing of a program with an arbitrary
number of variables. The function hypotenuse avoids squaring large numbers
and then taking their square root, thereby reducing the possible sizes of the
inputs. The function maxRange inputs a range of cells and finds the number
of rows and columns in the input. This is useful for inputting data.
Function maximum(ParamArray inputs() As Variant)
Dim i As Integer
maximum = inputs(0)

14

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

For i = 1 To UBound(inputs())
If inputs(i) > maximum Then maximum = inputs(i)
Next
End Function
Function minimum(ParamArray inputs() As Variant)
Dim i As Integer
minimum = inputs(0)
For i = 1 To UBound(inputs())
If inputs(i) < minimum Then minimum = inputs(i)
Next
End Function
Function hypotenuse(x As Double, y As Double) As Double
Dim temp As Double
If x > y Then
temp = y / x
hypotenuse = x * Sqr(1 + temp ^ 2)
Else
temp = x / y
hypotenuse = y * Sqr(1 + temp ^ 2)
End If
End Function
Function maxRange(strRange As String) As Double
Dim ran As Range, i As Integer, j As Integer
Set ran = Range(strRange)
maxRange = ran.Cells(1, 1)
For i = 1 To ran.Rows.Count
For j = 1 To ran.Columns.Count
If ran.Cells(i, j) > maxRange Then maxRange = ran.Cells(i, j)
Next j
Next i
End Function
Sub
Dim
m =
h =
r =
End

tstmax()
m As Double, h As Double, r As Double
maximum(1, 2, 3, Application.Pi())
hypotenuse(311111111111, 411111111111)
maxRange("A1:E2")
Sub

2.2. FUNCTIONS, SUBROUTINES AND VARIABLES

15

2.2.9 Running a function whose identity is passed to another


function

We often have to pass a function (or sub) to another function (or sub). For
example, in Newtons method, we need to tell the function implementing
the method which function to use for in order to find the root and what its
derivative is. We would like to pass this as an argument. There is a VBA
function Run which takes as first argument the string that is the function
name and as subsequent arguments the arguments of the function to be run.
The output is the value that would have resulted had we run the function in
the normal way. We give an example.

Function newt(fn As String, fnder As String, N As Integer, guess As Double) _


As Double
Dim i As Integer, z As Double, y As Double z = guess
For i = 1 To N
y = Run(fnder, z)
If y = 0 Then
Exit Function
Else
z = z - Run(fn, z) / y
End If
Next i
newt = z
End Function
Function qd(x As Double) As Double
qd = x ^ 2 - 3
End Function
Function qdder(x As Double) As Double
qdder = 2 * x
End Function
Sub
Dim
d =
End

tst()
Calculates the square root of 3 by Newtons Method
d As Double
newt("qd", "qdder", 100, 3)
Sub

16

CHAPTER 2.

2.3

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Working with Ranges and Cells in VBA

The following indicate how to refer to Range and Cells objects and their
properties:
Object
Application

Description
The entire EXCEL spreadsheet that is currently open
The default value (when omitted) is the current workbook
Sheets("Sheet2")
WorkSheet named Sheet2 of current application
The default value (when omitted) is the current active sheet
Range("A1:B3")
The cells in this range
Range("A1").Name
e.g. Range("A1").Name = "X"
Range("A1").Formula
e.g. Range("A1").Formula = "=C1"
Range("A1").Value
e.g. Range("A1").Value = 1.2
(Value may be omitted after Range, as it is the default)
Range("A1").Font.Name
= "Times New Roman"
Range("A1").Font.Size
= 11
Range("A1").Font.Fontstyle
= "Bold"
Range("A1").Font.Superscript
= True
Range("A1").Font.Subscript
= False
Range("A1").Font.ColorIndex
= 4
1=black;2=white;3;4;5=R;G;B (Look up ColorIndex in VBE Help)
Range("A1").Interior.ColorIndex
=5 ColorIndex is a property of Interior
Range("A1").Interior.Pattern
See VBE Help under Pattern
Range("A1").Interior.PatternColorIndex
Range("A1").Borders(xlEdgeRight)
See Help
Range("A1").Borders.LineStyle
= xlContinuous
Range("A1").Borders.Weight
= xlThick
Range("A1").Borders.ColorIndex
= 3
With Range("A1").Borders
Way to avoid repeating prefixes
.LineStyle = xlContinuous
.Weight = xlThick
.ColorIndex = 3
var = .ColorIndex
Assigns the value of ColorIndex to a variable
End With
Range("B2:C5").BorderAround weight:=xlMedium
Cells(i,j)
The row i, column j cell of the active worksheet
Note that the indices are 1-based
Cells(3,2)
Cell B3
Range("B2").Cells(2,3)
D3
Range("B3:C10").Cells(i,j)
Cell (i,j) relative to B3 as (1,1)

2.3. WORKING WITH RANGES AND CELLS IN VBA

Range(Cells(2,3),Cells(4,5))

17

So this is the cell in the 2 + i row, 1+j co


Another way of writing C2:E4

Tile EXCEL and the VBE and enter variations of the above property settings
in the Immediate Window.
The Cells Property and Looping through Cells
A way of referring to cells and ranges is with the Cells property. See examples
in the previous list. This may be used, for example, to loop through a range
of cells:
For i = 1 To 10
For j = 1 To 12
matrix(i,j) = Range("B2").Cells(i,j).Value
Next
Next
Alternatively:
For i = 1 To 10
For j = 1 To 12
matrix(i,j) = Range(Chr(Asc("B") - 1 + j) & i).Value
Next
Next
where Chr() converts a positive integer to the character with that number in
the ASCII character set and Asc() converts a character to its number in the
ASCII character set.
The property Value of the Range object is the default property. Thus Range("A1").Value
and Range("A1") both return the Value property value.
To get some idea on how to do spreadsheet tasks in VBA, you can do the
process in EXCEL while recording the code Excel uses in a module. The code
is almost always cumbersome and NEEDS MUCH EDITING to get it concise.
In EXCEL, use the menu items in Developer | Code.
Enter a name for the Macro (Subroutine), click OK and do your tasks.
Stop Recording.
Go to the VBE and look at the modules. One of them will have the code
of your tasks.
To view all the colours referenced by ColorIndex, run the following sub,
after changing Sheet3 to the sheet that you would like to use:

18

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Sub colors()
Dim i As Integer, j As Integer
With Sheets("Sheet3")
With Range("G5")
.Value = "Colorindex"
.Font.fontstyle = "Bold"
.Columns.AutoFit
.Interior.ColorIndex = 15
End With
For j = 1 To 20
.Cells(j, 1).Interior.ColorIndex = j
Next For j = 1 To 20
.Cells(j, 3).Interior.ColorIndex = j + 20
Next
On Error GoTo endproc
For j = 1 To 20
.Cells(j, 5).Interior.ColorIndex = j + 40
Next
End With
endproc:
End Sub
The following sub draws a border around a range selected and colours it with
colour number index.
Sub colourborderrange(index As Integer)
With Selection
.BorderAround Weight:=xlMedium, LineStyle:=xlContinuous
.Interior.ColorIndex = index
End With
End Sub
With ... End With enables one to avoid repetition of parts of a statement
To run this, select a range in EXCEL and enter in the Immediate Window:
colourborderrange 5
Alternatively, we could replace the first two lines by
Sub colourborderrange(index As Integer, strRng As String)
With Range(strRng)

2.4. USING ARRAYS IN VBA

19

which does the same for the range which is the contents of strRng (such as
"B2:C5") instead of a selected range.

2.4

Using Arrays in VBA

1. Dimensions and Typing


Arrays have lowest index 0 unless the declaration
Option base n
is placed in the declarations section (all arrays then have lowest index n)
Dim StrVect(5) As String
declares a vector of 6 elements (0, 1, 2, 3, 4, 5) of type string.
Numeric Arrays are initialised to have the value 0 and string Arrays are
initialized to "".
Multidimensional Arrays are available e.g.
Dim iArray(3, 4, 5) As Integer
More flexible indices are possible e.g.
Dim iArray2 (2 to 5, 3 to 7, 8 to 13) as Integer
The statement
Dim vntArray(3)
creates an array of 4 elements of type Variant.
Dynamic Assignment
Dim dArray( ) As Double
allows one to dimension the array later. For example if (positive) integer
variables are calculated or read as input (M, N say) then a later statement
ReDim dArray(M, N)
results in an array with these dimensions. The Dim statement cannot contain
variables (like M,N).
There are functions
ubound(arrayname, number of index from left)
and
lbound(arrayname, number of index from left)

20

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

The function
ubound(dArray, 2)
above yields the value in N. The function call
lbound(iArray2, 3)
has value 8. For a dynamic array, we can use
Redim dArray(ubound(iArray2,2))
Passing Arrays to Other Subs
The best way usually is to use an extension of the following code fragment:

Sub CallingSub ()
Dim e() as Double
Redim e(7)
CalledSub e
e() is here the previous array e(7) after processing by CalledSub.
The values have been stored in d() (hence in e) since the variable
d is called by reference in CalledSub.
End Sub
Sub CalledSub (d() as Double)
Dim i As Integer
For i = 1 to Ubound(d,1)
Do something with array d()
Next
End Sub
Assigning Values to Arrays
We consider two cases:
The object to which values are assigned is NOT a Range in the
Spreadsheet
It is then best to assign values component by component, although under
special circumstances, it is possible to use a block method (see below).
The following is RECOMMENDED:
Sub imprt(A() As Double)

2.4. USING ARRAYS IN VBA

21

If A is an MxN array, the values assigned to it


are the MxN values of the cells in the block starting
at D1
Dim i As Integer, j As Integer
For i = 1 To UBound(A, 1)
assuming base 1 is used
For j = 1 To UBound(A, 2)
A(i, j) = Range("D1").Cells(i, j).Value
Next
Next
End Sub
The following type of block assignment is legal but NOT RECOMMENDED
The reason for not recommending this method is that large variant arrays can
take up a great deal of space. It is feasible for medium sized arrays.

Dim A As Variant
A = Range("A1:B2").Value
If you wish to assign an array directly, do not dimension A or use A(1)= 2
etc before assigning the array to A. Also, A must be of type Variant if you
assign worksheet values in a block of cells directly to A.

Function VarAssgn (q as Variant)


Values of a 3 1 range of cells will be passed to q
Dim v as Variant, i as Integer, d() as Double
v = q
v is a variant containing a 3 1 array!
ReDim d(ubound(v,1))
For i = 0 to ubound(v, 1)
d(i) = v(i, 1)
Next i
VarAssgn = d
End Function
The output of VarAssgn is of type Variant.

22

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

The object to which values are assigned IS a Range in the Spreadsheet


Provided that the shape of the input and output is the same, the assignment
can be made directly.
However, there are some problems:
EXCEL needs to distinguish between a row vector in a sheet, and a column
vector. It does this by regarding
A row vector as a 1 n array
A column vector as an n 1 array.
So, even if the spreadsheet range to which we are assigning is part of a single
column, say, the array whose values we assign to it must be an n 1 array.
In VBA, we can use this principle to make input and output more compact,
as in the following example which calculates the path of the asset price in the
Black-Scholes model, and places the vectors calculated in the range A1:EN
where N is the number of points on the path (an input) and S, rate, sigma
and dt are inputs representing initial price, risk-free rate, volatility and step
in the path. Try it out, and note carefully how the arrays are handled.
Sub calc(S, rate, sigma, N, dt)
Dim i As Integer, t()As Double, w() As Double
Dim x()As Double, u()As Double, rd() As Double
ReDim t(N, 1 To 1), w(N, 1 To 1), x(N, 1 To 1),
u(N, 1 To 1), rd(N, 1 To 1)
rd(1, 1) = Application.Worksheetfunction.NormsInv(Rnd)
t(1, 1) = 0
w(1, 1) = 0
x(1, 1) = S
u(1, 1) = S
For i = 2 To N
rd(i, 1) = Application.Worksheetfunction.NormSInv(Rnd)
t(i, 1) = t(i - 1, 1) + dt
w(i, 1) = w(i - 1, 1) + rd(i, 1) * Sqr(dt)
x(i, 1) = x(i - 1, 1) * (1+ rate * dt + sigma *
(w(i, 1) - w(i - 1,1)))
u(i, 1) = u(1, 1) * Exp((rate - 0.5 * sigma ^ 2) * t(i,1)
+ sigma * w(i,1))

2.4. USING ARRAYS IN VBA

23

Next i
Range("A1:"
Range("B1:"
Range("C1:"
Range("D1:"
Range("E1:"

&
&
&
&
&

"A"
"B"
"C"
"D"
"E"

&
&
&
&
&

N).Value
N).Value
N).Value
N).Value
N).Value

=
=
=
=
=

rd
t
w
x
u

End Sub

We could equally have done the output using cells(i,j) and a loop.
We could have just used one-dimensional arrays x(N) and so on and in the
final statements writing to a range we could have then used
Range("A1:" \& "A" \& N).Value =Application.Transpose(rd)
and so on.
To enter an Array Formula from VBA
To enter a formula into a cell from VBA which will output an array, use the
following format:
Activesheet.Range("A1:A5").FormulaArray =
"=Application.MMult("C1:G5","I1:I5")"
The formula is evaluated and the result placed in range A1:A5.
Using a 1-dimensional array-valued VBA function in EXCEL cells:
When a 1-dimensional array (vector) occurs in a function or sub, it is ALWAYS regarded as a row vector when written to the spreadsheet.
Even if you transpose (Application.Transpose(v)) the vector v and assign
it to the function name and then use the function in a spreadsheet, it will
output a row vector.
To enter a 3-vector which is the output of function f(q) into your spreadsheet,
select a 1 3 set of cells, enter =f(q) and (simultaneously) press
Ctrl-Shift-Enter
To enter it as a column, select the 3 1 column and enter
=TRANSPOSE(f(q))
and then
Ctrl-Shift-Enter

24

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Alternatively in a VBA sub enter, for example (if v is dimensioned as v(N ))


Worksheets("Sheet1").Range ("C4:C6")
=Application.Worksheetfunction.Transpose(v)
Obtaining arguments from a Range (see also previous section on
ParamArrays: This example illustrates the techniques, but Sub Square is
clearly not a good way to square a matrix. For abbreviation, it has been
written to square 2 2 matrices.

Sub squared()
Dim B(1 To 2, 1 To 2) As Double
B(1, 1) = 1
B(1, 2) = 2
B(2, 1) = 3
B(2, 2) = 4
square B
Range("G1:H2") = B
End Sub
Sub square(A() As Double)
Dim i As Integer, j As Integer
Range("A1:B2").Value = A
Range("D1:E2").Value=Application.WorksheetFunction.MMult _
(Range("A1:B2"), Range("A1:B2"))
For i = 1 To UBound(A, 1)
For j = 1 To UBound(A, 2)
A(i, j) = Range("D1").Cells(i, j).Value
Next
Next
End Sub

2.5

Further VBA

Contents: Using Help, Communication with the user, Input from the user,
Constants, User-defined Data Types, Timing Code, Running Subs from buttons,

2.5. FURTHER VBA

25

Setting passwords, Creating Add-Ins.


Read and experiment with the following VBA structures and functions.
Use the VBE Help by entering a keyword in a module, putting the cursor
over it and pressing F1.
Communication with the user can be made with
MsgbBox prompt:= . . . , title:= . . .
where prompt is required, but title is optional. There are more optional
arguments, but these are not dealt with here.
Call msgbox (prompt:= "Hi", title:= "Hello")
is another calling method which should, however, not be used.
To get input from the user, one way is to use a pop-up box Inputbox.
Find out how to use it and experiment. There are several other ways to get
input from the user:
From the EXCEL sheets.
Through a UserForm (see later).
All these methods can be activated from a button on the sheet. See later
in this section.
How to specify an unchanging constant like :
Const pi As Double = 3.14159
The text As Double is optional. Constants declared in a Sub, Function,
or Property procedure (see the section on Class Modules) are local to that
procedure. A constant declared outside a procedure is defined throughout the
module in which it is declared. You can use constants anywhere you can use
an expression.
User-Defined Data Types
This example uses the Type statement to define a user-defined data type.
The Type statement is used at the module level only and cannot be defined
within a procedure. If it appears in a class module (see later section), a Type
statement must be preceded by the keyword Private.

26

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Type EmployeeRecord
ID As Integer
Name As String * 20
Address As String * 30
Phone As Long
HireDate As Date
End Type
Sub CreateRecord()
Dim MyRecord As EmployeeRecord

MyRecord.ID = 12003
MyRecord.Name = "Bob"
End Sub

Create user-defined type.


Define elements of data type.

Declare variable.
Assignment to EmployeeRecord variable
must occur in a procedure.
Assign a value to an element.

Timing Code
Use the following to time the execution of a block of code:
StartTime = timer
(code)
EndTime = timer
TotalTime = StartTime - EndTime
Range("A1").value = TotalTime
This places into cell A1 the time taken in seconds to execute the code.
Running subroutines from a Button
This method uses a button on the Forms toolbox.
Activate a worksheet
Go to Developer | Controls | Insert, click the Button on the Forms section
and them click a cell in the Worksheet. The button appears there, and a
box appears asking you to assign a macro. Give the name of one of the
subroutines you have written in your code modules.
Click on another cell. Then click your button. The macro will run.
To change the button caption, right click on the button, highlight the caption with left button and change it.

2.5. FURTHER VBA

27

Right click on the border of the button. Choosing Assign Macro will allow
you to change the macro. Choosing Format Control will allow you to format
some aspects of the button. Resizing can be accomplished by using the size
handles.
Subroutine with Arguments
You must insert the button from the Control Toolbox. Do so. Go into
Design Mode by making sure the toolbar button with the blue triangle is
clicked. Double click the button. A code window appears with a subroutine
which runs whenever the button is left - clicked. In the subroutine enter
YourSub arg1:= . . . , arg2:= . . .
Click the Properties button of the Control Toolbox. Change the Caption
property to your desired caption. Click the blue triangle button on the toolbar if necessary to turn design mode off. Click your button - the subroutine
will run.
Setting a Password
You can prevent others from expanding your workbooks name by setting
a password.
Go to the VBE. Go to menu item Tools | VBAProject Properties, and then
to the Protection tab. Set the password and confirm it. Press OK and
save the project (say, from the File menu). To load it in a new instance of
EXCEL and to be able to expand the project in the VBE you will need to
enter the password.
Having entered the password, you can remove the protection by using the
same protection tab and deleting the password and repetition.
Creating an Add-In
One can change any workbook into an Add-In. Any code will not be available for alteration and the worksheets of the Add-In can never become
active. The Code of the Add-In can, however, write to its own worksheets,
and these changes can be saved. The subs and functions of the Add-In
do not appear on the available list of subs and functions. These can be
run from other open workbooks also from forms and menus in these other
workbooks. We will not go into all this, but merely give a way of saving a
workbook as an Add-In. When it is loaded in the usual way via the Tools
| Add-Ins menu, the functions and subs can be used. We will only discuss
briefly a method for saving changes. Further information can be found on
the Microsoft website.
To change your workbook into an Add-In while it is open, go to the File |
Save As menu, go to the drop-down menu at the bottom marked Save as type
and go down to find Microsoft Excel Add-In (*.xla). Choose this and

28

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

save. The file is saved as an .xla file. This can be loaded as an Add-In
from the Tools menu in the usual way. You can then use the functions and
subs, so document these beforehand.
To delete the Add-In, go to the directory in which it is housed and change
the name or delete it. When you go into Excel, try to load the Add-In from
the menu. It will give you the opportunity of deleting it from the Add-In
list.
To delete the Add-In from your project without deleting it totally as above,
use the Intermediate window with code like
Workbooks("AddInName.xla").Close
If you wish to use the sheets of the Add-In you should use code like
ThisWorkbook.Sheets("Sheet2").Range("A1:B5").Clear
You can save changes by entering in the BeforeClose event code:
ThisWorkbook.Save
You can also use a dialog box in this code to leave it to the user to decide
whether to save or not.

2.6

Debugging

To run a function or sub with no arguments


In the VBE, place the cursor somewhere in the code for the routine and click
the button with a triangle. It will run or give an error message.
One can set a breakpoint in the function or sub at a line, and the procedure
will pause before executing the line. To do so, click in the left margin at the
code line (a disc appears in the margin). You can look at the values of the
variables at the time of the pause by viewing the Locals window. To remove
the breakpoint, click on it. One useful spot to set a breakpoint is on the
End Sub or End Function statement, to see what has happened at the end.
If the Locals window is not visible, it can be made visible from the View
menu.
To continue running after a breakpoint pause, click the triangular button
again. To stop the run, click the button with the square. You can watch the
variables as they are when the run stopped at a breakpoint by looking in the

2.6. DEBUGGING

29

Locals window or setting a watch (see below). Click the triangle to run the
function in which the cursor is sitting, or to continue.
You can run the function step by step by first placing the cursor in the
function code and then successively pressing F8.
To look only at a few variables (not all) you can use the Watch window
and set the variables you want to see. To set them, go to Debug|Add watch
(while the cursor is in the desired routine.) You can then set breakpoints and
look at only the watched variables at these points.
To run a sub that has an argument do so from the Immediate window
(which can be made visible from the View menu). You would enter in the
Immediate window something like
sbr arg1:=2,arg2:=3
A useful command to add to a routine when debugging it is
Debug.Print variablename
which prints the value of variablename (when this statement is reached) in
the Immediate window.
To run a function named fun with, for example, a numerical argument v,
either call it from a specially written sub, or set breakpoints and enter in the
Immediate window something like :
a=fun(1.5)
Debug.Print a
or
Debug.Print fun(1.5)

2.6.1

Excel Link for Matlab

A facility distributed by Matlab allows EXCEL to export data from the spreadsheet or VBA to Matlab, to execute Matlab programs and to import data from
Matrlab into EXCEL. The linking functions can be called either from the spreadsheet or from VBA.
Matlab must be installed. ExcelLink must first be available from Matlab and
installed. We will assume that this has been done.
Ensure that the link is loaded as an Add-In. Exclink.xla is an Add-In file
which is usually in the ToolBox subdirectory of the main Matlab directory.

30

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

In the Tools | Add-Ins menu make sure that there is an Excel Link option, and
check the check box. If it is not there, use the browse button to find it in the
above directory and load it and check the box. There will be some additional
buttons on the upper toolbar such as GetMatrix. Press one to make sure that
Matlab is running and if not click the buttons to ensure that it is. If you
are running link routines in VBA, you need also to switch to the VBE and
in Tools | References check the Excel Link box. The latter can only be done
when Matlab is running.
We will deal only with writing the routines in VBA. We will list a program in
VBA which illustrates most of the features and then comment on the code.
Only one- and two-dimensional numeric arrays, and one-dimensional character arrays (which are just the same as character strings can be transferred
to EXCEL. In addition, two-dimensional cell arrays whose elements are all
character strings may be transferred.
Sub ExLinkTrial()
Dim i As Integer, j As Integer, NewSheet As Object
Dim C1(2, 2) As Double, D(2, 2) As Double
Set NewSheet = Sheets.Add(Type:=xlWorksheet)
NewSheet.Name = "Scratch"
For i = 1 To 5
For j = 1 To 4
Sheets("Scratch").Range("A1").Cells(i, j) = i * j
Next
Next
For i = 1 To 4
Sheets("Scratch").Range("F1:F4").Cells(i, 1) = i
Next
Sheets("Scratch").Range("F1:F4").Name = "y"
For i = 1 To 2
For j = 1 To 2
C1(i, j) = i * j
Next
Next
MLOpen
MLPutMatrix "AMat", Sheets("Scratch").Range("A1:D5")
MLPutMatrix "y", Sheets("Scratch").Range("F1:F4")

2.6. DEBUGGING

31

MLEvalString "SDE2"
MLEvalString "y=AMat*y;z=1"
MLGetMatrix "AMat", "Scratch!H1:K5"
MatlabRequest
MLGetMatrix "y", "Scratch!M1:M4"
MatlabRequest
MLPutVar "C1", C
MLGetVar "C1", D
Sheets("Scratch").Range("A7:B8").Value = D
MLClose
Application.DisplayAlerts = False
Sheets("Scratch").Delete
Application.DisplayAlerts = True
End Sub
The program first creates a new sheet in the workbook to do input-output
from a worksheet. Input-output from Matlab can also be done directly to VBA
variables by using MLPutVar and MLGetVar as illustrated in the program.
The program then writes some data to the new sheet, sends it to Matlab, runs
a Matlab script file, executes Matlab commands to manipulate the data and
then imports it back to the spreadsheet and to VBA. It then deletes the new
sheet.
MLOpen opens Matlab. Later MLClose closes it. Matlab need not be opened
if it is already open and need not be closed.
MLPutMatrix "AMat", Sheets("Scratch").Range("A1:D5") loads the contents of A1:D5 in sheet Scratch into Matlab variable AMat. Note that the
second argument has no quotes around it. The routines are inconsistent in
this respect.
MLEvalString "SDE2" executes the Matlab statement SDE2. This happens to
be the name of a Matlab m-File in this version and this script file is executed.
MLEvalString "yAMat*y;z=1= executes the two statements yAMat*y=
and z1= in Matlab (the second one is pointless but is included for illustrative
purposes).
MLGetMatrix "AMat", "Scratch!H1:K5" puts the contents of Matlab variable AMat into the spreadsheet range H1:K5. It must have the command

32

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

MatlabRequest immediately following it. Note the quotes in this case.


MLPutVar "C", C puts the contents of VBA variable C into Matlab variable
C1. MLGetVar "C1", D gets the content of Matlab variable C1 into Matlab
variable D. Once again, note the position of the quotes.
Running form the Spreadsheet These statements can also be run from
the spreadsheet. For example enter =MOpen() in a blank cell outside the data
area, press F2 and Enter. Enter =MLPutMatrix("AMat",A1:D5) to put the
contents of the given range into the Matlab variable AMat. Note the position
of the quotes.
MLPutVar, MLGetVar are only for use in VBA.
Recommendation It is recommended that you use VBA programming to
run your Matlab programs.
It is easiest to write all your routines in Matlab m-Files and to execute them
as in the above program.
After executing a Matlab m-File , the variables local to the m-File disappear.
In order to pass a variable to the base Matlab layer so that one can then
transfer it to EXCEL use statements like the following in your m-File:
assignin(base,PassVarName,mFileVarName)
This assigns to a variable named PassVarName in the base layer the contents
of mFileVar in the m-File. PassVarName will persist after the m-File has been
run and can be transferred to EXCEL using, for example, MLGetMatrix.

2.7. OBJECTS

2.7

33

Objects

Contents: Objects, Properties, Methods, Classes, Collections, Executing Functions and Subs from VBA.
Object Notation
VBA deals with the objects of EXCEL such as cells, sheets, workbooks, charts,
etc. Given an object, there are usually subobjects included in the object,
properties of the object that can be accessed and changed and methods for
the object that perform calculations on the object or create something. There
are also objects which are collections of other objects of the same type. An
object has a type - when using a variable to store an object, it is declared in a
Dim statement (compulsory under Option Explicit) e.g. Dim Rng As Range.
The hierarchy of objects in an application is a tree, but there are too many
nodes to view diagrammatically.
To view the tree, select Object Browser from the View menu in the VBE. In
the top combobox, select EXCEL from the drop down list. In the column at
the left there appears a list of all the built in classes available in EXCEL.
Click on Application. Application is the root of the Excel tree. On the
right there appears the properties, methods, events and possibly certain
constants that are part of the class. The icon on the right indicates which
it is.
Some of these properties return objects which are themselves classes with
a similar name to the property. For example, Workbook and Workbooks are
also classes, the latter being the Collection of all the instances of the class
Workbook that have been created to date.
Click on Workbooks in the Classes window of the Object Browser. You can
find out the values of the properties listed in the right hand window or the
output of a method which returns a number by entering one of the following
two types of statement in the Immediate Window (which can be inserted
from the View menu):
Debug.Print Application.Workbooks(1).Sheets(1).Range("A1").Width
MsgBox Application.Workbooks.Count
Debug.Print Application.Workbooks.Count
The first pops up a messagebox with the property value, and the second
prints the value in the Immediate Window. At this stage, the value is 1.

34

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Figure 2.2: The Object Browser


Collections Objects are defined by means of Classes written in Class Modules. The defining code of the system classes is not visible to the user, but
the user can write her own class modules. The Class defines the abstract
properties of an object. To create objects requires a creator and a place
to store the new object once created. Collections are sets of objects of
the same type that have already been created, and are also Classes. They
will usually have methods Add, Delete (or Remove), Count. The Add
method creates a new object of a class and stores it in the collection. If
a class is called Sheet then the collection is conventionally called Sheets
and similarly for other classes. One way of referring to the instances in
a collection is to use an index. Thus Sheets(2) is one of the sheets of a
Workbook. (But BEWARE, it may not be the second sheet created or the
sheet "Sheet2". If some of the sheets have been deleted, then the indices
are rearranged to give them consecutive numbers starting from 1.) Add

2.7. OBJECTS

35

and other methods may have different arguments in different classes. One
must check which arguments are non-optional for each class and use at least
those.
To use a method, use a statement, for example in the Immediate Window,
of the form
Application.Workbooks.Add
If you wish to assign the new Workbook to a variable, then you can use
Dim wkbk As Workbook
Set wkbk = Application.Workbooks.Add
Note: The word Set must appear in an assignment statement involving an
object. This has the effect of adding a new workbook, which will appear
as a new project in the Project Window. There is an optional argument
which allows you to add an existing project which has been saved previously.
If Myproject.xls already exists in the current directory (press the Open
button to find out the current directory), the following will add it as a
project to your running version of EXCEL:
Application.Workbooks.Add "MyProject"
Try the following in the Immediate Window:
Application.Workbooks(1).Sheets(1).Chartobjects.Add 100,100,100,100
This creates a Chartobject in the first worksheet in the Sheets collection of
the first workbook (or project) in the current instance of your application
(look at your Worksheets to find a blank square in one of them.) Note
that the collection of Worksheet objects is Sheets. Find out what the 4
arguments 100,100,100,100 signify by clicking the Chartobjects class and
then its Add method (look at the bar below the Classes Window.) Try
leaving them out - you get an error message, since they are compulsory.
Try this with other properties and methods and explore the tree of your
instance of an EXCEL application. Some of the properties may yield error
messages (they may be required to have been set previously.)
Every created object has a parent in the tree, uniquely defined For example,
in the collection Chartobjects the Parent of an instance of Chartobject
will be the particular worksheet to which it belongs. A Chart has parent
a Chartobject if it is an embedded chart, or the sheet itself if the chart is
located in its own sheet. When a Chartobject is created in some sheet, a
Chart is automatically created as its child.
Objects have Properties and Methods. Properties can be changed and methods executed to give a result. Count is a method of all collections. In the
Immediate Window type

36

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

MsgBox Activesheet.Chartobjects.Count
A box will appear, with the number of objects in this collection.
Executing Functions and Subroutines from VBA
There are two possible ways of writing the arguments of functions and subroutines when executing them. HOWEVER in some situations only one of
these is permissible.
Subroutines: We illustrate with the MsgBox subroutine which displays a
(modal) messagebox with a message. To find out all the possible arguments
of this sub, type MsgBox on a new line in the Immediate window and press the
spacebar. A list of arguments appears. Alternatively, put the cursor in the
middle of the word and press F1. VBA help appears for this sub, listing the
arguments (in the Syntax portion of the window.) Arguments with square
brackets are optional. So there is only one required argument for MsgBox,
namely prompt. We will also use title.
Msgbox Activesheet.Name
recognises that Activesheet.Name is the required prompt argument, it evaluates the expression and puts the result in a box with an OK button (the
default). The box is modal in that it must be closed before you can continue.
Msgbox Activesheet.Name, title:= "trial1"
puts a caption in the coloured bar at the top of the box. Or
Msgbox prompt:= Activesheet.Name, title:= "trial1"
uses the argument name prompt in the function call. Optional arguments like
title must use the argument name in the call.
Note: Putting brackets around the arguments instead of writng them without brackets as above will sometimes work but should NOT be done as
it can lead to unpredictable results. On the other hand if we use Call
MsgBox(Activesheet.Name) the brackets are ESSENTIAL. Call should be
AVOIDED if possible, as it is obsolete, and adds confusion. Also Call
MsgBox(prompt:="hello") will work.
To directly assign a (possibly function) value to another variable at initialization, one can use the following (BRACKETS COMPULSORY):
Dim Var1 = Fun(arg1, arg2)
Dim Var2 = 3
When assigning to a variable whose type is some object type, one must use
Set. For example:
Set rng = Range ("A1")

2.8. CHARTS

37

As an example of placing the arguments of a method associated with an


object, we use the Location method of Chartobject, which is a subroutine
(invisible to the user). Both the following statements are legal:
Chartobjects(1).Location where:= xlChartobjectasobject, Name:="Sheet1"
OR
Dim chtobj As Chartobject
Set chtobj = Chartobjects(1).Location(where:= x1Chartobjectasobject,
Name:="Sheet1")
Note: Brackets around the arguments of Location are used in both lines for
the Set command. NO brackets are used in the first use of Location. Brackets
are used in the second use of Location. This will not work otherwise! Line 2
calls the Location method of an existing object, while Line 3 sets the variable
chtobj in addition to calling the Location method.

2.8

Charts

You can either have a chart as an embedded object in a worksheet or in its


own separate sheet.
In the case of embedded object the chart has Parent a Chartobject in the
Chartobjects collection of the worksheet. In the case of a separate sheet,
the parent is the worksheet itself.
To create an instance of the Chartobject class and add it to the Chartobjects
collection of worksheet sheetname use:
Sheets("sheetname").Chartobjects.Add(1, 1, 1, 1)
(the arguments 1,1,1,1 are compulsory, and give top, left, height, width
in pixels - they can be altered later.) This creates an embedded chart on the
sheet whose name is given by the contents of the string variable sheetname.
To assign the new object to a variable, use the Set command as explained
above.
Another alternative:
Dim Cht As Chart, strActiveSheetName As String
strActiveSheetName = ActiveSheet.Name
ActiveSheet.ChartObjects.Delete
Set Cht = Charts.Add

38

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Set Cht = Cht.Location(where:=xlLocationAsObject, Name:= strActiveSheetName)

This adds a chart to the global Charts collection, and then makes it an
embedded chart in a sheet.
Once created the characteristics can be altered by VBA. See the example that
follows this discussion.
Use Macro Recording to get an example and select the features you need.
(But try to use one of the methods if the macro is different.)
Use Help, and F1 (when the cursor is on a term) to get assistance and to
find further examples. Also use the Drop down menus that appear when you
insert a period after an identifier.
The following example illustrates the procedure. You may have to click on
the area that the graph should occupy to display it.
Sub MyChart()
Before use, place numberical data in D2:E10
Dim chtobj As ChartObject, cht As Chart
datarng As Range, obj As Object
Application.Screenupdating = False
Set datarng = Range("D2:E10")
On Error Resume Next
Sheet1.ChartObjects.Delete
Set chtobj = Sheets("Sheet1").ChartObjects.Add(1, 1, 1, 1)
Set cht = chtobj.Chart
With chtobj
.Top = Range("A1").top
.Left = Range("A1").Left
.Height = 150
.Width = 450
.RoundedCorners = True
End With
With cht
.Type = xlXYScatter
.SetSourceData Source:=Range("D2:E10"), PlotBy:=Columns
.ChartArea.Interior.ColorIndex = 30
.HasLegend = True
With .PlotArea.Fill

2.8. CHARTS

39

.ForeColor.SchemeColor = 50
.BackColor.SchemeColor = 43
.TwoColorGradient Style:=msoGradientHorizontal, Variant:=1
End With
End With
Application.Screenupdating = True
End Sub

A number of things need still need to be done to make the output more
acceptable. The series may be plotted with markers. To eliminate them, use:
cht.SeriesCollection(i).Markers = xlNone
where i is an index to loop through (or use For Each obj In Series.Collection
..... Next).
Also, the fonts may need to be resized, to avoid a default size that is too
large. This applies to the title, axis title and legend. These can be changed
by setting the following to values:
cht.ChartTitle.Font.Size
cht.Axes(xlCategory).Ticklabels.Font.Size
cht.Axes(xlValue).Ticklabels.Font.Size
cht.Legend.Font.Size

40

CHAPTER 2.

2.9

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Using Solver in VBA

To use the subroutines in the Solver package in VBA, it is firstly necessary


to go to the VBE and the menu item Tools|References and tick the Solver
button - in the VBE open a module first, click on a word in it and then do
the above. The help menu in the VBE lists the Solver routines and arguments. Look them up and look at them. If you do not find SOLVER listed
in Tools|References then make sure that the solver add-in has been loaded
(in EXCEL), and if you still do not find it, run solver from EXCEL on some
trivial problem and then check for the reference.
The package contains functions and subroutines and these do not return a
useful value - they return values to a worksheet range. Their arguments are
also, in some cases, cell names so it is necessary to enter arguments and results
in the spreadsheet (possibly using VBA), and then call the Solver routines in
VBA, after which the results can be retrieved from the spreadsheet and further
processed in VBA.
Example 1: To solve ax2 + 3x + 2 = 0 for various a.
The following will be done in the ActiveSheet. To use a specific sheet, use
for example
Sheets("Sheet1").Range("A1").Name = "a"
Sub Quad()
Dim v As Double
Range("A1").Name = "a"
Parameter of function f
Range("B1").Name = "x"
Variable of function f
Range("C1").Formula = "=f(x,a)"
Range("x").Value = 0
Estimate for solution
Range("a").Value = 1
set parameter value
SolverReset
SolverOK SetCell:= "C1", MaxminVal:=3, ValueOf:= "0", _
ByChange:= "x"
set cell C1 to the value of 0 by changing x;
Maxminval 3 is "match specific value"
SolverSolve UserFinish:= TRUE
Executes routine, "TRUE" value suppresses dialogue box
v = Range("x").Value
End Sub
Function f(x As Double, a As Double) As Double
f = a * x ^ 2 + 3 * x + 2

2.9. USING SOLVER IN VBA

41

End Function
Example 2 Optimisation of Functions with many Arguments
If a function has many arguments the arguments are best combined into an
array which is entered in a spreadsheet range. Suppose for example that the
arguments are entered into cells B1:B40 and that these are the cells that must
be varied to obtain the optimum. A fragment of a suitable function is the
following:
Function g(vec As Variant)) As Double
Dim i As Integer, M As Integer, params() as Double
M=Application.Count(vec)
Redim params(M)
For i = 1 To M
params(i)=vec(i)
Next i
.....
End Function
We would then use
Range("C1").Formula = "=g(B1:B40)"
The appropriate argument of SolverOK would be
SolverOK SetCell:= "C1", MaxminVal:=3, ValueOf:= "0", _
ByChange:= "B1:B40"
Note: If vec were a string variable this would not work. Example 3 To
solve the simultaneous equations y + t = 3, 3y + t = 5.
Sub LinEq()
Dim a As Double, b As Double
Range("G1").Name = "y"
Range("I1").Name = "t"
Range("G2").Formula = "=y+t-3"
Range("I2").Formula = "=3*y+t-5"
Range("I3").Formula = "=G2 ^ 2 + I2 ^ 2"

42

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

SolverOK SetCell:="I3", MaxMinVal:=3, _


ValueOf:="0", ByChange:="G1, I1"
SolverSolve UserFinish:=True
a = Range("y").Value
b = Range("t").Value
End Sub
Note: Constraints can be added. For example
3x + 2y 4
can be added by entering
"=3*x+2*y-4"
in a cell (say C6) and then calling
SolverAdd CellRef:="C6", Relation:="1", FormulaText:="0"
This can be changed at a later date by e.g.
SolverChange CellRef:= "C6", Relation:="2", FormulaText = "0"
and can be deleted by using
SolverDelete CellRef:= "C6", Relation:="1", FormulaText = "0"
Note: FormulaText can, according to the Help, take any constant as well as
a text cell name. However it does not seem to work with any constant other
than 0.
Example 4 To solve the linear programming problem x + y = max!, 3x +
2y 4, 5x + y 4, x, y 0.
Sub LinProg()
Dim a As Double, b As Double
Range("B6").Name = "x"
Range("B7").Name = "y"
Range("C6").Formula = "=3*x+2*y-4"
Range("C7").Formula = "=5*x+y-4"
Range("D6").Formula = "=x+y"
SolverAdd CellRef:="C6", Relation:="1", FormulaText:="0"
SolverAdd CellRef:="C7", Relation:="1", FormulaText:="0"
SolverAdd CellRef:="B6", Relation:="3", FormulaText:="0"
SolverAdd CellRef:="B7", Relation:="3", FormulaText:="0"
SolverOK SetCell:="D6", MaxMinVal:=1, ByChange:="B6, B7"

2.9. USING SOLVER IN VBA


SolverSolve UserFinish:=True
a = Range("x").Value
b = Range("y").Value
End Sub
The possible values for the argument Relation are:
1 is <=
2 is =
3 is >=
The possible values for MaxMinVal are:
1
2
3
4
5

is maximize
is minimize
is match a specific value (set by argument ValueOf)
cells referenced by CellRef must be integers
cells referenced by CellRef must be 0 or 1

43

44

CHAPTER 2.

2.10

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Errors

Worksheet Errors - Common causes


#####
#DIV/0!
#REF!
#NULL!
#NAME?
#N/A
#VALUE!
#NUM!

Number, date or time is wider than current cell


Division by cell containing blank or zero, or formula containing /0
Cell reference not valid (perhaps it was deleted)
Incorrect range operator or cell reference
Using a name that does not exist
(not available) - something cannot be found
Wrong variable type
Number required and other type used

Note that these are CELL WORKSHEET FUNCTION errors, not runtime
errors in VBA.
Runtime Errors in VBA In VBA, an error (at RUNTIME) that occurs is
described by an intrinsic object Err (that need not be created). Refer to the
HELP in VBA (F1 in the VBE). Look at the entries for Err Object and Err
Object Example. Properties are:
Err.Number
(default property) the number of the error
Err.DescriptionA string description of the error
Err.Clear
Clears the error - can now proceed
and some other possibilities.
Two useful error numbers are
9 Subscript out of range
11 Division by zero
Trapping Errors
When errors occur, control can be transferred to another section which has
code to deal with them, and then control can be transferred back if necessary.
Such error trapping can be done by a variant of the following code:

On Error GoTo Label1

Turns on error handling statements.

(program statements)
Exit Sub
Label 1:

or "Exit Function" as appropriate

2.10. ERRORS

45

(error handling statements)


Resume
End Sub

Optional - if error is fixed you can retry your statement

An alternatives for the On Error statement and the Resume statement


in the above example:
On Error Resume Next
skips statement with error and starts at next statement

The statement
On Error GoTo 0
turns normal VBA error handling on again (after the last error stopped
things). It DOES NOT instruct return to line 0 - heaven knows what it
does exactly.
Note: The most common runtime errors are division by zero (9) and subscript
out of range (11) in numerical work, and a variety of system errors associated
with files when using them in VBA (File referred to does not exist etc.)
Example The following example first uses the On Error GoTo statement to
specify the location of an error-handling routine within a procedure. In the
example, an attempt to delete an open file generates error number 55. The
error is handled in the error-handling routine, and control is then returned
to the statement that caused the error. The On Error GoTo 0 statement
resumes error trapping After return from the handling routine. A different
procedure is used for the next error. The On Error Resume Next statement
is used to defer error trapping to the following line so that the context for
the error generated by the next statement can be known for certain. Note
that Err.Clear is used to clear the Err objects properties after the error is
handled.
Sub OnErrorStatementDemo()
Dim Msg As String, ObjectRef As Object, num As Integer
On Error GoTo ErrorHandler
Enable error-handling routine.
Open "TESTFILE" For Output As #1
Open file for output.
Kill "TESTFILE"
Attempt to delete open file.
On Error GoTo 0
Resumes normal error trapping.
On Error Resume Next
Defer error trapping.

46

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Open "TESTFILE" For Output As #1


Kill "TESTFILE"
If (Err.Number = 55) Then

Open file for output.

Tell user what happened.


Then clear the Err object.
Msg = "There was an error attempting to delete an open file!"
MsgBox Msg, , "Deferred Error Test"
Close #1
Err.Clear
Clear Err object fields
End If
Exit Sub
Exit to avoid handler
ErrorHandler:
Handling routine.
Deals with "Open File" error
Select Case Err.Number
Evaluate error number.
Case 55
"File already open" error.
Close #1
Close open file.
Case Else
(statements)
Handle other situations here...
End Select
Resume
Resume execution at same line
that caused the error. (The file
is now closed).
End Sub
is now closed).
Generating Your Own Error States
You can also define your own error and give it a number that is not on VBAs
list but which now corresponds to the error that you have detected - e.g. a
matrix is not symmetric. You can use
Err.Raise
For example, the following uses raise to announce a system overflow error and
a user-defined error.
Sub errTest()
Dim Msg As String
If an error occurs, construct an error message
On Error Resume Next
Defer error handling.
Err.Clear
Err.Raise 6
Generate an "Overflow" error.
Check for error, then show message.

2.10. ERRORS

47

If Err.Number <> 0 Then


Msg = "Error # " & CStr(Err.Number) & " was generated by " _
& Err.Source & " " & Err.Description
MsgBox Msg, , "Error", Err.HelpFile, Err.HelpContext
End If
Err.Clear
Err.Raise 1001, "Sub ErrTest", "Nonsensical Error"
If Err.Number <> 0 Then
Msg = "Error # " & CStr(Err.Number) & " was generated by " _
& Err.Source & " " & Err.Description
MsgBox Msg
End If

48

CHAPTER 2.

2.11

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Userforms

Example 1: A simple data entry form


1. Open a Workbook in Excel and switch to the VBE (Alt F11).
2. Access menu Insert|Userform. A dotted form (in design mode) appears in
the window, and a Toolbox pop-up menu titled Controls appears.
3. Click on the form, change its name (say to frmTrial) and set its Caption
property (in the properties window) to Test Form.
4. In the Toolbox, click on the label control A.
Near the top left of the Userform, move the cursor so that the cross hair
is at the top left point of the position you would like the label to have, and
click. The label appears on the form.
Change the Name of the label (say, to lblHead).
Change the Caption property to Enter Data.
Change the Font property (by clicking on the button with 3 dots) to Bold.
The label now has the caption inside it in boldface.
You may want to resize it manually (by clicking and moving the borders)
or to shift it by clicking and holding down on a border and then dragging.
5. Similarly, put a Frame control under the label.
Change the name, and set the caption to blank (this will remove the text
at the top of the frame).
In the frame insert a label control with caption CellB3Content in boldface.
Alongside the label insert a TextBox (ab).
Change the Control source property of the TextBox (remember to click on
it first) to Sheet1!B3.
Enter something in the TextBox.
Switch to the EXCEL Sheet1. B3 will have the text you entered.
Switch back to the VBE.
6. Below the frame in the centre, insert a Command Button.
Change its caption to Close and give it a Name.
Double Click on the button. A code window opens with a sub heading
CommandButton Click( ) (your name for the button will appear in place
of Command Button.)

2.11. USERFORMS

49

Insert the code


Unload Me
7. Double click on the Userform (possibly renamed) tag in the Project Window
to go back to the Userform.
8. Press the Run button (small square), enter something in the TextBox, click
Close and look at Sheet1. Cell B3 will have the content of the TextBox. (You
can also exit the form by clicking the " box on the bar at the top of the
form.
9. Now return to the spreadsheet Sheet1 (use AltF11).
Go to menu View|Toolbars|Control Toolbox.
Click the CommandButton and place it somewhere on Sheet1.
Click the Properties icon on the top row of the toolbar Control Toolbox.
Change the name of the button to btnEnter, and the Caption to Enter
Data (in boldface).
Make sure the Design Mode icon (blue triangle) on the top row of the
Control Toolbox is clicked.
Double click the button. The code window appears with Sub btnEnter click().
Add the code line
FrmTrial.Show
10. Return to the spreadsheet (Alt F11).
Make sure the Design Mode button is off (click it if necessary.)
Click the Command Button. The form appears on the spreadsheet.
Enter something in the TextBox and click Close. The entered item appears
in cell B3.
11. Add a few more TextBoxs and labels to enter data to your form and test it.
Some Properties and Methods:
1. A Userform is modal by default, in that it retains focus until it is unloaded
or hidden - nothing else can be done to the computer until the modal object
is made to disappear. To create a modeless form and shows it:
frmFormname.Show vbModeless
This allows other tasks to be performed while the form is open.

50

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

2. frmFormname.Load
.Show
.Hide
.Unload

loads the form into memory, initially


loads and makes visible
makes invisible
deletes from memory

For any object in the Userform, "Me" refers to the parent, namely the
Userform e.g.
Unload Me
3. Userforms can contain the following objects. It is best to name them as
indicated below:
Frame
Textbox
CommandButton
OptionbButton
CheckBox
Listbox
Label
SpinBox

frmFrameName
txtBoxName
btnButtonName
optButtonName
chkBoxName
lstBoxName
lblLabelName
spnBoxName

To give these a name, click on the object and change the Name field in the
Properties Window. There are several other controls objects - see the Controls Toolbox.
4. The Control Source property links a cell in a worksheet to the Value property of the object e.g. one can set the ControlSource property to Sheet1!A1.
5. The Caption property can be used to give the object a descriptive title (which
is written somewhere on the object).
6. HINT: When changing a property in the property window, first click on the
text to be changed in the box on the right of the property name to highlight
property value, then double click. This highlights the text, and you can type
in the new text without erasing the old text. ALTERNATIVELY double
click the property name on the left.
7. Multiple Controls
If you have several different possibilities for the user, you can add a Multipage
Control, with tabs to change pages. You can insert material on each page
as if it were a single form.

2.11. USERFORMS

51

Enlarge your form and add a Multipage control. It will by default have
2 tabs. To add more pages, right click on a tab. You will have 4 options:
New page, Delete Page, Rename, Move.
Some properties on the property list of a Multipage: (to get this list,
click on the Multipage border or use the dropdown list in the Properties
Window (in Design mode)).
Value
Style
Tab Orientation
Multirow

the number of the page displayed


tabs can appear as tabs, buttons or not appear at all
tabs may appear on the top, bottom, left or right
if there are many tabs, more than one row can be used

Click on a Page to set its properties. Try adding other controls and getting them to work (e.g. SpinButton, ControlBox, TextBox, ListBox,
CheckBox, OptionButton.)

52

CHAPTER 2.

2.12

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Working with files in VBA - Method 1

Creating and Opening a File To work with the data in a file (read or write)
the file must be created if it does not exist, or opened if it does exist. For Help
with the following, enter Open Statement in the VBE Help Index. The following statement creates or opens a file with name pathname - it only creates the
file if mode is Output. (For example, pathname = "c:\direc\myfile.txt".)
filenumber is a unique integer.
Open (pathname) For (mode) As #(filenumber)
brackets

Omit the

Possible values:

Mode:

Input
Output
Append
Filenumber:

allows one to read but not write


allows one to read and write
writes to end of file
A filenumber different from other flenumbers in
use must appear here. The function Freefile
returns the smallest filenumber not in use

There are other arguments and other possibilities for mode (see HELP in
VBE). The above options for mode allows sequential access - other forms of
access are possible.
Working with Directories (You can find further details by consulting the
Help in VBE (NOT IN EXCEL) and entering the command name in the
INDEX). The most important function is
Dir(PathName)
where pathname is a string which may contain wildcards * (any number of
letters) and ? (1 letter) in your pathname, for example, "c:\windows\*.e??"
There is also the possibility of using a second argument
Dir(pathname, attribute)
Dir returns files without regard to attributes. Possible attributes:
vbReadOnly, vbHidden, vbSystem, vbDirectory.
Dir("c:\windows\*.e??") returns the first filename in the current directory matching the pathname.
To get the next matching file use Dir without any arguments.
If no files are left to return, Dir returns the empty string "".

2.12. WORKING WITH FILES IN VBA - METHOD 1

53

dir is a method of the FileSystem object. See the Object Browser and
the next item for information on other methods.
Other useful methods of FileSystem:
ChDir, ChDrive, FileCopy, FileDateTime, FileLen, GetAttr, Kill (Deletes
file), MkDir, Name (renames the file), RunDir, SetAttr
It is best to use an error trapping procedure when working with files, as
there are frequent user and system errors.
Enter the following in a module and run it with a breakpoint at the final
ttbKill. Check the directory and the file in it, reading the contents. Run
to the end and check again.

Sub sb()
On Error Resume Next
Disregards error in following sta
MkDir "c:\temp1\"
Creates new directory
On Error Resume Next
Kill "c:\temp1\aaatr.txt"
Open "c:\temp1\aaatr.txt" For Output As #1
Write #1, "all";
Writes string "all", leaving line ac
Write #1, " done"
Writes "done" on same line,starts ne
Close #1
Closes file #1
Debug.Print Dir("c:\windows\*.e??")
Finds first .exe file
Debug.Print Dir
Finds next .exe file
Debug.Print Dir("c:\temp1\a*")
On Error Resume Next
Kill "c:\temp1\aaatr.txt"
Deletes a file
On Error Resume Next
RmDir "c:\temp1\"
Deletes a directory
End Sub
The following is a program fragment:
Directory = "c:\*.do?"
File = Dir(Directory)
Cells(1,1) = File
Cells(1,2) = FileLen(Directory & File)
Cells(1,3) = FileDateTime(Directory & File)
File = Dir
Next file in "c:\*.do?" matching pathname
Working with Text Files The best way of handling text from files is to
read either individual characters or entire lines (Sequential Access).

54

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Opening To work with the data in a file (read or write) the file must be
opened. As before, use:
Open (pathname) For (mode) As #(filenumber)
CSV Files (Comma Separated Variable). These have data organised in
columns separated by a comma , and in rows or records terminated by
carriage return/linefeed i.e. chr(13) & chr(10). We will only use such
files here. The Open statement with mode Input or Output creates CSV
files.
Reading Files
Input #(filenumber), Data
inputs the text up to next comma into variable Data
LineInput #(filenumber), Data
inputs a line of data (up to chr(13)) into variable Data
Input inputs text as a string without the inverted commas created previously by writing using Write # . . . (see below). LineInput includes all
punctuation.
Input #1,(variable list) Reads into the successive variables listed
e.g.
Input #1, var1, var2
Example:
Sub sb2()
Dim Data As String, r As
Data = "dat"
r = 0
Open "c:\myfile.txt" For
Write #1, Data;
Write #1, Data;
Close #1
Open "c:\myfile.txt" For
Do Until EOF(1)
Input #1, Data
ActiveCell.Offset(r,
r = r + 1
Loop
Close #1
Kill "c:\myfile.txt"
End Sub
Writing to Files

Integer

Output As #1

Input As #1
or LineInput #1 ... to input a line
0) = Data

2.12. WORKING WITH FILES IN VBA - METHOD 1

55

Write #(filenumber), (outputlist)


writes outputlist. For example:
Write #1,Data,"This is some data"
will write on one record the content of Data, a string variable, in inverted
commas followed by a comma, followed by "This is some data" followed
by chr(13) & chr(10) to start a new line. To avoid ending the line use:
Write #1, Data;
(the ; does NOT put chr(13) to end the line and allows further writing
to this record.)
Write #1, var1, var2, "a", 3, "b"
Write takes a list of variables and constants.
Writing to and Reading from EXCEL
Writing a Range of Cells to a CSV File
This must be done cell by cell using Write # :
Sub ReadWriteMatrixExcelToFile()
Dim rng As Range, row As Integer, col As Integer
Dim numrows As Integer, numcols As Integer, data As Integer
Set rng = Selection
numrows = rng.Rows.Count
numcols = rng.Columns.Count
Open "c:\myfile.txt" For Output As #2
Write #2, numrows
Write #2, numcols
For row = 1 To numrows
For col = 1 To numcols
data = rng.Cells(row, col).Value
Write #2, data;
Next col
Next row
Close #2
End Sub
A blank cell gives value 0 - you may need to handle this case
If you wish to end the record at the end of the line, you must add code:
If
c <> Numcols Then
Write #1, Data;
Else
Write #1, Data
EndIf

56

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

to replace the Write statement.


Reading from a CSV File to a Range of Cells If you want to write each
line in a single row of cells, you need to know how many entries (separated
by commas) are on each line, and use a looped Input #n,word statement
to read them into a variable word). They can then be written to EXCEL.
If all records are the same length, this is easy if you know what that length
is. If not, you may have to read the record into a variable using LineInput
#n, and then parse the string, removing commas and " " as you go along.
Study and try out the following:
Sub ReadWriteMatrixFileToExcel()
Dim numrows As String, numcols As String, word As String
Dim i As Integer, j As Integer
Open "c:\myfile.txt" For Input As #1
Input #1, numrows
Input #1, numcols
For i = 1 To Val(numrows)
Convert string numrows to number
For j = 1 To Val(numcols)
Input #1, word
Range("A5").Cells(i, j).Value = Val(word)
Next
Next
Close #1
Kill "c:\myfile.txt"
End Sub
The following is useful for reading the whole file:
Do Until EOF(1)
Reading File #1
(statements)
Loop
or
While Not EOF(2) . . . Loop
REMEMBER CLOSURE. Always close your file when finished:
Close #1
One sometimes forgets to put a Close #n statement and then exits from a
sub, making the file temporarily unusable. You then need a procedure of
the following form to close it and make it usable again:
Sub cls()
Close #n
End Sub

2.12. WORKING WITH FILES IN VBA - METHOD 1

57

Some comments
Use Open in mode Output to write to a file. Then close it and use Open in
mode Input to read from the file. Use Open in mode Append to write to the
end of the file.
Do NOT open .xls, .doc etc files with Open. Use it for text files (.txt perhaps).
If you read a character number, e.g. "12" from a file and write to the
spreadsheet, it will be usable as a number. EXCEL converts strings to numerical types. Also Integer variables are usable as Strings in VBA, for
example:
Dim i as Integer, str As String
i=3
str = "A" & i
Range(str) = "4"
places the number 4 in cell A3.

58

CHAPTER 2.

2.13

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Working with Files in VBA - Method2

File Management with the Scripting Object


A defect with the method of the previous section is that the object paradigm is
not clear. Visual Basic does not allow the creation of new classes and objects
at runtime, only instances of already defined classes. A form, for example, is
a class. It also does not allow the user to evaluate expressions at runtime.
Since VBA also connects with an application, one can use the application to
do the calculation of expressions and functions, since the application must be
able to do this at runtime. We have frequently used this facility. To get around
this, one can use a scripting language in a similar way that, say, VBScript
allows runtime calculation on the web. The Scripting Object in VB provides
additional facilities for file management, among other facilities. However, it is
not referenced in VB Help, except for file handling. We outline its use for file
manipulation. It operates within the Object Oriented paradigm.
1. FileSystemObject is the object whose properties are the Drives of the system. To create such an object use
Dim filesystem
Set filesystem = CreateObject("Scripting.FileSystemObject")

Note: The type of statement Set filesystem = New Scripting.FilesystemObject


or its variants does not seem to work in some versions of VBA. CreateObject
is used for special types, such as ActiveX objects.
2. Having created a filesystem, we can Create a File:
Dim FileName As String, f , Str As String
Assign your filename to the variable FileName, and then:
Set f = GetFile(FileName)
Str = f.path
the path to file f (without the actual filename)
f will have such properties as path, name, DateCreated, DateLastAccessed,
DateLastModified.
To delete the file use
Filesystem.GetFile(filename).Delete
3. To read or write to the file, we need to Open it and feed it into a stream
object:

2.13. WORKING WITH FILES IN VBA - METHOD2

59

Dim datastream
Set datastream = filesystem.GetFile(filename).OpenTextStream(1,-2)
datastream has properties such as the position we are at in the file, column
number, row number, AtEndOf(line), AtEndOf(File).
The arguments (1, -2) have other possibilities:
First Argument : 1 for read only, 2 for write only, 3 for appending (to the
end)
Second Argument: -2 is the system default for code type (usually ASCII), -1
Unicode, 0 ASCII
4. To check whether a file exists: there is a Boolean property
FileExist(filename)
5. Reading:
Dim Str As String
Str = datastream.ReadLine
must now parse Str to get data - alternatively
Str = datastream.Read(n)
n an integer - reads n characters

6. Writing:
datastream.Writeline
datastream.Write 5.47

writes a whole line Or


appends to the current line

7. When one has finished with the current type of operation, one must close
the file:
datastream.Close
8. Further information: In VBE go to Help|Contents|Visual Basic Language
Reference|Objects and look at FileSystemObject, File Object, Files Collection
- also look at the links on these pages. The read and write methods will be
in Contents|Visual Basic Language Reference|Methods.
9. To store and retrieve numerical data from files:
It is simplest to store one number per line - one does not then have to parse
the input string. (The file will be only slightly larger than one having multiple
data values per line.)
10. The following is an example of the use of Method 2 of file processing for input
and output of matrices.

60

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Sub SaveMatrixToFile(filename As String, matrix() As Double)


filename is just the name and qualifier e.g. "fnoo.qul", which must
be in the same directory as the workbook running the program
Dim filesystem, datastream
Dim i As Integer, j As Integer
Set filesystem = CreateObject("Scripting.FileSystemObject")
filename = Application.ActiveWorkbook.Path & Application.PathSeparator & filename
If filesystem.FileExists(filename) Then filesystem.DeleteFile filename, True
Set datastream = filesystem.CreateTextFile(filename, True)
write numrows and numcols each on a line
datastream.Writeline UBound(matrix, 1) - LBound(matrix, 1) + 1
datastream.Writeline UBound(matrix, 2) - LBound(matrix, 2) + 1
write 1st row, 2nd row, ... one element to a line
For i = LBound(matrix, 1) To UBound(matrix, 1)
For j = LBound(matrix, 2) To UBound(matrix, 2)
datastream.Writeline matrix(i, j)
Next j
Next i
datastream.Close
End Sub

Sub
Dim
Dim
Dim

ReadMatrixFromFile(filename As String, matrix() As Double)


filesystem, datastream
numrows As Integer, numcols As Integer
i As Integer, j As Integer

On Error GoTo ErrorHandler


Set filesystem = CreateObject("Scripting.FileSystemObject")
filename = Application.ActiveWorkbook.Path & Application.PathSeparator & filename
Set datastream = filesystem.GetFile(filename).OpenAsTextStream(1, -2)
numrows = datastream.Readline()
numcols = datastream.Readline()
ReDim matrix(numrows, numcols)

2.13. WORKING WITH FILES IN VBA - METHOD2

61

For i = 1 To numrows
For j = 1 To numcols
matrix(i, j) = datastream.Readline()
Next j
Next i
datastream.Close
Exit Sub
ErrorHandler:
MsgBox Err.Description, vbOKOnly, "Unhandled Error"
datastream.Close
End Sub
Sub ReadSaveMatrix_Excel_to_File(wsht As Worksheet, strRngName As String, _
strFile As String)
For example, wsht could be Sheets("Sheet1")
Dim i As Integer, j As Integer
Dim numrows As Integer, numcols As Integer
Dim matrix() As Double
numrows = wsht.Range(strRngName).Rows.Count
numcols = wsht.Range(strRngName).Columns.Count
ReDim matrix(1 To numrows, 1 To numcols)
For i = 1 To numrows
For j = 1 To numcols
matrix(i, j) = wsht.Range(strRngName).Cells(i, j).Value
Next j
Next i
SaveMatrixToFile filename:=strFile, matrix:=matrix
End Sub
Sub SaveToFile()
Dim fName As String, mat(1 To 3, 1 To 3) As Double, i As Integer, j As Integer
For i = 1 To 3
For j = 1 To 3
mat(i, j) = i * j

62

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Next
Next
SaveMatrixToFile "fnoo.txt", mat()
End Sub
Sub ReadFromFile()
Dim mat() As Double
ReadMatrixFromFile "fnoo.txt", mat()
End Sub
Sub RangeMatrixToFile()
ReadSaveMatrix_Excel_to_File Sheets("Sheet2"), "A1:C3", "fnoo.txt"
End Sub

2.14. EVENTS

2.14

63

Events

We will briefly introduce events and their use. Associated with each object
is a set of events. VBA allows one to transfer control from executing something in EXCEL to a program which will do something that you want to
do, and after completion return control to EXCEL. For example, there are
events of the type Click CommandButton1 (occurs when this button has been
clicked), the Calculate event (occurs before recalculation takes place), the
BeforeRightClick event, the BeforeDoubleClick event, the SelectionChange
and Change events, opening and closing of a workbook events and many more.
For example, to use events associated with a WorkSheet that is active, say
Sheet1, switch to the VBE and click on Sheet1 in the Project Window, then
look at the two combo boxes near the top on the right. Click on the left hand
box and choose WorkSheet. Then click on the right hand box. All the events
associted with WorkSheet are displayed. If you click on one, a sub skeleton
appears in the text portion of the window with the name of your event. You
can then fill in the actions you want taken when the event occurs in VBA.
All the embedded objects in the sheet will appear in the left hand box, and their
events in the right hand box. If you want to know the events associated with
a non-embedded object, find the object in the Object Browser - the events are
listed among the properties and methods.
An example of the use of an event is to display or hide a chart. Suppose you
have a chart in the worksheet. You can place a piece of text in one of the cells,
like Hide/Show, and use the SelectionChange event. In the code, check if the
new selection, given by Selection.Cells(1,1).Value, is equal to Hide/Show
and if it is, you can use
ActiveSheet.ChartObjects(i).Visible = False
(or set it to True) to perform the hiding or showing.

64

CHAPTER 2.

2.15

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Class Modules

Contents: Classes, Collections.


Creating an object can be conceptually useful for numerical work. We will use
an example of a Black Scholes class, which houses some of the information in a
Black Scholes Market Model and allows one to find call and put prices. Other
aspects of the model (for example the Greeks) can be added, but these will be
left as exercises.
The idea is to create a class, which we will call BS, which houses in an abstract
way all the aspects we will consider. There will be Properties of BS (such as
the initial asset price So), and Methods of BS (such as routines to calculate the
option prices.) Having defined the class BS, we will be able to create an instance
of the class (a particular BS model) and allow the user to assign the relevant
properties (such as Strike and Risk-free interest rate.) For example, the strike
price will be assigned by
BS.X = 100
Having assigned the properties, the user may determine the Call price by using
the method Cll in the statement:
dblCallValue = BS.Cll
where the LHS is a variable already declared. (Note that Call is a VBA
keyword, and cannot be used as a procedure name, so we use Cll.)
This is similar to what one does when using ordinary programming, but encapsulates all the routines in one concept. We should be able to extend classes by
adding other classes to it (for example,we may want a charting class) but unfortunately VBA does not support these hereditary aspects of the object oriented
paradigm.
The inputs to the model are of two types: those which are basic properties of
the model and those that are incidental, such as for example, user instructions
on what is to be displayed. The basic properties are usually given their own
variables and declared Private to the class. They are usually locally available
to all the routines in the class, and are therefore placed in the declarations
section. We put a prefix m in front of the name to indicate their special nature.
In our case, they are
Private mX As Double
Private mSo As Double

2.15. CLASS MODULES


Private
Private
Private
Private

65

mr As Double
msigma As Double
mT As Double
mq As Double

In our case all the variables are Double variables, so we do not indicate this
as a prefix. Other types are given a prefix.
Some of the basic properties could be made available to the user, so that they
can be checked or altered. Such a property requires two functions if it is to be
a read/write property, a Property Get routine and a Property Let routine,
and only one of these if it is to be read-only or write-only. They are of a
special type, and one of these properties in our case is
Public Property Get X() As Double
X = mX
End Property
Public Property Let X(ByVal NewX As Double)
mX = NewX
End Property
Note that the property is given a new name, X in our case. It is convenient
to give the property the same name as the variable to which it corresponds,
namely mX, but without the prefix m. The user will access the property by one
of the two types of statement:
VariableName = BS.X
BS.X = 100
The first calls Property Get, and the second calls Property Let with NewX
as 100. A similar pair of routines must be set up for each property - see the
program below.
We also use subs and functions in the class module which are Methods in object oriented terminology. There are four Methods, d1, d2, Cll, Pt. These
calculate the values of the parameters d1 and d2, and the values of the Call
and the Put respectively, in terms of the values of the basic properties. They
are accessed by the user by such statements as
VariableName = BS.Cll

66

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Although none of these methods have arguments, they could have had. They
would then be used as follows:
VariableName = BS.function1(arg1,arg2)
BS.sub1 arg1:= val1, arg2:= val2
In order to create various BS models, we need a way of creating instances of
this class, and then we need a way of defining the properties of the specific
instance through the user. To do the latter, we could:
(i) Write a sub or function which sets the properties.
(ii) Write a sub or function which reads values we have entered in a spreadsheet and uses these to set the properties.
(iii) Design an input form.
(iv) Use the InputBox facility, which in our case might look like
mX = val(InputBox("Enter the Strike Price"))
To create a new instance of the class, it is often desirable to place it in a
variable which is private to the set of routines in the module being used,
but available to all the routines in the module. One would then put in the
Declarations Section of the module:
Private mBS As BS
and in the sub that needs to create the instance:
Set mBS = New BS
Alternatively, if one is using only one sub, we could use the following in the
sub:
Dim mBS as New BS

A listing of the class BS will be given later. BS must be written in a Class


Module under the VBE, or imported via the File Menu (use Import) into
your project. It is then usable in all modules in the project. The following
is an example of initialization and use of BS, assuming that the values of the
properties have been entered in cells A1:A6 and the outputs of the Call, Put,
d1, d2 are to go in cells C1:C4.

2.15. CLASS MODULES

67

Sub bsc()
Dim mBS As New BS
mBS.x = Sheet1.Range("A1")
mBS.So = Sheet1.Range("A2")
mBS.rate = Sheet1.Range("A3")
mBS.sigma = Sheet1.Range("A4")
mBS.t = Sheet1.Range("A5")
mBS.q = Sheet1.Range("A6")
Sheet1.Range("C1").Value
Sheet1.Range("C2").Value
Sheet1.Range("C3").Value
Sheet1.Range("C4").Value

= mBS.Cll
=mBS.Pt
= mBS.d1
=mBS.d2

End Sub
Later on we will set up a new class called mBSs which organizes a collection
of instances of the BS class. We could also discuss the possibility of creating
new events for the class, and creating error handling routines. However the
basics discussed thus far will suffice for most of our purposes.
A Class definition must be entered in a Class Module which can be inserted in
a project through the Insert menu. Classes can be exported to .cls files and
imported to any project. Both Import and Export is accomplished through
the appropriate menu item in the File menu.
The name of the Class si the same as the name displayed under Class Modules
in the Project window (initially, it is Class1 or similar). To change the name,
press F4 to bring up the Properties menu and alter the name field.
There follows now a listing of the BS Class.

68

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Listing of the BS Class


Option Explicit
Private mX As Double R/W
Private mSo As Double R/W
Private mr As Double R/W
Private msigma As Double
R/W
Private mT As Double R/W
Private mq As Double R/W

X is the Strike price


So is the initial asset price
r is the Risk-free rate percentage
sigma is the Volatility percentage
T is the time in years
q is the continuous dividend rate

In variablenames of this class, the default prefix is dbl (Double variables)


Public Property Get X() As Double
X = mX
End Property
Public Property Let X(ByVal NewX As Double)
mX = NewX
End Property
Public Property Get So() As Double
So = mSo
End Property
Public Property Let So(ByVal NewSo As Double)
mSo = NewSo
End Property
Public Property Get rate() As Double
rate = mr
End Property
Public Property Let rate(ByVal Newr As Double)
mr = Newr
End Property
Public Property Get sigma() As Double
sigma = msigma
End Property
Public Property Let sigma(ByVal Newsigma As Double)
msigma = Newsigma

2.15. CLASS MODULES


End Property
Public Property Get T() As Double
T = mT
End Property
Public Property Let T(ByVal NewT As Double)
mT = NewT
End Property
Public Property Get q() As Double
q = mq
End Property
Public Property Let q(ByVal Newq As Double)
mq = Newq
End Property
Public Function d1() As Double
d1 = (Log(mSo / mX) + (mr - mq
+ 0.5 * msigma ^ 2 * mT)) / (msigma * Sqr(mT))
End Function
Public Function d2() As Double
d2 = d1 - msigma * Sqr(mT)
End Function
Public Function Cll() As Double
Cll = mSo * Application.NormSDist(d1) - mX * Exp(-mr * mT)
* Application.NormSDist(d2)
End Function
Public Function Pt() As Double
Pt = Cll() - mSo + mX * Exp(-mr * mT)
End Function

69

70

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Collections
Given a class, it is possible to construct a collection class which will keep
track of instances of the original class as they are created. In EXCEL, for
example, the WorkSheet class has a collection class Sheets, which houses all
the sheets in a Workbook that have been created. In general, if the classname
is Xyz then the collection of instances of such classes is named Xyzs.
The collection is created by dimensioning a variable As Collection and
setting it to a new instance of the class that has been created. We illustrate
this procedure by creating the collection BSs of Black-Scholes objects - see
below.
The holding variable mBSs is declared Private (which must be done in the
Declarations section.) A collection is a class which has built in methods
Add, Remove and built in Read-Only properties Item, Count. The methods add and delete an instance, the property Item finds the instance with
a given name or index and the property Count returns the number of instances in the collection. However, since the variable mBSs is Private, these
methods and properties are not available to the user. The variable could
be declared Public, but this would not allow the collection to control their
use. For example, it may be necessary to define the values of properties of
the original class, and the user cannot be trusted to do it correctly on his
own. So it is necessary to write Public versions of these properties and
methods, which use the private versions.
the public Add method here creates the BS class instance, fills in all its
properties and calls the private Add method to add the instance to the
collection. The instance can be created optionally with a name given by
the input string variable sKey. This can be used to refer to the instance
(see comments in the function definition below.) If the optional argument
is not included, the instance can be referred to by a positive integral Index.
The Remove and Count property routines are self explanatory.
There are two events, Class Initialize and Class Terminate which occur on initialization and termination of the collection. The first is used to
set the variable mBSs to an new instance of a collection. The second is used
to remove the content of this variable.
The routine NewEnum is difficult to explain properly, and may be omitted.
If it is omitted, then there is only one way to run through all instances in
the collection, namely
Dim i As Integer
For i=1 To (variable).Count
(Statements involving Item(i))
Next

2.15. CLASS MODULES

71

If the routine is included, one can, in addition, use


Dim v as Object
For Each v In (collectionvariable)
(Statements)
Next
The symbols [ NewEnum] indicates a hidden routine. There should be a way
of setting the attributes of this routine by using a statement, but I do not
know what it is. The only way I know is by importing the new collection
class into the VB6 VBE, placing the cursor on the NewEnum word in the
first line of that procedure, going to Tools|Procedure Attributes|Advanced,
filling in -4 as Procedure ID and checking the Hide this member button.
The collection class can be saved and imported back. I am not sure what
all this means.
There is a sub below which illustrates the use of the BSs collection. If you
have not included NewEnum then comment out the For Each ... Next
lines. Run the sub with the Immediate Window open.
The VB6 VBE is a better environment for creating classes. They should
be created without the EXCEL features, saved, imported and completed.
Some versions have an add-in Class Builder Utility which, among other
things, allows rapid creation of collections once the class is defined.
Classes can also raise errors and do error handling, and define events, but we
will not go into this here as they are of more limited usefulness in numerical
work.

72

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

local variable to hold collection


Private mBSs As Collection
Public Function Add(q As Double, T As Double, sigma As Double, _
rate As Double, So As Double, X As Double, Optional sKey As String) _
As BS
create a new object
Dim objNewMember As BS
Set objNewMember = New BS
set the properties passed into the method
objNewMember.q = q
objNewMember.T = T
objNewMember.sigma = sigma
objNewMember.rate = rate
objNewMember.So = So
objNewMember.X = X
If Len(sKey) = 0 Then
mBSs.Add objNewMember
Else
mBSs.Add objNewMember, sKey
End If
return the object created
Set Add = objNewMember
Set objNewMember = Nothing
End Function
Public Property Get Item(vntIndexKey As Variant) As BS
used when referencing an element in the collection
vntIndexKey contains either the Index or Key to the collection,
this is why it is declared as a Variant
Syntax: Set foo = x.Item("xyz") or Set foo = x.Item(5)
Set Item = mBSs(vntIndexKey)
End Property

Public Property Get Count() As Long


used when retrieving the number of elements in the
collection. Syntax: Debug.Print x.Count

2.15. CLASS MODULES

73

Count = mBSs.Count
End Property

Public Sub Remove(vntIndexKey As Variant)


used when removing an element from the collection
vntIndexKey contains either the Index or Key, which is why
it is declared as a Variant
Syntax: x.Remove(xyz)

mBSs.Remove vntIndexKey
End Sub

Public Property Get NewEnum() As IUnknown


this property allows you to enumerate
this collection with the For...Each syntax
Set NewEnum = mBSs.[_NewEnum]
End Property

Private Sub Class_Initialize()


creates the collection when this class is created
Set mBSs = New Collection
End Sub

Private Sub Class_Terminate()


destroys collection when this class is terminated
Set mBSs = Nothing
End Sub

Testing Routine
Sub BStest()
This is a routine testing various aspects of the BS class, BSs Collection
Dim objBS As BS, v As BS, i As Integer
Dim objBSs As BSs

74

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Set objBSs = New BSs


Set objBS = objBSs.Add .05, 1, .2, .05, 100, 105, "first")
objBSs.Add q:=.025, T:=1, sigma:=.25, rate:=.075, _
So:=90, X:=95, sKey:="second"
Debug.Print
Debug.Print
Debug.Print
Debug.Print
Debug.Print

"Call", objBS.Cll
"Put", objBS.Pt
"X", objBS.X
"rate", objBS.rate
"Count", objBSs.Count

For Each v In objBSs


Debug.Print "Call" & " " & i, v.Cll
Next
For i = 1 To objBSs.Count
Debug.Print "Put" & " " & i, objBSs.Item(i).Pt
Next
objBSs.Remove "first"
objBSs.Remove "second"
End Sub

2.16. APPENDIX 1 - VBA KEYWORDS

2.16

75

Appendix 1 - VBA Keywords

Visual Basic Naming Rules


Use the following rules when you name procedures, constants, variables, and
arguments in a Visual Basic module:
One must use a letter as the first character.
One cannot use a space, period (.), exclamation mark (!), or the characters
, &, $, # in the name.
Name cannot exceed 255 characters in length.
Do not use names that are the same as the functions, statements, and
methods in Visual Basic. You end up shadowing the same keywords in the
language.
Do not repeat names within the same level of scope. For example, one
cannot declare two variables named Age within the same procedure.
Visual Basic is not case-sensitive, but if a name is dimensioned or otherwise declared then VBA repeats the capitalization of the variable in the
declaration in all occurrences of the same variable.

76

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Data Type Summary


The following table shows the supported data types, including storage sizes and
ranges.
Data type
Byte
Boolean
Integer
Long
(long integer)

Double
(double-precision
floating-point)
Currency
(scaled integer)
Decimal

Date
Object
String
(variable-length)
String
(fixed-length)
Variant
(with numbers)
Variant
(with characters)
User-defined
(using Type)

Storage
size
1 byte
2 bytes
2 bytes
4 bytes

8 bytes

8 bytes
14 bytes

8 bytes
4 bytes
10 bytes
Length
of string
16 bytes
22 bytes
Number
required by
elements

Range
0 to 255
True or False
-32,768 to 32,767
-2,147,483,648 to 2,147,483,647 Single (singleprecision floating-point) 4 bytes -3.402823E38 to
-1.401298E-45 for negative values; 1.401298E-45
to 3.402823E38 for positive values
-1.79769313486231E308 to -4.94065645841247E324 for negative values; 4.94065645841247E-324
to 1.79769313486232E308 for positive values
-922,337,203,685,477.5808
to
922,337,203,685,477.5807
+/-79,228,162,514,264,337,593,543,950,335
with
no
decimal
point;
+/7.9228162514264337593543950335
with
28 places to the right of the decimal;
smallest non-zero number is +/0.0000000000000000000000000001
January 1, 100 to December 31, 9999
Any Object reference
+ string length 0 to approximately 2 billion
1 to approximately 65,400
Any numeric value up to the range of a Double
+ string length Same range as for variablelength String
The range of each element is the same as the
range of its data type.

Note: Arrays of any data type require 20 bytes of memory plus 4 bytes for
each array dimension plus the number of bytes occupied by the data itself.

2.16. APPENDIX 1 - VBA KEYWORDS

77

For example, the data in a single-dimension array consisting of 4 Integer data


elements of 2 bytes each occupies 8 bytes. The 8 bytes required for the data plus
the 24 bytes of overhead brings the total memory requirement for the array to
32 bytes. A Variant containing an array requires 12 bytes more than the array
alone.
Note: Use the StrConv function to convert one type of string data to another.

78

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Conversion Keyword Summary


Action
ANSI value to string.
String to lowercase or uppercase.
Date to serial number.
Decimal number to other bases.
Number to string.
One data type to another.

Date to day, month, weekday, or year.


Time to hour, minute, or second.
Second String to ASCII value.
String to number.
Time to serial number.

Keywords
Chr
Format, LCase, Ucase
DateSerial, DateValue
Hex, Oct
Format, Str
CBool, CByte, CCur, CDate,
CDbl, CDec, CInt, CLng, CSng,
CStr, CVar, CVErr, Fix, Int
Day, Month, Weekday,Year
Hour, Minute,
Asc
Val
TimeSerial, TimeValue

Data Types Keyword Summary


Action
Convert between data types.

Intrinsic data types.


Verify data types.

Keywords
CBool, CByte, CCur, CDate, CDbl, CDec,
CInt, CLng, CSng, CStr, CVar, CVErr, Fix, Int
Set
Boolean, Byte, Currency, Date, Double, Integer,
Long, Object, Single, String, Variant (default)
IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject

Math Keyword Summary


Action
Arithmetic.

Trigonometric functions.
General calculations.
Generate random numbers.
Get absolute value.
Get the sign of an expression.
Perform numeric conversions.
Rounnding.

Keywords
, , , /, Mod e.g. 10 Mod 3:
1,
+, & (string op.), =
Atn, Cos, Sin, Tan
Exp, Log, Sqr
Randomize, Rnd
Abs
Sgn
Fix, Int
Round(x[,No. Decimal Places])

result

2.16. APPENDIX 1 - VBA KEYWORDS

79

String Manipulation Keyword Summary


Action
Compare two strings.
Convert strings.
Convert to lowercase or uppercase.
Create string of repeating character.
Find length of a string.
Format a string.
Justify a string.
Manipulate strings.
Set string comparison rules.
Work with ASCII and ANSI values.

Keywords
StrComp
StrConv
Format, Lcase, Ucase
Space, String
Len
Format
LSet, Rset
InStr, Left, LTrim, Mid, Right, RTrim,
Trim
Option Compare
Asc, Chr

Prefix Conventions
Data
Prefix
Type
Boolean
bln
Currency
cur
Double
dbl
Date/Time dtm
Integer
int
Long
lng
Single
sng
String
str
Variant
vnt

Relational and Logical Operators


Relational Operators
>
(greater than)
<
(less than)
=
(equal to)
>=
(greater than or equal to)
<=
(less than or equal to)
<>
(not equal to)

Logical Operators
And
Or
Not

80

CHAPTER 2.

VISUAL BASIC FOR APPLICATIONS EXCEL 2007

Dates and Times Keyword Summary


Action
Get the current date or time.
Perform date calculations.
Return a date.
Return a time.
Set the date or time.
Time a process.

Keywords
Date, Now, Time
DateAdd, DateDiff, DatePart
DateSerial, DateValue
TimeSerial, TimeValue
Date, Time
Timer

Directories and Files Keyword Summary


Action
Change directory or folder.
Change the drive.
Make directory or folder.
Remove directory or folder.
Name Return current path.
Return file date/time stamp.
Return file, directory, label attributes.
Return file length.
Return file name or volume label.
Set attribute information for a file.

Keywords
ChDir
ChDrive
MkDir
RmDir
CurDir
FileDateTime
GetAttr
FileLen
Dir
SetAttr

2.17. EXERCISES

2.17

81

Exercises

1. Write a subroutine which takes as input a range in the form A1:C50 and
clears the range of all content, all borders and also of colour. Allow the user
instead to clear these from the currently selected range. [If necessary, get
ideas from running a macro].
2. Write a subroutine for estimating the cumulative normal distribution by
means of a polynomial. Look up an appropriate algorithm in Press etal
or Hull or somewhere similar.
3. Write a subroutine which multiplies two variables representing matrices. Input also the matrix sizes. Do similarly for a subroutine for taking the transpose of a matrix.
4. Write three functions which return values drawn from a Uniform, Poisson
and Binomial distribution.
5. Write a function for solving an single equation of the form f (x) = 0 by
Newtons method and by the Newton-Bailey method. [Look them up if necessary].
6. Extend the previous question to the case of more than one equation.