Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
126 views

Excel VBA Array - The Complete Guide - Excel Macro Mastery

Uploaded by

BELAID
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
126 views

Excel VBA Array - The Complete Guide - Excel Macro Mastery

Uploaded by

BELAID
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Firefox https://excelmacromastery.

com/excel-vba-array/

Member Area  VBA Articles Courses

Webinars About

Excel VBA Array – The Complete Guide


by Paul Kelly | | Data Structures VBA, Most Popular | 312 comments

This post provides an in-depth look at the VBA array which is a very important part of
the Excel VBA programming language. It covers everything you need to know about the
VBA array.

We will start by seeing what exactly is the VBA Array is and why you need it.

Below you will see a quick reference guide to using the VBA Array. Refer to it anytime
you need a quick reminder of the VBA Array syntax.

The rest of the post provides the most complete guide you will �nd on the VBA array.

Contents [hide]

1 Related Links for the VBA Array


2 A Quick Guide to the VBA Array
3 Download the Source Code and Data
4 What is the VBA Array and Why do You Need It?
5 Two Types of VBA Arrays
6 VBA Array Initialization
7 Assigning Values to VBA Array
8 VBA Array Length
9 Using the Array and Split function
10 Using Loops With the VBA Array

1 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

10.1 Using the For Each Loop with the VBA Array

11 Using Erase with the VBA Array


12 Increasing the length of the VBA Array

12.1 Using Preserve with Two-Dimensional Arrays

13 Sorting the VBA Array


14 Passing the VBA Array to a Sub
15 Returning the VBA Array from a Function
16 Using a Two-Dimensional VBA Array
17 Using the For Each Loop
18 Reading from a Range to the VBA Array
19 How To Make Your Macros Run at Super Speed
20 Conclusion
21 What’s Next?

Related Links for the VBA Array


Loops are used for reading through the VBA Array:
For Loop
For Each Loop

Other data structures in VBA:


VBA Collection – Good when you want to keep inserting items as it automatically resizes.
VBA ArrayList – This has more functionality than the Collection.
VBA Dictionary – Allows storing a Key\Value pair. Very useful in many applications.

The Microsoft guide for VBA Arrays can be found here.

A Quick Guide to the VBA Array


Task Static Array Dynamic Array

Declare Dim arr(0 To Dim arr() As Long


5) As Long Dim arr As Variant

Set Size See Declare ReDim arr(0 To 5)As Variant


above

Get See ArraySize See ArraySize function below.


Size(number function
of items) below.

2 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Task Static Array Dynamic Array

Increase size Dynamic Only ReDim Preserve arr(0 To 6)


(keep existing
data)

Set values arr(1) = 22 arr(1) = 22

Receive total = arr(1) total = arr(1)


values

First position LBound(arr) LBound(arr)

Last position Ubound(arr) Ubound(arr)

Read all For i = LBound(arr) For i = LBound(arr) To UBound(arr)

items(1D) To UBound(arr) Next i

Next i Or
Or For i = LBound(arr,1) To UBound(arr,1)

For i = Next i

LBound(arr,1) To

UBound(arr,1)

Next i

Read all For i = For i = LBound(arr,1) To UBound(arr,1)

items(2D) LBound(arr,1) To For j = LBound(arr,2) To UBound(arr,2)

UBound(arr,1) Next j

For j = Next i

LBound(arr,2) To

UBound(arr,2)

Next j

Next i

Read all items Dim item As Dim item As Variant


Variant For Each item In arr
For Each item Next item
In arr
Next item

3 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Task Static Array Dynamic Array

Pass to Sub Sub Sub MySub(ByRef arr() As


MySub(ByRef String)
arr() As
String)

Return from Function Function GetArray() As Long()


Function GetArray() As Dim arr() As Long
Long() GetArray = arr
Dim arr(0 End Function
To 5) As Long
GetArray =
arr
End Function

Receive from Dynamic only Dim arr() As Long


Function Arr = GetArray()

Erase array Erase arr Erase arr


*Resets all *Deletes array
values to
default

String to Dynamic only Dim arr As Variant


array arr =
Split("James:Earl:Jones",":")

Array to Dim sName As Dim sName As String


string String sName = Join(arr, ":")
sName =
Join(arr, ":")

Fill with Dynamic only Dim arr As Variant


values arr = Array("John", "Hazel",
"Fred")

Range to Dynamic only Dim arr As Variant


Array arr = Range("A1:D2")

Array to Same as Dim arr As Variant


Range dynamic Range("A5:D6") = arr

4 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Download the Source Code and Data


Please click on the button below to get the fully documented source code for this article.

What is the VBA Array and Why do You Need It?


A VBA array is a type of variable. It is used to store lists of data of the same type. An
example would be storing a list of countries or a list of weekly totals.

In VBA a normal variable can store only one value at a time.

In the following example we use a variable to store the marks of a student:

' Can only store 1 value at a time


Dim Student1 As Long
Student1 = 55

If we wish to store the marks of another student then we need to create a second
variable.

In the following example, we have the marks of �ve students:

Student Marks

We are going to read these marks and write them to the Immediate Window.

Note: The function Debug.Print writes values to the Immediate Window. To view this
window select View->Immediate Window from the menu( Shortcut is Ctrl + G)

5 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

6 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

As you can see in the following example we are writing the same code �ve times – once
for each student:

' https://excelmacromastery.com/
Public Sub StudentMarks()

' Get the worksheet called "Marks"


Dim sh As Worksheet
Set sh = ThisWorkbook.Worksheets("Marks")

' Declare variable for each student


Dim Student1 As Long
Dim Student2 As Long
Dim Student3 As Long
Dim Student4 As Long
Dim Student5 As Long

' Read student marks from cell


Student1 = sh.Range("C" & 3).Value
Student2 = sh.Range("C" & 4).Value
Student3 = sh.Range("C" & 5).Value
Student4 = sh.Range("C" & 6).Value
Student5 = sh.Range("C" & 7).Value

' Print student marks


Debug.Print "Students Marks"
Debug.Print Student1
Debug.Print Student2
Debug.Print Student3
Debug.Print Student4
Debug.Print Student5

End Sub

The following is the output from the example:

7 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Output

The problem with using one variable per student is that you need to add code for each
student. Therefore if you had a thousand students in the above example you would
need three thousand lines of code!

Luckily we have arrays to make our life easier. Arrays allow us to store a list of
data items in one structure.

The following code shows the above student example using an array:

' ExcelMacroMastery.com
' https://excelmacromastery.com/excel-vba-array/
' Author: Paul Kelly
' Description: Reads marks to an Array and write
' the array to the Immediate Window(Ctrl + G)
' TO RUN: Click in the sub and press F5
Public Sub StudentMarksArr()

' Get the worksheet called "Marks"


Dim sh As Worksheet
Set sh = ThisWorkbook.Worksheets("Marks")

' Declare an array to hold marks for 5 students


Dim Students(1 To 5) As Long

' Read student marks from cells C3:C7 into array


' Offset counts rows from cell C2.
' e.g. i=1 is C2 plus 1 row which is C3
' i=2 is C2 plus 2 rows which is C4
Dim i As Long
For i = 1 To 5
Students(i) = sh.Range("C2").Offset(i).Value
Next i

8 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Print student marks from the array to the Immediate Window
Debug.Print "Students Marks"
For i = LBound(Students) To UBound(Students)
Debug.Print Students(i)
Next i

End Sub

The advantage of this code is that it will work for any number of students. If we have to
change this code to deal with 1000 students we only need to change the (1 To 5) to (1 To
1000) in the declaration. In the prior example we would need to add approximately �ve
thousand lines of code.

Let’s have a quick comparison of variables and arrays. First we compare the declaration:

' Variable
Dim Student As Long
Dim Country As String

' Array
Dim Students(1 To 3) As Long
Dim Countries(1 To 3) As String

Next we compare assigning a value:

' assign value to variable


Student1 = .Cells(1, 1)

' assign value to first item in array


Students(1) = .Cells(1, 1)

Finally we look at writing the values:

' Print variable value


Debug.Print Student1

9 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Print value of first student in array


Debug.Print Students(1)

As you can see, using variables and arrays is quite similar.

The fact that arrays use an index(also called a subscript) to access each item is
important. It means we can easily access all the items in an array using a For Loop.

Now that you have some background on why arrays are useful let’s go through them
step by step.

Two Types of VBA Arrays


There are two types of VBA arrays:

1. Static – an array of �xed length.


2. Dynamic(not to be confused with the Excel Dynamic Array) – an array where the
length is set at run time.

The di�erence between these types is mostly in how they are created. Accessing values
in both array types is exactly the same. In the following sections we will cover both of
these types.

VBA Array Initialization


A static array is initialized as follows:

' https://excelmacromastery.com/
Public Sub DecArrayStatic()

' Create array with locations 0,1,2,3


Dim arrMarks1(0 To 3) As Long

' Defaults as 0 to 3 i.e. locations 0,1,2,3


Dim arrMarks2(3) As Long

' Create array with locations 1,2,3,4,5


Dim arrMarks3(1 To 5) As Long

10 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Create array with locations 2,3,4 ' This is rarely used
Dim arrMarks4(2 To 4) As Long

End Sub

An Array of 0 to 3

As you can see the length is speci�ed when you declare a static array. The problem with
this is that you can never be sure in advance the length you need. Each time you run the
Macro you may have di�erent length requirements.

If you do not use all the array locations then the resources are being wasted. So if you
need more locations you can use ReDim but this is essentially creating a new static
array.

The dynamic array does not have such problems. You do not specify the length when
you declare it. Therefore you can then grow and shrink as required:

' https://excelmacromastery.com/
Public Sub DecArrayDynamic()

' Declare dynamic array


Dim arrMarks() As Long

' Set the length of the array when you are ready
ReDim arrMarks(0 To 5)

End Sub

The dynamic array is not allocated until you use the ReDim statement. The advantage is
you can wait until you know the number of items before setting the array length. With a
static array you have to state the length upfront.

To give an example. Imagine you were reading worksheets of student marks. With a
dynamic array you can count the students on the worksheet and set an array to that
length. With a static array you must set the length to the largest possible number of

11 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

students.

Assigning Values to VBA Array


To assign values to an array you use the number of the location. You assign the value for
both array types the same way:

' https://excelmacromastery.com/
Public Sub AssignValue()

' Declare array with locations 0,1,2,3


Dim arrMarks(0 To 3) As Long

' Set the value of position 0


arrMarks(0) = 5

' Set the value of position 3


arrMarks(3) = 46

' This is an error as there is no location 4


arrMarks(4) = 99

End Sub

The array with values assigned

The number of the location is called the subscript or index. The last line in the example
will give a “Subscript out of Range” error as there is no location 4 in the array example.

VBA Array Length


There is no native function for getting the number of items in an array. I created the
ArrayLength function below to return the number of items in any array no matter how
many dimensions:

12 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' https://excelmacromastery.com/
Function ArrayLength(arr As Variant) As Long

On Error Goto eh

' Loop is used for multidimensional arrays. The Loop will terminate when a
' "Subscript out of Range" error occurs i.e. there are no more dimensions.
Dim i As Long, length As Long
length = 1

' Loop until no more dimensions


Do While True
i = i + 1
' If the array has no items then this line will throw an error
Length = Length * (UBound(arr, i) - LBound(arr, i) + 1)
' Set ArrayLength here to avoid returing 1 for an empty array
ArrayLength = Length
Loop

Done:
Exit Function
eh:
If Err.Number = 13 Then ' Type Mismatch Error
Err.Raise vbObjectError, "ArrayLength" _
, "The argument passed to the ArrayLength function is not an array."
End If
End Function

You can use it like this:

' Name: TEST_ArrayLength


' Author: Paul Kelly, ExcelMacroMastery.com
' Description: Tests the ArrayLength functions and writes
' the results to the Immediate Window(Ctrl + G)
Sub TEST_ArrayLength()

' 0 items
Dim arr1() As Long

13 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Debug.Print ArrayLength(arr1)

' 10 items
Dim arr2(0 To 9) As Long
Debug.Print ArrayLength(arr2)

' 18 items
Dim arr3(0 To 5, 1 To 3) As Long
Debug.Print ArrayLength(arr3)

' Option base 0: 144 items


' Option base 1: 50 items
Dim arr4(1, 5, 5, 0 To 1) As Long
Debug.Print ArrayLength(arr4)

End Sub

Using the Array and Split function


You can use the Array function to populate an array with a list of items. You must
declare the array as a type Variant. The following code shows you how to use this
function.

Dim arr1 As Variant


arr1 = Array("Orange", "Peach","Pear")

Dim arr2 As Variant


arr2 = Array(5, 6, 7, 8, 12)

Contents of arr1 after using the Array function

The array created by the Array Function will start at index zero unless you use Option
Base 1 at the top of your module. Then it will start at index one. In programming, it is

14 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

generally considered poor practice to have your actual data in the code. However,
sometimes it is useful when you need to test some code quickly.

The Split function is used to split a string into an array based on a delimiter. A delimiter
is a character such as a comma or space that separates the items.

The following code will split the string into an array of four elements:

Dim s As String
s = "Red,Yellow,Green,Blue"

Dim arr() As String


arr = Split(s, ",")

The array after using Split

The Split function is normally used when you read from a comma-separated �le or
another source that provides a list of items separated by the same character.

Using Loops With the VBA Array


Using a For Loop allows quick access to all items in an array. This is where the power of
using arrays becomes apparent. We can read arrays with ten values or ten thousand
values using the same few lines of code. There are two functions in VBA called LBound
and UBound. These functions return the smallest and largest subscript in an array. In an
array arrMarks(0 to 3) the LBound will return 0 and UBound will return 3.

The following example assigns random numbers to an array using a loop. It then prints
out these numbers using a second loop.

' https://excelmacromastery.com/
Public Sub ArrayLoops()

15 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Declare array


Dim arrMarks(0 To 5) As Long

' Fill the array with random numbers


Dim i As Long
For i = LBound(arrMarks) To UBound(arrMarks)
arrMarks(i) = 5 * Rnd
Next i

' Print out the values in the array


Debug.Print "Location", "Value"
For i = LBound(arrMarks) To UBound(arrMarks)
Debug.Print i, arrMarks(i)
Next i

End Sub

The functions LBound and UBound are very useful. Using them means our loops will
work correctly with any array length. The real bene�t is that if the length of the array
changes we do not have to change the code for printing the values. A loop will work for
an array of any length as long as you use these functions.

Using the For Each Loop with the VBA Array


You can use the For Each loop with arrays. The important thing to keep in mind is that it
is Read-Only. This means that you cannot change the value in the array.

In the following code the value of mark changes but it does not change the value in the
array.

For Each mark In arrMarks


' Will not change the array value
mark = 5 * Rnd
Next mark

The For Each is loop is �ne to use for reading an array. It is neater to write especially for
a Two-Dimensional array as we will see.

Dim mark As Variant


For Each mark In arrMarks

16 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Debug.Print mark
Next mark

Using Erase with the VBA Array


The Erase function can be used on arrays but performs di�erently depending on the
array type.

For a static Array the Erase function resets all the values to the default. If the array is
made up of long integers(i.e type Long) then all the values are set to zero. If the array is
of strings then all the strings are set to “” and so on.

For a Dynamic Array the Erase function DeAllocates memory. That is, it deletes the
array. If you want to use it again you must use ReDim to Allocate memory.

Let’s have a look an example for the static array. This example is the same as the
ArrayLoops example in the last section with one di�erence – we use Erase after setting
the values. When the value are printed out they will all be zero:

' https://excelmacromastery.com/
Public Sub EraseStatic()

' Declare array


Dim arrMarks(0 To 3) As Long

' Fill the array with random numbers


Dim i As Long
For i = LBound(arrMarks) To UBound(arrMarks)
arrMarks(i) = 5 * Rnd
Next i

' ALL VALUES SET TO ZERO


Erase arrMarks

' Print out the values - there are all now zero
Debug.Print "Location", "Value"
For i = LBound(arrMarks) To UBound(arrMarks)
Debug.Print i, arrMarks(i)
Next i

17 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

End Sub

We will now try the same example with a dynamic. After we use Erase all the locations in
the array have been deleted. We need to use ReDim if we wish to use the array again.

If we try to access members of this array we will get a “Subscript out of Range” error:

' https://excelmacromastery.com/
Public Sub EraseDynamic()

' Declare array


Dim arrMarks() As Long
ReDim arrMarks(0 To 3)

' Fill the array with random numbers


Dim i As Long
For i = LBound(arrMarks) To UBound(arrMarks)
arrMarks(i) = 5 * Rnd
Next i

' arrMarks is now deallocated. No locations exist.


Erase arrMarks

End Sub

Increasing the length of the VBA Array


If we use ReDim on an existing array, then the array and its contents will be deleted.

In the following example, the second ReDim statement will create a completely new
array. The original array and its contents will be deleted.

' https://excelmacromastery.com/
Sub UsingRedim()

Dim arr() As String

' Set array to be slots 0 to 2

18 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

ReDim arr(0 To 2)
arr(0) = "Apple"

' Array with apple is now deleted


ReDim arr(0 To 3)

End Sub

If we want to extend the length of an array without losing the contents, we can use the
Preserve keyword.

When we use Redim Preserve the new array must start at the same starting dimension
e.g.

We cannot Preserve from (0 to 2) to (1 to 3) or to (2 to 10) as they are di�erent starting


dimensions.

In the following code we create an array using ReDim and then �ll the array with types
of fruit.

We then use Preserve to extend the length of the array so we don’t lose the original
contents:

' https://excelmacromastery.com/
Sub UsingRedimPreserve()

Dim arr() As String

' Set array to be slots 0 to 1


ReDim arr(0 To 2)
arr(0) = "Apple"
arr(1) = "Orange"
arr(2) = "Pear"

' Reset the length and keep original contents


ReDim Preserve arr(0 To 5)

End Sub

19 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

You can see from the screenshots below, that the original contents of the array have
been “Preserved”.

Before ReDim Preserve

After ReDim Preserve

Word of Caution: In most cases, you shouldn’t need to resize an array like we have
done in this section. If you are resizing an array multiple times then you may want to
consider using a Collection.

Using Preserve with Two-Dimensional Arrays


Preserve only works with the upper bound of an array.

For example, if you have a two-dimensional array you can only preserve the second
dimension as this example shows:

' https://excelmacromastery.com/
Sub Preserve2D()

Dim arr() As Long

20 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Set the starting length


ReDim arr(1 To 2, 1 To 5)

' Change the length of the upper dimension


ReDim Preserve arr(1 To 2, 1 To 10)

End Sub

If we try to use Preserve on a lower bound we will get the “Subscript out of range” error.

In the following code we use Preserve on the �rst dimension. Running this code will give
the “Subscript out of range” error:

' https://excelmacromastery.com/
Sub Preserve2DError()

Dim arr() As Long

' Set the starting length


ReDim arr(1 To 2, 1 To 5)

' "Subscript out of Range" error


ReDim Preserve arr(1 To 5, 1 To 5)

End Sub

When we read from a range to an array, it automatically creates a two-dimensional


array, even if we have only one column.

The same Preserve rules apply. We can only use Preserve on the upper bound as this
example shows:

' https://excelmacromastery.com/
Sub Preserve2DRange()

Dim arr As Variant

' Assign a range to an array

21 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

arr = Sheet1.Range("A1:A5").Value

' Preserve will work on the upper bound only


ReDim Preserve arr(1 To 5, 1 To 7)

End Sub

Sorting the VBA Array


There is no function in VBA for sorting an array. We can sort the worksheet cells but this
could be slow if there is a lot of data.

The QuickSort function below can be used to sort an array.

' https://excelmacromastery.com/
Sub QuickSort(arr As Variant, first As Long, last As Long)

Dim vCentreVal As Variant, vTemp As Variant

Dim lTempLow As Long


Dim lTempHi As Long
lTempLow = first
lTempHi = last

vCentreVal = arr((first + last) \ 2)


Do While lTempLow <= lTempHi

Do While arr(lTempLow) < vCentreVal And lTempLow < last


lTempLow = lTempLow + 1
Loop

Do While vCentreVal < arr(lTempHi) And lTempHi > first


lTempHi = lTempHi - 1
Loop

If lTempLow <= lTempHi Then

' Swap values

22 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

vTemp = arr(lTempLow)

arr(lTempLow) = arr(lTempHi)
arr(lTempHi) = vTemp

' Move to next positions


lTempLow = lTempLow + 1
lTempHi = lTempHi - 1

End If

Loop

If first < lTempHi Then QuickSort arr, first, lTempHi


If lTempLow < last Then QuickSort arr, lTempLow, last

End Sub

You can use this function like this:

' https://excelmacromastery.com/
Sub TestSort()

' Create temp array


Dim arr() As Variant
arr = Array("Banana", "Melon", "Peach", "Plum", "Apple")

' Sort array


QuickSort arr, LBound(arr), UBound(arr)

' Print arr to Immediate Window(Ctrl + G)


Dim i As Long
For i = LBound(arr) To UBound(arr)
Debug.Print arr(i)
Next i

End Sub

23 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Passing the VBA Array to a Sub


Sometimes you will need to pass an array to a procedure. You declare the parameter
using parenthesis similar to how you declare a dynamic array.

Passing to the procedure using ByRef means you are passing a reference of the array.
So if you change the array in the procedure it will be changed when you return.

Note: When you use an array as a parameter it cannot use ByVal, it must use ByRef. You
can pass the array using ByVal making the parameter a variant.

' https://excelmacromastery.com/
' Passes array to a Function
Public Sub PassToProc()
Dim arr(0 To 5) As String
' Pass the array to function
UseArray arr
End Sub

Public Function UseArray(ByRef arr() As String)


' Use array
Debug.Print UBound(arr)
End Function

Returning the VBA Array from a Function


It is important to keep the following in mind. If you want to change an existing array in a
procedure then you should pass it as a parameter using ByRef(see last section). You do
not need to return the array from the procedure.

The main reason for returning an array is when you use the procedure to create a new
one. In this case you assign the return array to an array in the caller. This array cannot
be already allocated. In other words you must use a dynamic array that has not been
allocated.

The following examples show this

' https://excelmacromastery.com/
Public Sub TestArray()

24 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Declare dynamic array - not allocated


Dim arr() As String
' Return new array
arr = GetArray

End Sub

Public Function GetArray() As String()

' Create and allocate new array


Dim arr(0 To 5) As String
' Return array
GetArray = arr

End Function

Using a Two-Dimensional VBA Array


The arrays we have been looking at so far have been one-dimensional arrays. This
means the arrays are one list of items.

A two-dimensional array is essentially a list of lists. If you think of a single spreadsheet


row as a single dimension then more than one column is two dimensional. In fact a
spreadsheet is the equivalent of a two-dimensional array. It has two dimensions – rows
and columns.

One small thing to note is that Excel treats a one-dimensional array as a row if you write
it to a spreadsheet. In other words, the array arr(1 to 5) is equivalent to arr(1 to 1, 1 to 5)
when writing values to the spreadsheet.

The following image shows two groups of data. The �rst is a one-dimensional layout and
the second is two dimensional.

25 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

To access an item in the �rst set of data(1 dimensional) all you need to do is give the row
e.g. 1,2, 3 or 4.

For the second set of data (two-dimensional), you need to give the row AND the column.
So you can think of 1 dimensional being multiple columns and one row and two-
dimensional as being multiple rows and multiple columns.

Note: It is possible to have more than two dimensions in an array. It is rarely required. If
you are solving a problem using a 3+ dimensional array then there probably is a better
way to do it.

You declare a two-dimensional array as follows:

Dim ArrayMarks(0 To 2,0 To 3) As Long

The following example creates a random value for each item in the array and the prints
the values to the Immediate Window:

' https://excelmacromastery.com/
Public Sub TwoDimArray()

' Declare a two dimensional array


Dim arrMarks(0 To 3, 0 To 2) As String

' Fill the array with text made up of i and j values


Dim i As Long, j As Long
For i = LBound(arrMarks) To UBound(arrMarks)
For j = LBound(arrMarks, 2) To UBound(arrMarks, 2)
arrMarks(i, j) = CStr(i) & ":" & CStr(j)

26 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Next j
Next i

' Print the values in the array to the Immediate Window


Debug.Print "i", "j", "Value"
For i = LBound(arrMarks) To UBound(arrMarks)
For j = LBound(arrMarks, 2) To UBound(arrMarks, 2)
Debug.Print i, j, arrMarks(i, j)
Next j
Next i

End Sub

You can see that we use a second For loop inside the �rst loop to access all the items.

The output of the example looks like this:

How this Macro works is as follows:

• Enters the i loop


• i is set to 0
• Entersj loop
• j is set to 0
• j is set to 1
• j is set to 2
• Exit j loop
• i is set to 1

27 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

• j is set to 0
• j is set to 1
• j is set to 2
• And so on until i=3 and j=2

You may notice that LBound and UBound have a second argument with the value 2.
This speci�es that it is the upper or lower bound of the second dimension. That is the
start and end location for j. The default value 1 which is why we do not need to specify it
for the i loop.

Using the For Each Loop


Using a For Each is neater to use when reading from an array.

Let’s take the code from above that writes out the two-dimensional array

' Using For loop needs two loops


Debug.Print "i", "j", "Value"
For i = LBound(arrMarks) To UBound(arrMarks)
For j = LBound(arrMarks, 2) To UBound(arrMarks, 2)
Debug.Print i, j, arrMarks(i, j)
Next j
Next i

Now let’s rewrite it using a For each loop. You can see we only need one loop and so it is
much easier to write:

' Using For Each requires only one loop


Debug.Print "Value"
Dim mark As Variant
For Each mark In arrMarks
Debug.Print mark
Next mark

Using the For Each loop gives us the array in one order only – from LBound to UBound.
Most of the time this is all you need.

28 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Reading from a Range to the VBA Array


If you have read my previous post on Cells and Ranges then you will know that VBA has
an extremely e�cient way of reading from a Range of Cells to an Array and vice versa

' https://excelmacromastery.com/
Public Sub ReadToArray()

' Declare dynamic array


Dim StudentMarks As Variant

' Read values into array from first row


StudentMarks = Range("A1:Z1").Value

' Write the values back to the third row


Range("A3:Z3").Value = StudentMarks

End Sub

The dynamic array created in this example will be a two dimensional array. As you can
see we can read from an entire range of cells to an array in just one line.

The next example will read the sample student data below from C3:E6 of Sheet1 and
print them to the Immediate Window:

' https://excelmacromastery.com/
Public Sub ReadAndDisplay()

' Get Range


Dim rg As Range
Set rg = ThisWorkbook.Worksheets("Sheet1").Range("C3:E6")

' Create dynamic array


Dim StudentMarks As Variant

' Read values into array from sheet1


StudentMarks = rg.Value

29 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' Print the array values


Debug.Print "i", "j", "Value"
Dim i As Long, j As Long
For i = LBound(StudentMarks) To UBound(StudentMarks)
For j = LBound(StudentMarks, 2) To UBound(StudentMarks, 2)
Debug.Print i, j, StudentMarks(i, j)
Next j
Next i

End Sub

Sample Student data

Output from sample data

As you can see the �rst dimension(accessed using i) of the array is a row and the second
is a column. To demonstrate this take a look at the value 44 in E4 of the sample data.

30 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

This value is in row 2 column 3 of our data. You can see that 44 is stored in the array at
StudentMarks(2,3).

You can see more about using arrays with ranges in this YouTube video

How To Make Your Macros Run at Super Speed


If your macros are running very slow then you may �nd this section very helpful.
Especially if you are dealing with large amounts of data. The following is a very well-kept
secret in VBA

Updating values in arrays is exponentially faster than updating values in cells.

In the last section, you saw how we can easily read from a group of cells to an array and
vice versa. If we are updating a lot of values then we can do the following:

1. Copy the data from the cells to an array.


2. Change the data in the array.
3. Copy the updated data from the array back to the cells.

For example, the following code would be much faster than the code below it:

31 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

' https://excelmacromastery.com/
Public Sub ReadToArray()

' Read values into array from first row


Dim StudentMarks As Variant
StudentMarks = Range("A1:Z20000").Value

Dim i As Long
For i = LBound(StudentMarks) To UBound(StudentMarks)
' Update marks here
StudentMarks(i, 1) = StudentMarks(i, 1) * 2
'...
Next i

' Write the new values back to the worksheet


Range("A1:Z20000").Value = StudentMarks

End Sub

' https://excelmacromastery.com/
Sub UsingCellsToUpdate()

Dim c As Variant
For Each c In Range("A1:Z20000")
c.Value = ' Update values here
Next c

End Sub

Assigning from one set of cells to another is also much faster than using Copy and Paste:

' Assigning - this is faster


Range("A1:A10").Value = Range("B1:B10").Value

' Copy Paste - this is slower


Range("B1:B1").Copy Destination:=Range("A1:A10")

32 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

The following comments are from two readers who used arrays to speed up their
macros

“A couple of my projects have gone from almost impossible and long to run into almost too
easy and a reduction in time to run from 10:1.” – Dane

“One report I did took nearly 3 hours to run when accessing the cells directly — 5 minutes
with arrays” – Jim

You can see more about the speed of Arrays compared to other methods in this
YouTube video.

To see a comparison between Find, Match and Arrays it is worth checking out this post
by Charles Williams.

Conclusion
The following is a summary of the main points of this post

33 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

1. Arrays are an e�cient way of storing a list of items of the same type.
2. You can access an array item directly using the number of the location which is known
as the subscript or index.
3. The common error “Subscript out of Range” is caused by accessing a location that
does not exist.
4. There are two types of arrays: Static and Dynamic.
5. Static is used when the length of the array is always the same.
6. Dynamic arrays allow you to determine the length of an array at run time.
7. LBound and UBound provide a safe way of �nd the smallest and largest subscripts of
the array.
8. The basic array is one dimensional. You can also have multidimensional arrays.
9. You can only pass an array to a procedure using ByRef. You do this like this: ByRef
arr() as long.
10. You can return an array from a function but the array, it is assigned to, must not be
currently allocated.
11. A worksheet with its rows and columns is essentially a two-dimensional array.
12. You can read directly from a worksheet range into a two-dimensional array in just
one line of code.
13. You can also write from a two-dimensional array to a range in just one line of code.

What’s Next?
Free VBA Tutorial If you are new to VBA or you want to sharpen your existing VBA skills
then why not try The Ultimate VBA Tutorial.

Related Training: Get full access to the Excel VBA training webinars.

(NOTE: Planning to build or manage a VBA Application? Learn how to build 10 Excel VBA
applications from scratch.)

312 Comments
← Older Comments
James on June 17, 2020 at 2:49 pm

34 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Hello Paul,
I’m reading through your articles and I have one concern:
what’s the best solution:
1. array of UDTs,
2. colection of UDTs,
3. dictionary of UDTs,
4. collection of classes
5. dictionary of classes?
Let’s assume it is the big number of personal data with strings, numbers
and dates.
Thanks in advance.

Reply

Jothiboss on July 19, 2020 at 8:04 pm


Hi Paul,

Hope you’re good!

I could see many Custom Toolbars with User de�ned functions in all of
your videos.
Can you please help to understand, how it was created..

* Eagerly waiting for a positive response


Regards,

Jothiboss S

Reply

Richard Greenwood on July 31, 2020 at 3:42 pm


hi paul
In your arrays tutorial under the section;
How To Make Your Macros Run at Super Speed,
You copy data from a sheet range A1 to Z20000 to the student marks
array. You then double the values in the �rst dimension and then write
the array back to the original range again.
Am I right in thinking that the values that have been doubled are in the

35 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

�rst dimension which is the rows A1 to A20000.


Your tutorial by the way is very helpful and has helped me understand
arrays which has been useful in my work so thanks very much.

Reply

Paul Kelly on August 3, 2020 at 10:00 am


Hi Richard,

It will update column A. StudentMarks(i, 1) is column A,


StudentMarks(i, 2) is column B as so on.

-Paul

Reply

Richard HArkins on August 4, 2020 at 6:06 pm


Paul:

I have an Excel program that is calling a Word doc. I want


the word doc to be “on top” when it opens. However, it
isn’t and I am not �nding any code that handles that
matter. Suggestions?

Best

Dick Harkins
Scottsdale Arizona
dharkins@staircasered.com

Reply

Charles Rogers on November 21, 2020 at 2:59 am


Paul,

This Array information is great, question is I have a huge range of


information(ie rows(8:450) & columns(A:AM) that I need to separated out
by a speci�c column(M) value. Need I have written a simple copy paste

36 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

routine and it works, but takes a long long time to perform. Am


extremely interested in knowing if this Array method might be able to
speed the system up.

Reply

Paul Kelly on December 7, 2020 at 2:29 am


Hi Charles,

Try it out on a small sample and compare the time. This video
may help.

Reply

Graeme on January 28, 2021 at 9:06 am


What i have discovered is that as well as copy values using your super
fast method, is that you can say:

DestinationRange.Formula = SourceRange.Formula
DestinationRange.Style = SourceRange.Style

Which is pretty cool.

Reply

Rien on March 15, 2021 at 9:13 pm


Hi Paul,
I have a question about your “Range to Array” method
Dim arr As Variant
arr = Range(“A1:D2”)
followed by your method of walking through the 2-Dimensional array
For i = lbound(arr,1)… etc.

37 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

In stead of �xed, I need the range to be dynamic, so


Dim rng as Range
Set rng = Range(“A1:D2”)
arr = rng

But since the range is dynamic, it can happen that sometimes it contains
only one cell, eg Range(“A1”). Then it will not return a 2-dimensional
array, but a single String.
The consequence is that the for-loop can not be used, since the variant
arr is not an array.

How can I force the result of arr = rng always to be a 2-dimensional


array?

Maybe you can add this to your great guide, to make it even more
complete.
THANKS in advance,
Rien, Netherlands

Reply

Paul Kelly on March 21, 2021 at 4:17 am


Hi Rien,

You can do something like this:

If Not IsArray(arr) Then


arr = Range(“A1:D2”).Value
ReDim Preserve arr(1 To 1, 1 To 1)
End If

Reply

Lorn on April 17, 2021 at 11:16 am


The only thing missing is how to sort multi-dimensional arrays

Reply

38 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Deon on May 18, 2021 at 1:54 pm


Hi Paul.
Thanks for the useful posts and videos.
I have a set of data that looks like this: 48 rows, 3 columns. Columns 2
and 3 contain multiple comma delimited values, but of unknown
quantities (anything between 0 and an upper limit of 100 comma
delimited values per cell should su�ce).
My function needs to loop through the rows, then for each row perform
a loop of LIKE operations for each comma delimited value in column 2,
and (if the like is true) within that loop a NOT LIKE operation for each
comma delimited value in column 3. Hope that makes sense.
My question is: what data structure would you use for the data? A 3D
array with lots of empty 3rd dimensions for column 2 and 3? Or can
collections or a dictionary serve me better here? I have little experience
of those last structures but I guess choosing the right one is the starting
point.
Thanks

Reply

Karsten Liebmann on December 11, 2021 at 7:40 pm


Hi Paul,

thanks for the comprehensive description.

Questions I am puzzled by – can you help?

1. why does this not work (the values in the range are 0 to 10):
Dim Numbers() As Integer
Numbers = Range(“A1:L12”).Value
2. why does this not work (the row/column sizes are identical):
Dim Numbers(0 to 11,0 to 11) As Variant
Numbers = Range(“A1:L12”).Value

Reply

Peter Denney on May 31, 2022 at 8:09 am


additional way to create array’s you may want to add

39 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Sub pike_test()
Dim dbArray() As Variant

‘1D array string conversion


dbArray = [{1,2,3}]
Range(“A1”).Resize(1, UBound(dbArray)).Value = dbArray

dbArray = [{“apple”,”bannana”,”mango”}]
Range(“H1”).Resize(1, UBound(dbArray)).Value = dbArray

‘2D array string conversion


dbArray = [{1,2;3,4;5,6}]
Range(“A5″).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray

dbArray = [{1,”apple”;3,”bannana”;5,”mango”}]
Range(“H5”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray

dbArray = [{1,2,3;4,5,6;7,8,9}]
Range(“A10”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray

‘2D array string conversion with a string variable


dbArray = Evaluate(“{1,2;3,4;5,6}”) ‘have to be more explicit, the
shorthand won’t work
Range(“E1”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray
y = “{1,2;3,4;5,6}”
dbArray = Evaluate(y) ‘have to be more explicit, the shorthand won’t work
Range(“E5”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray

40 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

‘2D array string conversion with a string variable


‘ dbArray = Evaluate(“1,apple;3,bannana;5,mango}”) ‘have to be more
explicit, the shorthand won’t work
‘ Range(“E10”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray
‘ y = “{1,apple;3,bannana;5,mango}”
‘ dbArray = Evaluate(y) ‘have to be more explicit, the shorthand won’t
work
‘ Range(“E15”).Resize(UBound(dbArray, 1), UBound(dbArray, 2)).Value =
dbArray

End Sub

Reply

Ricardo Hernandez on June 16, 2022 at 10:51 pm


Hello, i have a problem, when i assign a range to an array, the values in
cells are di�erent that values in array. the cells store �lenames, some
have accented chars á, what can i do in order to store the true
�lenames?

Reply

Armaan Khan on June 23, 2022 at 9:09 pm


Hi Paul,

Your explenations are the best!

Is there a way to write a speci�c sub section of a 2D arry to a specifc


range?

arr = ( 1 to 100, 1 to 3)

arr = ws1.range(“A2:C100”)

ws2.range(“A5:C50”) = arr(5 to 50, 1 to 3)

Its this last line that I can’t �nd a solution to. Array to Range seems a lot
faster then going thru each element of the array and writing to a cell.

41 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Thanks!

Reply

Keith Me�erd on December 1, 2022 at 3:37 pm


Hi, Armann – this may be way late, but I would create a second
array to contain the portion of the main array you want, then
assign that smaller temporary array to the range.

Reply

Philippe Wuest on July 7, 2022 at 7:13 am


Hi Paul,

Thanks for your very helpful explanations on VBA arrays! They helped
me solve a problem I had been struggling with for a long time.
What I found confusing however, is the illustration of the di�erence
between 1D and 2D arrays in the “Using a Two-Dimensional VBA Array”
section. In the illustration the 1D array stretches over as many columns
as the 2D array, which is in contradiction to your explanation or at least
rather counter-intuitive.
Or maybe, as a VBA newbie, I got it all wrong …?

Reply

Paul Kelly on July 13, 2022 at 9:10 am


That is correct Philippe. A 1D array is simply a 2D array with one
row.

Reply

John Noriega on July 13, 2022 at 6:14 pm


Thank you for that reply to Phillipe. I was going nuts trying to write a 1D
array to a column of cells. It would only put the �rst value in the array in

42 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

every cell. I �nally scrolled down and read the comments here.
“A 1D array is simply a 2D array with one row.” and the light bulb goes
on!
It’s treating rows in the range as rows in the array, so for each new row
in the range it starts reading the array again. I reset the array from
arr(24) to arr(24,0) and everything works.
Perfect timing, too. I just ran into this yesterday.

Reply

Paul Kelly on July 14, 2022 at 9:01 am


Glad that helped John. I only replied to it yesterday.

Reply

Thomas on September 22, 2022 at 9:07 pm


should this be split into 4 elements? –not 3

The Split function is used to split a string into an array based on a


delimiter. A delimiter is a character such as a comma or space that
separates the items.

The following code will split the string into an array of three elements:

Dim s As String
s = “Red,Yellow,Green,Blue”

Dim arr() As String


arr = Split(s, “,”)

Reply

Paul Kelly on September 26, 2022 at 8:34 pm


Yes, It was a typo that I just updated.

Reply

43 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

Joe on October 31, 2022 at 5:07 pm


Hi Paul, What is happening when one does not use ReDim to set the
length of a dynamic array? For example, in the below simple example, is
ReDim implicitly called in the last line [e.g. arr = Split(s, “,”)]?

Dim s As String
s = “Red,Yellow,Green,Blue”

Dim arr() As String


arr = Split(s, “,”)

Similarly for the case of the variant array, is ReDim implicitly called?

Dim arr1 As Variant


arr1 = Array(“Orange”, “Peach”,”Pear”)

Dim arr2 As Variant


arr2 = Array(5, 6, 7, 8, 12)

In summary, my question is, when is ReDim required to set the length of


a dynamic array and when is ReDim not required to set the length of a
dynamic array ?

Thank you.

Reply

Paul Kelly on November 8, 2022 at 12:34 pm


When you use a function like split or array it automatically
creates the array for you so you don’t need to use Redim.
When you are going to �ll the array then you need to set the size
using Dim or Redim. Redim allows using variables to set the size
which makes it more �exible.

Reply

Andy on November 29, 2022 at 2:24 pm


Hi Paul, Love your content and videos. I have a data set which is 7000
columns by 3000 rows. As an example I want to �nd the average of a

44 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

subset of column A where values in column D meet are greater than a


certain value and values in column Z are less than a certain value. Once I
get the result I want to put this in a di�erent worksheet. I am trying to
process lots of values. Is this a job for arrays? Do I solve this thru a loop
or what is the best way to write the averageifs function.
Thank you so much!

Reply

cunky on July 13, 2023 at 9:31 am


hi paul, could you suggest me how to create (coding) for this :
colomn F = colomn E + 1 without function looping for i=1 to n. because if
i use looping for xxx.xxx rows it needs time to proceed.?

Reply

蘇孟緯 on November 24, 2023 at 3:23 am


Thank You

Reply

JP on February 20, 2024 at 1:05 pm


Great explanation.

But how do you deal with dates and formats.

I do have cells with dates in YYYY-MM-DD format


And when i read the range to an array and write it back, the format is
messed up.
2023-02-12 might become 2023-12-02
Besides the �le is used in di�erent countries, so the date might be
changed accordign to regional settings.

45 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

I read that it is better to use myarr = rng.Value2 instead of myarr =


rng.Value
with Value2 date becomes a double.
with Value it is #12/02/2024# Date – French

But then, how do you compare dates or do calculations on dates ?

Thanks

Reply

Phil Simpson on April 2, 2024 at 1:43 pm


Hi Paul, in your recent webinar on Arrays 27/03/2024 you sorted the
array using WorkSheetFunction.Sort and commented that in the past we
would have needed to write additional code to perform the sort. I
therefore wondered whether the QuickSort code in this guide is now
obsolete, or is it actually quicker?

Reply

Paul Kelly on April 7, 2024 at 9:45 am


Hi Phil,

I haven’t done a speed comparison recently so I’m not sure.


I would say if you have o�ce 365 or greater then the sort
function code in this article is unnecessary. But if you have an
older version of Excel that doesn’t have access to the new Excel
Sort function then you would still need it.

-Paul

Reply

Phil Simpson on April 9, 2024 at 11:54 am


Hi Paul,

Thank you. I’ve struggled implementing ‘MicroTimer’ code

46 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

and haven’t done a comparison either, so I’m happy to


follow your expert advice.

On a similar theme I was curious about the


WorksheetFunction.SortBy to sort on multiple columns of
an array. Although, I found it quicker sorting on two
columns (using crude ‘TImer’ code) I concluded it wasn’t
worth the e�ort to create additional arrays for each of
the sort columns.
I found in practical terms, for the size of my dataset,
sorting the data twice (last sort column �rst) using the
WorksheetFunction.Sort to be almost as quick.

-Phil

Reply

Paul Kelly on April 10, 2024 at 8:09 am


Thanks for the feedback Phil.

Reply

← Older Comments

You are not logged in

47 sur 48 22/05/2024, 11:57 PM


Firefox https://excelmacromastery.com/excel-vba-array/

You are not currently logged in.


Username or Email Address:
museographe@gmail.com
Password:


●●●●●●●●●●●●●

Remember Me

» Register
» Lost your Password?

5 Things I wish I knew When I started using Excel VBA

   
Designed by Elegant Themes | Powered by WordPress

48 sur 48 22/05/2024, 11:57 PM

You might also like