In September, 2018 we announced that Dynamic Array support would be coming to Excel. This allows formulas to spill across multiple cells if the formula returns multi-cell ranges or arrays. This new dynamic array behavior can also affect earlier functions that have the ability to return a multi-cell range or array.
Below is a list of functions that could return multi-cell ranges or arrays in what we refer to as pre-dynamic array Excel. If these functions were used in workbooks predating dynamic arrays, and returned a multi-cell range or array to the grid (or a function that did not expect them), then silent implicit intersection would have occurred. Dynamic array Excel indicates where implicit intersection could occur using the @ operator, and as a result, these functions may be prepended with an @ if they were originally authored in a pre-dynamic array version of Excel. Additionally, if authored on dynamic array Excel, these functions may appear as legacy array formulas in pre-dynamic array Excel unless prepended with @.
-
CELL
-
COLUMN
-
FILTERXML
-
FORMULATEXT
-
FREQUENCY
-
GROWTH
-
HYPERLINK
-
INDEX
-
INDIRECT
-
ISFORMULA
-
LINEST
-
LOGEST
-
MINVERSE
-
MMULT
-
MODE.MULT
-
MUNIT
-
OFFSET
-
ROW
-
TRANSPOSE
-
TREND
-
All User Defined Functions
Need more help?
You can always ask an expert in the Excel Tech Community or get support in the Answers community.
Need more help?
Want more options?
Explore subscription benefits, browse training courses, learn how to secure your device, and more.
Communities help you ask and answer questions, give feedback, and hear from experts with rich knowledge.
All,
I would like to write a function to return an array of integers so I can index them, but I am not aware of the syntax for VBA. Here is the pseudo code:
function getStats() as integer
dim returnVal(4) as integer
returnVal(0)=c2percent14
returnVal(1)=c3percent14
returnVal(2)=c4percent14
returnVal(3)=c5percent14
getStats=returnVal
end function
msgbox getStats(3)
where these values are all integers, or should be, and then I can index the return array for the stat that I want. Thanks.
-Rik
moffeltje
4,4644 gold badges32 silver badges56 bronze badges
asked Jul 22, 2015 at 13:39
Give the function the type as an array:
function getStats() as Integer()
dim returnVal(0 to 3) as integer
returnVal(0) = c2percent14
returnVal(1) = c3percent14
returnVal(2) = c4percent14
returnVal(3) = c5percent14
getStats = returnVal
end function
Sub mysub()
Dim myArray() As Integer
myArray = getStats()
msgbox myArray(3)
end sub
GSerg
75.3k17 gold badges160 silver badges340 bronze badges
answered Jul 22, 2015 at 13:50
moffeltjemoffeltje
4,4644 gold badges32 silver badges56 bronze badges
2
Function getStats() As Variant
getstats = Array(c2percent14, c3percent14, c4percent14, c5percent14)
End Function
Sub mysub()
Dim myArray() As Variant
myArray = getStats()
msgbox myArray(3)
End Sub
getStats
is now an Array of type ´Variant´. The drawback of this method is that you effectively have no static typing anymore, since Variant could be anything.
ascripter
5,47512 gold badges49 silver badges67 bronze badges
answered Jul 22, 2015 at 13:47
TimTim
2,6333 gold badges25 silver badges47 bronze badges
1
I’m going to add an answer here because I’m happy to say, after hours of frustration and bad information, I finally know how to return arrays! Here is how you return an array from a function:
Sub mysub()
Dim i As Integer, s As String
Dim myArray() As Integer 'if you declare a size here you will get "Compile error, can't assign to array"
myArray = getStats()
s = "Array values returned:" & vbCrLf
For i = 0 To UBound(myArray)
s = (s & myArray(i) & " ")
Next
MsgBox s
End Sub
Function getStats() As Integer() 'The return type must be EXACTLY the same as the type declared in the calling sub.
Dim returnVal(2) As Integer 'if you DON'T declare a size here you will get "Run-time error '9': Subscript out of range"
returnVal(0) = 0
returnVal(1) = 1
returnVal(2) = 2
'returnVal(3) = 3 This will throw an error. Remember that an array declared (2) will hold 3 values, 0-2.
getStats = returnVal
End Function
Output:
The comments I included here are very important. Although VBA is usually pretty lax, this particular thing is very picky. These are required for your function, assignment, and return to work:
- The array declared in the calling sub has to be of undeclared length.
- The function that returns an array has to be of EXACTLY same type. Even if you declare the array in the sub as a Variant and the function returns an Integer array that will not work either.
- You have to use a temporary array in the function. You cannot assign values to the function name (getStats) like you normally would in a function; you can only assign the temporary array to the function name once you have assigned all the values to the temp array. Any attempt to ReDim getStats as an array will also throw an error.
- The temp array has to be declared with length. In VBA you cannot assign values to an array at an index until you declare the length.
answered Apr 19, 2020 at 5:25
5
Return to VBA Code Examples
This article will demonstrate how to return an Array using a VBA Function.
VBA Function Return Array
When using functions to return arrays, I strongly recommend declaring arrays with type variant:
Function ReturnArray() As Variant
End Function
Variant Arrays are easier to work with. Array size becomes less of a concern.
Function Return Array Examples
Here is an example of a function that returns an array:
Function ReturnArray() As Variant
Dim tempArr As Variant
'Create New Temp Array
ReDim tempArr(1 To 3, 1 To 2)
'Assign Array Values
tempArr(1, 1) = "Steve"
tempArr(1, 2) = "Johnson"
tempArr(2, 1) = "Ryan"
tempArr(2, 2) = "Johnson"
tempArr(3, 1) = "Andrew"
tempArr(3, 2) = "Scott"
'Output Array
ReturnArray = tempArr
End Function
Sub TestTransposeArray()
Dim outputArr As Variant
'Call Return Function
outputArr = ReturnArray()
'Test Output
MsgBox outputArr(2, 1)
End Sub
Notice we declared the Arrays with data type = variant to avoid size issues.
This example takes an array as an input, transposes the array, and outputs the new transposed array:
Function TransposeArray(MyArray As Variant) As Variant
Dim x As Long, y As Long
Dim maxX As Long, minX As Long
Dim maxY As Long, minY As Long
Dim tempArr As Variant
'Get Upper and Lower Bounds
maxX = UBound(MyArray, 1)
minX = LBound(MyArray, 1)
maxY = UBound(MyArray, 2)
minY = LBound(MyArray, 2)
'Create New Temp Array
ReDim tempArr(minX To maxX, minY To maxX)
'Transpose the Array
For x = minX To maxX
For y = minY To maxY
tempArr(y, x) = MyArray(x, y)
Next y
Next x
'Output Array
TransposeArray = tempArr
End Function
Sub TestTransposeArray()
Dim testArr(1 To 3, 1 To 2) As Variant
Dim outputArr As Variant
'Assign Array Values
testArr(1, 1) = "Steve"
testArr(1, 2) = "Johnson"
testArr(2, 1) = "Ryan"
testArr(2, 2) = "Johnson"
testArr(3, 1) = "Andrew"
testArr(3, 2) = "Scott"
'Call Transpose Function
outputArr = TransposeArray(testArr)
'Test Output
MsgBox outputArr(2, 1)
End Sub
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More!
Today I’m going to show you how to return an array from a VBA function. VBA functions can return arrays of any data type. But sometimes we need to return arrays with elements of different data types. Luckily we can do it using the variant data type. I will show how to return an array of type variant in an example. Let’s start with a simple example. Assume we want to create a VBA function which returns 3 random numbers between 1 and 100. The VBA function can return these 3 numbers as an array. We can use the inbuilt function called Rnd to generate a random number. Then we can do some additional calculations and use the VBA Int function to get a number between 1 and 100. Here is how you can do it.
Function ThreeRandomNumbers() As Integer()
Dim ResultArr(2) As Integer
ResultArr(0) = Int(Rnd * 100) + 1
ResultArr(1) = Int(Rnd * 100) + 1
ResultArr(2) = Int(Rnd * 100) + 1
ThreeRandomNumbers = ResultArr
End Function
Rnd function return values similar to this.
0.8626193
0.7904852
0.3735362
So I multiplied those numbers by 100.
86.26193
79.04852
37.35362
And the VBA Int function returns the integer part of the number. So finally we get random numbers like below.
86
79
37
Rnd function returns values equal or greater than 0 and less than 1. Then Int(Rnd * 100) will output numbers from 0 to 99. Therefore we have to add 1 to get a random number between 1 and 100.
Int(Rnd * 100) + 1 => Generates integer values between 1 and 100
Now we have a VBA function which can return an array. Let’s see how we can call this function within a subroutine. Data type of the array returned by our function is integer. So we need an array of the type integer inside our subroutine. Then we can assign the function’s return value to that array.
Sub Test1()
Dim RandomNumbers() As Integer
RandomNumbers = ThreeRandomNumbers()
End Sub
Add a breakpoint at End Sub and run the subroutine. Then you will see the result in the Locals window like this.
Also you can print these values to an Excel sheet as well. If the name of the worksheet is “Sheet1” then you can write the array to the worksheet as follows.
Sub Test2()
Dim WS As Worksheet
Dim RandomNumbers() As Integer
Dim i As Integer
Set WS = Worksheets(«Sheet1»)
RandomNumbers = ThreeRandomNumbers()
For i = 0 To 2
WS.Range(«A1»).Offset(i, 0).Value = RandomNumbers(i)
Next i
End Sub
Here is the result of the Test2 subroutine.
Next let’s look at another example where we need to pass arguments to the VBA function. Assume we need to find 5 powers/exponents of a given number. For an example if the given number is 3 then the VBA function should return 1,3,9,27 and 81 (30,31,32,33,34)
Here we have to pass the given number as an argument to the function. Then the function can return 5 exponents of the number as an array.
Function FiveExponents(GivenNumber As Integer) As Integer()
Dim ResultArr(4) As Integer
ResultArr(0) = GivenNumber ^ 0
ResultArr(1) = GivenNumber ^ 1
ResultArr(2) = GivenNumber ^ 2
ResultArr(3) = GivenNumber ^ 3
ResultArr(4) = GivenNumber ^ 4
FiveExponents = ResultArr
End Function
.
Now we can call this function within a subroutine like this.
Sub Test3()
Dim WS As Worksheet
Dim Exponents() As Integer
Dim i As Integer
Set WS = Worksheets(«Sheet1»)
Exponents = FiveExponents(5)
For i = 0 To 4
WS.Range(«A1»).Offset(i, 0).Value = Exponents(i)
Next i
End Sub
Below is the outcome of the above subroutine.
Above functions output arrays of integer data type. So the returned array consists of only integers. But sometimes we need VBA functions which should return arrays with elements of various data types. They may contain values of data types such as integer, string, boolean etc. Here is an example.
This worksheet contains order information of a shop. Assume we need a VBA function which takes an order id as an argument and then returns all the other information of that order as an array. It is a type of function we need when searching data. So here various columns have various data types. Therefore we need to declare the data type of the return value of the function as the variant.
This is the function developed for the above requirement.
Function GetOrderInformation(OrderId As String) As Variant
Dim WS As Worksheet
Dim WS_LastRow As Long
Dim i As Long
Dim j As Integer
Dim ResultArr(6) As Variant
Set WS = Worksheets(«Order Details»)
WS_LastRow = WS.Cells.Find(«*», [A1], , , xlByRows, xlPrevious).Row
For i = 2 To WS_LastRow
If StrComp(WS.Range(«A» & i).Value, OrderId, vbTextCompare) = 0 Then
For j = 0 To 6
ResultArr(j) = WS.Range(«A» & i).Offset(0, j).Value
Next j
Exit For
End If
Next i
GetOrderInformation = ResultArr
End Function
First we find the last row of the worksheet. Then use For Next Statement to iterate through the rows. Strcomp function is used to find the matching row for the given order id. If a matching row is found then all the information of that row is written to an array.
Here is how you can call the above function inside a subroutine.
Sub Test4()
Dim OrderInfo() As Variant
OrderInfo = GetOrderInformation(«209-2752429-9545»)
End Sub
Add a breakpoint at End Sub and run the macro. Then you can view the OrderInfo array in the Locals window.
Also read
Quickly Write Multidimensional Array to Excel Range
Re-size Dynamic Arrays
Calculate With Arrays
How to use preserve keyword in arrays
Transposing an Array in VBA
Returning Arrays From VBA User Defined Functions
This page describes returning arrays as the result of VBA User Defined Functions.
If you often write your own User Defined Functions (UDFs) in VBA or in a COM or Automation Add-Ins (click
here for information about writing your own functions in VBA; click
here for information about writing COM Add-Ins, or click
here for information about writing Automation Add-Ins), you have likely needed to or
at least found it useful to return an array as the result of your VBA function. This allows the user to array enter
your function (click here for information about array formulas) into a range of cells
on the worksheet to display the contents of the array that is returned by your UDF.
This page looks at a few issue that might arise when you are returning arrays from UDFs.
At its simplest, the size of the returned array can be mandated by the function and require that the user use an array that size
in order to get all the results. The Excel function LINEST function works this way. You must
array-enter that function into a range of cells that is 5 rows tall and 2 columns wide. If you enter it into a larger range,
Excel fills out the unused elements of the range with #N/A errors. If you enter it into a smaller
range, you will not get all the values created by LINEST.
To mandate the size of the returned array, simply declare the array to that size and setting the result of the function to that
array. For example,
Function Test() As Variant Dim V() As Variant Dim N As Long Dim R As Long Dim C As Long ReDim V(1 To 3, 1 To 4) For R = 1 To 3 For C = 1 To 4 N = N + 1 V(R, C) = N Next C Next R Test = V End Function
This function simply returns an array with 3 rows and 4 columns that contains the integers from 1 to 12.
Returning such a fixed-size array can be useful if the number of results does not vary with the number and/or values of the
inputs to the function. However, this is usually not the case.
In the majority of circumstances, if your UDF is going to return an array, that array will vary in size and the size will depend
on any one or more of three things: the size of the range into which the UDF was entered, the number of elements passed into
the function, and, of course, the nature and function of the UDF itself. The Application.Caller object,
when used in a UDF called from a worksheet range, is a Range reference to the range from which your UDF was called.
CAUTION: Application.Caller will be a Range object only when the function in which it appears
was called from a worksheet cell. If the function was called from another VB procedure, Application.Caller
will be an Error-type Variant and most any attempt to use it will result in a Type Mismatch (13) error. If the code containing
Application.Caller was called via the OnAction property of a Shape object on
a worksheet, Application.Caller will be a String containing the name of the sheet. Therefore, if your
function might be called from another VB procedure rather than only from a worksheet cell, you should test
Application.Caller with the IsObject function to ensure that it is indeed
an object before attempting to access any of its properties.
CAUTION: In Excel 2003, a new object, Application.ThisCell, was introduced. It is similar in nature to
Application.Caller, but differs when a UDF is array entered into a range of more than one cell.
Application.Caller will return the a Range reference to the entire range in which the UDF was array-entered.
Application.ThisCell returns a reference to the first (upper left) cell in the range from which the UDF
was called. Frankly, I’m not sure why Application.ThisCell was introduced in the first place.
In the example code on this page, we will not test Application.Caller with IsObject.
For simplicity and brevity, we will assume that the function is being called from a worksheet.
Using Application.Caller, you can determine the number of rows and columns from which the function
was called. For example,
Function Test() Dim CallerRows As Long Dim CallerCols As Long With Application.Caller CallerRows = .Rows.Count CallerCols = .Columns.Count End With Test = CallerRows * CallerCols End Function
In this code, the variables CallerRows and CallerCols get the number of rows
and columns in the range from which the function was called. If you want to return an array the same size as the range from
which the function was called, you can use code like the following:
Function Test() As Variant Dim CallerRows As Long Dim CallerCols As Long Dim CallerAddr As String Dim Result() As Long Dim N As Long Dim RowNdx As Long Dim ColNdx As Long With Application.Caller CallerRows = .Rows.Count CallerCols = .Columns.Count End With ReDim Result(1 To CallerRows, 1 To CallerCols) For RowNdx = 1 To CallerRows For ColNdx = 1 To CallerCols N = N + 1 Result(RowNdx, ColNdx) = N Next ColNdx Next RowNdx Test = Result End Function
This function returns an array with the same dimensions as the range from which the function was called, and simply fills those
elements with the first Rows*Columns integers.
You can, of course, ignore the size of the range from which the function was called and return an array with the dimensions
required by your function’s purpose. In this case, if the function is entered into a range smaller than the result array of
the function, the result array is trunctated on the bottom and on the right to the size of the calling range. If the function
was entered into a range larger than the size of the returned array, Excel fills the unused cells with #N/A
values. This is the normal behavior of Excel’s own array functions. For example, if you array enter
=ROW(A1:A3) into cells B1:B5, the result will be
1 2 3 #N/A #N/A. The ROW(A1:A3) returns an array with only three elements,
so Excel fills in the rest of the calling range with #N/A values.
If your UDF creates a 1-dimensional array as its result, it can orient the array as either a row vector or a column vector so that
is will be properly displayed in the worksheet cells without requiring the user to wrap your UDF result in a TRANSPOSE
function. If the function was called from a row vector of cells (e.g., A1:E1), it does not need to
be transposed. If the function was called from a column vector of cells (e.g., A1:A5), the array needs
to be transposed. The code below looks at Application.Caller.Rows.Count and if this is greater than
1, it tranposes the array before returning it to the caller. Note that this should be done only with single-dimensional
arrays and only when the UDF is being called from a worksheet range. Therefore, you should first test
Application.Caller with IsObject and then test
Application.Caller.Rows.Count and Application.Caller.Columns.Count to test
if it is being called from a row or column vector. For example,
Function Test(NN As Long) Dim Result() As Long Dim N As Long ReDim Result(1 To NN) For N = 1 To NN Result(N) = N Next N If Application.Caller.Rows.Count > 1 Then Test = Application.Transpose(Result) Else Test = Result End If End Function
You can, of course, forego this and return the array as-is and leave it up to the user to use the TRANSPOSE
function to properly orient the array.
This page last updated: 6-Nov-2007