You are on page 1of 12

Excel for Chemists: A Comprehensive Guide. E.

Joseph Billo
Copyright  2001 by John Wiley & Sons, Inc.
ISBNs: 0-471-39462-9 (Paperback); 0-471-22058-2 (Electronic)

15
WORKING WITH ARRAYS IN VBA
Many scientists make extensive use of arrays in their calculations. Because
arrays in VBA can be quite confusing, this chapter provides detailed coverage
of this important topic.

VISUAL BASIC ARRAYS


If you’re familiar with other programming languages you are probably
familiar with the concept of an array. An array is a collection of related
variables denoted by a single name, such as Sample. You can then specify any
element in the array by using an index number: Sample(l), Sample(Y), etc.

DIMENSIONING AN ARRAY
The Dim statement is used to declare the size of an array. Unless specified
otherwise, VBA arrays begin with an index of 0. The statement

Dim Sample( 10)

establishes array storage for 11 elements, Sample(O) through Sample(l0).


You can specify the lower bound of an array in the Dim statement. For
example,
Dim Sample (1 To 10)
allows you to specify any value, even negative values, for the lower or upper
bounds of an array. Alternatively, you can use the Option Base 1 statement,
which specifies that all arrays begin with a lower index of 1. The Opt ion
Base 1 statement is used at the module level: that is, it must appear in a
module sheet ahead of any procedures.

Excel Tip. Since worksheet ranges, worksheet functions and worksheet


arrays use (or assume) a lower array index of 1, you should always
include the Option Base I statement at the beginning of each code
module that uses arrays.

Several variables can be dimensioned in a single Dim statement.

279
280 Excel for Chemists

It’s considered good programming practice to put the Dim statements at the
beginning of the procedure.

USE THE NAME OF THE ARRAY VARIABLE


TO SPECIFY THE WHOLE ARRAY
You can refer to the complete array by using the array variable name in
your code. Sometimes the array name can be used with parentheses, other times
without parentheses.

MULTIDIMENSIONAL ARRAYS
Arrays can be multidimensional. Excel permits arrays with up to 60
dimensions; one-, two- and three-dimensional arrays are common. To create a 2-
D array with dimensions 2 x 500, use the statement

Dim Spectrum (2,500)


Since multidimensional arrays such as the one above can use up significant
amounts of memory, it’s important to define the data type of the variable. The
complete syntax of the Dim statement is

Dim VariableName(Lower To Upper) As Type

The optional Lower To can be omitted. Type can be Integer, Single,


Double, Variant, etc. See the complete list of data types in “VBA Data
Types” in chapter 13.) A Variant array can hold values of different data types
(e.g., 1.173 and “Billo, E. Joseph”).
Several variables can be dimensioned in a single Dim statement, but there
mu st be a separate As Type for each variable.

RETURNING THE DIMENSIONS OF AN ARRAY


Use the LBound and UBound functions to obtain the dimensions of an array
during execution of your procedure. The LBound function returns the lower index
of an array. For example, for the array Sample described previously,
LBound(Sample) returns 1 and UBound(Sample) returns 10.
The complete syntax of LBound and UBound is LBound ,(arrayname,
dimension). For the array Spectrum dimensioned thus:
Dim Spectrum (2,500)
the statement UBound(Spectrum,l) returns 2 and UBound(Spectrum,2) returns
500 .

DYNAMIC ARRAYS
If you don’t know what array size you will need to handle a particular
Chapter 15 Working with Arrays in VBA 281

problem, you can create a dynamic array. This will allow you to declare a
variable as an array but set its size later. Dimension the array using the Dim
command, using empty parentheses; use the ReDim command later to specify
the array size, e.g.,

Dim MeanX(), MeanY()

‘Get number of cells to use in calculation


Ncells = XValues.Count
ReDim MeanX(Ncells), MeanY(Ncells)
You can also use the ReDim command to change the nurnber of dimensions of
an array.
The ReDim command can appear more than once in a procedure.

PRESERVING VALUES IN DYNAMIC ARRAYS


You can also use the ReDim statement to re-size an existing array during
execution of the code. For example, your procedure initially may need an array
of 5 x 2000 elements, but later, during execution on a particular data set, a much
smaller number of array elements may be needed. You can free up memory by re-
sizing the array during execution. However, the ReDim statement re-
initializes the array (numbers are set to zero, strings to null, objects to Nothing,
for example). You can preserve the values in an existing array by using the
Preserve keyword, e.g.,

Dim MeanX(), MeanY()

ReDim Preserve MeanX(Ncells / 2), MeanY(Ncells / 2)


But, there’s a limitation. Only the upper bound of the last dimension of a
multidimensional array can be changed. Thus, the following code is valid:

Dim BothMeans(2, 1000)

ReDim Preserve BothMeans(2,Ncells / 2)

but the following code will generate a run-time error:

Dim BothMeans(lOO0, 2)

ReDim Preserve BothMeans(Ncells / 2, 2)

If you use Preserve, you can’t use the ReDim command to change the
number of dimensions of an array.
282 Excel for Chemists

WORKING WITH ARRAYS


IN SUB PROCEDURES: PASSING VALUES
FROM WORKSHEET TO VBA MODULE
There are at least two ways to get values from a worksheet into a VBA
array. You can either set up a loop to read the value of each worksheet cell and
write the value to the appropriate element of an array, or you can assign the
VBA array to a worksheet range. These two methods are described next. There
is a definite difference with respect to speed. (See “Speed Differences in
Reading or Writing Arrays Created by Two Different Methods” later in this
chapter.)

USING A LOOP TO TRANSFER VALUES


FROM A WORKSHEET TO A VBA ARRAY
The Sub procedure shown in Figure 15-1 reads values from worksheet cells
and writes them to elements of a VBA array by means of a loop. Either the
Cells method or the Range method can be used; in the example that follows,
the Range method is used, with the concatenation operator, to access the
appropriate cell in the range. In this example the values to be copied are in
column A, beginning in row 2. To illustrate an additional point, the values
extend down to a row that must be determined by the VBA code.
The code to obtain the row number of the last-used row in the block of cells
in column A was obtained by using the Recorder to record the VBA code
corresponding to CONTROL+SHIFT+(down arrow).

Sub ArrayDemo ()
‘Reads values from column A, beginning in row 2,
‘into a VBA array.
I++++++++++++++++++++++++++++++++++++++++
Dim TestArray
LastRow = Range(“A2”).End(xlDown).Row
NCells = LastRow - 1
ReDim TestArray(NCells)
For x = 2 To LastRow
TestArray(x - 1) = Range(“A” & x)
Next x
MsgBox “First array element = ” & TestArray(1) & Chr(13) & _
“Last array element = ” & TestArray(NCells)
End Sub
Figure 15-l. Reading values into a VBA array.
Chapter 15 Working with Arrays in VBA 283

A RANGE SPECIFIED IN A SUB PROCEDURE


CAN BE SET EQUAL TO AN ARRAY VARIABLE
If a variable in a VBA Sub procedure is set equal to a range of cells in a
worksheet, that variable becomes an array. No Dim statement is necessary.
Thus the following expression in Figure 15-2 creates a VBA array called
TestArray:

TestArray = Range(“A2:AlO”)
The worksheet array can be a range reference or a name that refers to a
reference. Thus, if the name XRange had been assigned to the range ” A2 : A 10 ‘I,
then the following expression would also create a VBA array called TestArray:
TestArray = Range(“XRange”)
A one-row or one-column reference becomes a one-dimensional array; a
rectangular range becomes a two-dimensional array of dimensions a rray(ro ws,
columns).
The lower index of these arrays is always 1. Although arrays created
within VBA have a lower array index of zero unless specified otherwise (by
means of the Option Base 1 statement, for example), when you transfer a
range of cells from a worksheet to VBA, an array is created with lower arrav J

index of 1.

Sub ArrayDemo
‘Reads values from column A, beginning in row 2,
‘into a VBA array.
I++++++++++++++++++++++++++++++++++++++++
TestArray = Range(“A2:AlO”)
MsgBox “Fifth array element = ” & TestArray(5, 1)
Msg Box “Now changing first array element to zero.”
TestArray(5, 1) = 0
Msg Box “Confirming that first array element = ” & TestArray(5, 1)
MsgBox “Please examine first array element on worksheet.”
End Sub
Figure 15-2. Another way to create a VBA array.

SOME WORKSHEET FUNCTIONS USED WITHIN VBA


CREATE AN ARRAY
If you use a worksheet function within VBA that returns an array, the
lower array index will be 1. Such worksheet functions include: LINEST,
TRANSPOSE, MINVERSE, MMULT. Other functions that return arrays include the
VBA function Caller when used with a menu command or toolbutton.
284 Excel for Chemists

Note that the values in the range of cells have not been transferred to a
VBA array; the VBA variable simply “points” to the range on the worksheet.

AN ARRAY OF OBJECT VARIABLES


There is an important difference between equating a range of cells in a
worksheet to a simple variable in VBA, thus:
ar = Range(“A2:Bg”)
or equating a range of cells in a worksheet an object variable by using the Set
command, thus:
Set ar = Range(“A2:Bg”)
Equating a variable in VBA to a worksheet range automatically creates an
array in VBA in which each array element contains the value stored in the
cell. Using the Set command to equate an object variable in VBA to a
worksheet range automatically creates an array of “cell” objects in VBA. If you
change the value of one of the array elements by means of your VBA code, the
value in that cell in the worksheet will change, as illustrated by the Sub
procedure in Figure 15-3.
For an array of object variables, you must use a different approach to obtain
the upper or lower bounds of the array indices, thus:
ar.Rows.Count

or

ar.Columns.Count.

Sub ArrayDemo2aO
‘Reads values from column A, beginning in row 2,
‘into a VBA array of object variables.
I++++++++++++++++++++++++++++++++++++++++++
Set TestArray = Range(“A2:AlO”)
,MsgBox “Fifth array element = ” & TestArray(5)
MsgBox “Now changing fifth array element to zero.”
TestArray(5) = 0
Msg Box “Confirming that fifth array element = ” & TestArray(5)
MsgBox “Please examine fifth array element on worksheet.”
lend Sub
Figure 15-3. Creating an array of object variables.
Chapter 15 Working with Arrays in VBA 285

WORKINGWITHARRAYSIN SUB PROCEDURES:


PASSING VALUESFROM A VBA MODULE
TO A WORKSHEET
There are at least two ways to send values from a VBA array to a
worksheet. You can either set up a loop and write the value of each array
element to a worksheet cell, or you can assign the value of the VBA array to the
value of a worksheet range.

USING A LOOP TO TRANSFER VALUES


FROM A VBA ARRAY TO A WORKSHEET
To write the value of each array element to a worksheet cell, you can use
either the Cells method or the Range method. In the example shown in
Figure 15-4, the Cells method is used.

Sub ArrayDemo
‘Demo to illustrate writing array values to a sheet
‘by means of a loop.
I++++++++++++++++++++++++++++++++++++++++++
D i m TestArray( 10)
‘Puts the numbers 11, 12, 13... in a VBA array.
For x = 1 To 10: TestArray = 10 + x: Next
‘Then writes the array elements to cells Dl :DlO.
For x = 1 To 10
Cells(x, 4).Value = TestArray
Next x
End Sub
Figure 15-4. Passing values from a VBA array to a worksheet.

This method is straightforward, although sometimes not as convenient as


the method that follows.

EQUATING A WORKSHEET RANGE TO AN ARRAY VARIABLE


In the example shown in Figure 15-5, a 2-D range on a worksheet becomes an
array in VBA. Then the array elements are written back to the worksheet with
a single line of code.
This is much more convenient than the loop method, where two nested loops
would be required to read or write a 2-D range. However, a problem arises
when you use this method with a 1-D range, as described next.
286 Excel for Chemists

Sub ArrayDemo
‘Demo to illustrate writing array values to a sheet
‘by writing the array.
I++++++++++++++++++++++++++++++++++++++++++
TestArray = ActiveSheet.Range(“Al:B5000”)
Range(“D1 :E5000”) = TestArray
End Sub
Figure 15-5. Another way to write values from a VBA array to a worksheet.

A&DIMENSIONALARRAYASSIGNEDTOAWORKSHEETRANGE
CAN CAUSE PROBLEMS
Arrays can cause some confusion when you write the array back to a
worksheet by assigning the value of the array to a worksheet range.
VBA considers a one-dimensional array to have the elements of the array
in a row. This can cause problems when you select a range of cells in a column
and assign an array to it, as in the Sub procedure shown in Figure 15-6.

Sub ArrayDemo
‘Illustrates that 1-D VBA arrays have elements in a row,
‘not a column.
‘Was supposed to put the numbers 11, 12, 13... in El :ElO.
‘But instead writes element(l) in all cells.
I++++++++++++++++++++++++++++++++++++++++++
D i m TestArray( 10)
‘Puts the numbers 11, 12, 13... in a VBA array.
For x = 1 To 10: TestArray = 10 + x: Next
‘Then writes the array elements to cells E1:ElO.
Range(“E1 :El O”).Value = TestArray
End Sub
Figure 15-6. From a VBA array to a worksheet: the row-column problem.

If you run the preceding Sub procedure, you will find that cells El througn
El 0 will all contain 11, the first element of the array. However, if you write
the array to a row of cells instead of a column, thus:
Range(“E1 :Nl”).Value = TestArray
each cell of the range will receive the correct array value.
There are at least three ways to “work around” this problem caused by
“horizontal” and “vertical” arrays. One way is to use a loop to write the
elements of the array to individual worksheet cells in a column (Figure 15-7),
instead of using the more convenient procedure of assigning the array variable
to a range of cells in the worksheet.
Chapter 15 Working with Arrays in VBA 287

Sub ArrayDemoG()
‘One method to “work around” the row-column problem:
‘write the array elements using a loop.
I+++++++++++++++++++++++++++++++++++++++++++++++
Dim TestArray(l0)
‘Puts the numbers 11, 12, 13... in a VBA array.
For x = 1 To 10: TestArray = IO + x: Next
‘Then writes the array elements to cells El :ElO.
DestRow = 0 : DestCol = 5
For x = 1 To 10
CeIIs(DestRow + x, DestCol) = TestArray
Next
End Sub
Figure 15-7. One method to “work around” the row-column problem.

A second way is to specify both the row and the column dimensions of the
array, so as to make it an array in a column, as illustrated in the Sub procedure
shown in Fiare 15-8.

Sub ArrayDemo
‘Second method to “work around” the row-column problem:
‘specify the row and column dimensions.
I+++++++++++++++++++++++++++++++++++++++++++++++
‘Puts the numbers 11, 12, 13... in a VBA array.
Dim TestArray(l0, 1)
For x = 1 To 10: TestArray(x, 1) = 10 + x: Next
‘Then writes the array elements to cells El:ElO.
Range(“E1 :El O”).Value = TestArray
End Sub
Figure 15-8. A second way to “work around” the rowxolumn problem.

A third way is to use the TRANSPOSE worksheet function (Figure 15-9):

Sub ArrayDemo
Another method to “work around” the row-column problem: use
Transpose. Note that Transpose creates a l-base array.
+++++++++++++++++++++++++++++++++++++++++++++++
Dim TestArray(l0)
‘Puts the numbers 11, 12, 13... in a VBA array.
For x = 1 To 10: TestArray = IO + x: Next
NewArray = Application.Transpose(TestArray)
Range(“E1 :El O”).Value = NewArray
End Sub
Figure 15-9. A third way to “work around” the row-column problem.
288 Excel for Chemists

SPEED DIFFERENCES IN READING OR WRITING ARRAYS


CREATED BY TVVO DIFFERENT METHODS
There is a marked difference in the speed of execution of the two methods of
reading or writing arrays just described. When you are writing values from a
VBA array to a range of worksheet cells, assigning the array name to the range
reference, as illustrated by Sub procedure ArrayDemo4, is much faster than
using a loop, as in ArrayDemo3. The same is true when you are reading
worksheet cells into a VBA array. However, VBA code that involves accessing
the individual array elements (such as summing or comparing all the elements
of an array) executes much faster when the cell values have been read into
elements of a VBA array that was declared by means of a Dim statement. Thus
if your arrays are large, the method you use to “create” the array should be
guided by what you intend to do with the array.

WORKING WITH ARRAYS


IN FUNCTIONPROCEDURES:
FROMWORKSHEET To MODULE
You can create Function procedures that use arrays as arguments, or return
an array as a result.

A RANGE PASSED TO A FUNCTION PROCEDURE


AUTOMATICALLY BECOMES AN ARRAY
If a range argument is passed in a function macro, the range automatically
becomes an array in the VBA procedure. No Dim statement is necessary. Thus
the expression
Function Deming(XValues, Yvalues)

passes the worksheet ranges XValues and Yvalues to the VBA procedure where
they become arrays.
A one-row or one-column reference becomes a one-dimensional array; a
rectangular range becomes a two-dimensional array of dimensions array(rows,
columns).
The Function procedure in Figure 15-10 is identical to Excel’s INDEX
worksheet function: it passes a range and a number as arguments and returns the
xth element of the array.
The name of the array in the procedure must be the name of the placeholder
argument of the function.
Chapter 15 Working with Arrays in VBA 289

IFunction ArrayDemog(ArrayRef, x)
(‘Shows how to pass an array as an argument.
I+++++++++++++++++++++++++++++++++++++++++++++++
ArrayDemo = ArrayRef(x)
End Function
Figure 15-10. Passing an array as an argument in a Function procedure.

PASSING AN INDEFINITE NUMBER OF ARGUMENTS


USING THE PARAMARRAY KEYWORD
Occasionally a Function procedure needs to accept an indefinite number or
arguments. The SUM worksheet function is an example of such a function; its
syntax is =SUM(numberl ,number2,...). To allow a Function procedure to
accept an indefinite number of arguments, use the ParamArray keyword in the
argument list of the function, as in the following expression
Function ConcatenateSpeciaI(ParamArray String1 0)
Only one argument can follow the Pa r a m Array keyword, and it must be
the last one in the function’s list of arguments. The argument declared by the
Pa ra m Ar r ay keyword is an array of Variant elements. Empty parentheses
are required.
Interestingly, even if you use the Option Base 1 statement, the lower
bound of the array is zero.
Elements in the array of arguments passed using the Pa r a m Array
keyword can themselves be arrays.

RETURNING AN ARRAY OF VALUES AS A RESULT


There are seve ral ways to enable a Function proced ure to return an array of
values. The most obvious is to assemble the va .lues in arrav and return the
array. The procedure shown in Figure 15-11 illustrates a function that returns
an array of values: the letters a, b, c and d in a 2 x 2 array. The function requires
no arguments. The user must select a 2 x 2 range of cells, enter the function and
press, CONTROL+SHIFT+ENTER.
A second approach is to use the Array keyword. The Array function
returns a variant that contains an array. In the Sub procedure shown in Figure
15-12, the variable MyArray contains an array of text values, but an array can
contain text, number values, the value of a VBA variable, even a Range
reference.
To use this function the user must select a horizontal range of cells, enter the
function, and press CONTROL+SHIFT+ENTER.
290 Excel for Chemists

Function ArrayDemo 10
‘Shows one way to return an array of values:
‘Create an actual array by using the Dim statement.
I+++++++++++++++++++++++++++++++++++++++++++++++
Dim ReturnValu(2, 2)
ReturnValu(1, 1) = “a”
ReturnValu(1, 2) = “b”
ReturnValu(2, 1) = “c”
ReturnValu(2, 2) = “d”
ArrayDemo 1 = ReturnValu()
End Function
Figure 1541. A Function procedure that returns an array.

Function ArrayDemo 20
‘Shows another way to return an array of values: the Array keyword
‘Array returns a single variable of Variant type
‘that contains an array.
‘Only 1 -dimensional array, though.
I+++++++++++++++++++++++++++++++++++++++++++++++
MyArray = Array(“Jan”, “Feb”, “Mar”, “Apr”, “May”, “Jun”, _
II II “Aug”, “Sep”, “Ott”, “Nov”, “Dee”)
Jul
ArrayDemo 1 = MyArray
End Function
Figure 1542. Using the Array keyword in a Function procedure.

The A r ray keyword can accommodate only a one-dimensional array. To


use this approach to return a two-dimensional array, you can create an array of
arrays, as illustrated in Figure 15-13. This function returns the letters a, b, c and
d in a 2 x 2 array.

Function ArrayDemo 30
‘Shows another way to return a 2-D array of values.
‘Use the Array function in a nested fashion.
, ArrayDemo 3 = Array(Array(“a”, “b”), Array(“c”, “d”))
End Function
Figure 1543. Using the Array keyword to return a 2-D array.

In each of the preceding examples, you must select an appropriate range of


cells to contain the result, enter the function, and press CONTROL+SHIFT+ENTER
(Excel for Windows) or CONTROL+SHIFT+RETURN (Excel for the Macintosh).

You might also like