In VBA, calculate an array’s length as UBound(array) - LBound(array) + 1. The expression works for a one-dimensional array with any lower bound; for a multidimensional array, specify which dimension you want to count.
What VBA Means by Array Length
VBA arrays do not have a built-in Length property. To count the elements in an array dimension, find its lower and upper bounds and include both endpoints in the count. For example, an array whose indexes run from 1 through 5 contains five elements, not four: 5 − 1 + 1 = 5.
This distinction matters because array indexes are not always zero-based or one-based. A declared array might use indexes from 0 to 4, 1 to 5, or even 10 to 14. Each has five elements, but the upper bound alone is not necessarily the element count. The formula accounts for both ends of the index range.
Use the same calculation whether the array is fixed-size or dynamic, provided it has been allocated and you are counting one dimension. The function names are built into VBA, so no worksheet function or special reference is needed.
The Basic UBound and LBound Calculation
LBound returns the smallest valid subscript in a dimension, and UBound returns the largest. Both accept an optional dimension number. When the array is one-dimensional, the dimension defaults to 1, so this expression is sufficient:
UBound(values) - LBound(values) + 1
For a concrete example, this procedure creates an array with subscripts 5 through 9. The result is 5 because the indexes are 5, 6, 7, 8, and 9.
Save a copy of the workbook before running a macro. VBA macros cannot be undone with Ctrl+Z, even when a particular example only prints a result in the Immediate window.
Public Sub CountFixedArray()
Dim values(5 To 9) As Long
Dim elementCount As Long
' Count both endpoints of the index range.
elementCount = UBound(values) - LBound(values) + 1
Debug.Print elementCount
End Sub
In the Visual Basic Editor, Debug.Print writes the result to the Immediate window. If that window is not visible, use View > Immediate Window in the editor. The macro does not place the answer in a worksheet cell.
Lower Bounds and Option Base
The lower bound is why UBound(array) is not a general substitute for an element count. If an array starts at 0, its upper bound happens to equal its element count, but that coincidence does not hold for an array starting at 1 or another value. Subtracting LBound makes the calculation reliable across these cases.
In a VBA module, the optional Option Base statement can set the default lower bound used when a declaration omits an explicit lower bound. The default is 0; a module can specify Option Base 1. This setting is local to its module and does not change an array whose bounds are written explicitly, such as Dim values(5 To 9) As Long.
For code that other people may maintain, explicit bounds are often easier to read than relying on a module setting. Regardless of how the array was declared, checking its actual bounds with LBound and UBound avoids assumptions about where indexing begins.
Counting Elements in a Multidimensional Array
A multidimensional array has a separate lower and upper bound for each dimension. Pass the dimension number as the second argument to both functions. For an array declared with three rows and five columns, dimension 1 has three elements and dimension 2 has five.
Public Sub CountArrayDimensions()
Dim grid(1 To 3, 0 To 4) As String
Dim rowCount As Long
Dim columnCount As Long
Dim totalElements As Long
' Dimension 1 is rows; dimension 2 is columns.
rowCount = UBound(grid, 1) - LBound(grid, 1) + 1
columnCount = UBound(grid, 2) - LBound(grid, 2) + 1
totalElements = rowCount * columnCount
Debug.Print rowCount
Debug.Print columnCount
Debug.Print totalElements
End Sub
The output values are 3, 5, and 15. Multiplying the dimension counts gives the number of positions in a rectangular array when you need the total number of elements. It does not tell you how many positions contain nonblank text or nonzero numbers; that is a different question about the values stored in the array.
For arrays with more dimensions, repeat the bounds calculation with the relevant dimension number. To find the total number of positions, multiply the counts for all dimensions. Keep the dimension order straight: in a worksheet range array, the first dimension conventionally represents rows and the second represents columns.
Dynamic Arrays and Unallocated Arrays
A dynamic array is declared with empty parentheses and receives bounds later through ReDim. Once allocated, the standard length formula applies. Before allocation, however, calling LBound or UBound raises an error, so code should not assume that every declared dynamic array is ready to count.
For a known dynamic array, this pattern treats a bounds error as an indication that no usable bounds are available. It clears the error before checking and turns normal error handling back on afterward.
Public Sub CountIfAllocated()
Dim values() As Long
Dim elementCount As Long
' Allocate the array before counting it.
ReDim values(1 To 4)
Err.Clear
On Error Resume Next
elementCount = UBound(values) - LBound(values) + 1
If Err.Number <> 0 Then
elementCount = 0
Err.Clear
End If
On Error GoTo 0
Debug.Print elementCount
End Sub
As written, the array is allocated with four elements, so the result is 4. If the ReDim line is removed, the bounds call fails and the procedure reports 0. Use this kind of error handling narrowly around the bounds operation: On Error Resume Next can conceal unrelated errors if it is left active across more code than necessary.
Arrays Returned from Excel Ranges
Reading a multi-cell range through its Value property commonly produces a two-dimensional Variant array. For example, the range A1:C5 has five rows and three columns, with the resulting array indexed from 1 to 5 in its first dimension and 1 to 3 in its second. The dimensions can be counted rather than assumed:
Public Sub CountRangeValues()
Dim data As Variant
Dim rowCount As Long
Dim columnCount As Long
' Read a multi-cell range into a Variant array.
data = Range(A1:C5).Value
rowCount = UBound(data, 1) - LBound(data, 1) + 1
columnCount = UBound(data, 2) - LBound(data, 2) + 1
Debug.Print rowCount
Debug.Print columnCount
End Sub
In actual VBA, the range address must be a string. The assignment line should therefore be written as data = Range("A1:C5").Value. The counts are 5 rows and 3 columns. This range example is useful when a macro should adapt to a range whose size changes, rather than hard-coding its dimensions.
There is an important exception: a single-cell range’s Value is a scalar value, not a two-dimensional array. Calling UBound on that scalar will fail. If code may read either one cell or multiple cells, account for the different return shapes before treating the result as an array.
Array Length Compared with Capacity
In VBA, the bounds describe the valid indexes currently allocated for an array. They do not expose a separate capacity value like some programming languages provide. If a dynamic array has bounds 1 through 100, its current dimension contains 100 positions, whether all, some, or none of those positions have meaningful values.
This also separates array size from the number of occupied entries. An array can have 10 allocated elements while only 6 contain non-empty strings. Counting non-empty strings requires examining the values, not just subtracting the bounds. Similarly, a two-dimensional array’s total position count is the product of its dimension sizes, whereas the count of qualifying records may require checking a condition in each row.
Collections are a related but different VBA structure. A Collection exposes a Count property, while an array uses bounds. If the code needs a resizable set of items with a direct item count, a Collection may fit better; if it needs indexed, compact data or a block of worksheet values, an array is often appropriate.
Common Mistakes and How to Avoid Them
- Using only UBound: this gives the greatest index, not a reliable count when the lower bound can vary. Subtract
LBoundand add 1. - Forgetting the dimension argument: in a two-dimensional array, the default dimension is 1. Specify 2 to count columns, or the appropriate number for another dimension.
- Counting an unallocated dynamic array: allocate it first or handle the bounds error deliberately.
- Assuming every range result is an array: a one-cell range returns a scalar, so code that uses array bounds needs to account for it.
- Confusing allocated slots with filled values: bounds count positions, not nonblank cells, nonzero values, or records that pass a test.
When looping through an array, use its actual lower and upper bounds if the indexing base is not guaranteed. A loop that always starts at 0 can fail for a one-based array; one that always starts at 1 can skip the first value or fail for a zero-based array.
Frequently Asked Questions
How do I get the length of an array in VBA?
For one dimension, use UBound(array) - LBound(array) + 1. This counts every valid subscript, including both the lower and upper bounds.
Does UBound return the number of elements?
Not in every case. It returns the largest index in the selected dimension. It equals the count only when the lower bound is zero; otherwise, subtract the lower bound and add 1.
How do I count columns in a two-dimensional array?
Use UBound(array, 2) - LBound(array, 2) + 1. Dimension 2 is commonly the column dimension for arrays read from multi-cell Excel ranges.
What happens if I call UBound on an unallocated array?
VBA raises an error because the dynamic array has no valid bounds yet. Use ReDim to allocate it first, or handle the bounds error if an unallocated state is expected.
Can VBA arrays have a lower bound other than zero or one?
Yes. You can specify bounds such as 5 To 9 in an array declaration or when using ReDim. The LBound-and-UBound formula still counts the elements correctly.
Is array length the same as the number of non-empty values?
No. Array length is the number of allocated positions in a dimension. To count only non-empty values, inspect the elements and count those that meet the condition.
Related
- Excel Shortcut to Select a Row
- Excel Shortcut to Select Visible Cells in a Filtered Range
- Excel Save As Shortcut: Windows, Mac, and Web
Try it: the Column Letter to Number: aA is 27, XFD is 16,384. Converts both ways.
More in VBA & macros
- AutoHotkey v2 Macro Recorder: Options and Setup GuideAutoHotkey v2 does not include a built-in macro recorder: it is a scripting language for Windows automation, so…
- Read a Text File with Excel VBA: Methods and ExamplesYes. In Excel for Microsoft 365 on Windows, VBA can read a plain-text file with the Open and…
- Excel VBA Popup Message: Show a MsgBox in a MacroTo show a popup message in Excel VBA, use the MsgBox function in a macro, such as MsgBox…
- VBA Range.Intersect: Find Overlapping CellsIn VBA, use Application.Intersect(range1, range2) to find the cells shared by two or more ranges. It returns a…
- Microsoft Excel VBA InputBox: How to Use It SafelyIn Excel VBA, use InputBox to ask a person for a text response, or use Application.InputBox when you…
- Excel VBA: Turn On AutoFilter and Show Filter ArrowsTo turn on AutoFilter in Excel VBA, call the AutoFilter method on the complete data range, including its…
Sources: Function behaviour and menu paths: Microsoft Support documentation for Excel. Method & sources
Spotted an error in this guide? Let us know.