16

I would like to add a value to the end of a VBA array. How can I do this? I was not able to find a simple example online. Here's some pseudocode showing what I would like to be able to do.

Public Function toArray(range As range)
 Dim arr() As Variant
 For Each a In range.Cells
  'how to add dynamically the value to end and increase the array?
   arr(arr.count) = a.Value 'pseudo code
 Next
toArray= Join(arr, ",")
End Function
TylerH
  • 543
  • 1
  • 7
  • 20
megloff
  • 409
  • 2
  • 5
  • 11
  • Is the idea to add values to the end of an existing array? Or is it like your example where you just want to load a range into an array? If the latter, why not use the one-liner `arr = Range.Value`? – Excellll Sep 09 '14 at 20:13

7 Answers7

12

I solved the issue by using a Collection and copy it afterwards to an array.

Dim col As New Collection
For Each a In range.Cells
   col.Add a.Value  '  dynamically add value to the end
Next
Dim arr() As Variant
arr = toArray(col) 'convert collection to an array

Function toArray(col As Collection)
  Dim arr() As Variant
  ReDim arr(0 To col.Count-1) As Variant
  For i = 1 To col.Count
      arr(i-1) = col(i)
  Next
  toArray = arr
End Function
megloff
  • 409
  • 2
  • 5
  • 11
  • 3
    If you're going to use a Collection, you might as well use a Dictionary Object. ` Set col = CreateObject("Scripting.Dictionary") ` Then you can output the Keys directly as an array and skip your added function: ` arr = col.keys ` <= Array – B Hart Oct 05 '16 at 15:13
10

Try this [EDITED]:

Dim arr() As Variant ' let brackets empty, not Dim arr(1) As Variant !

For Each a In range.Cells
    ' change / adjust the size of array 
    ReDim Preserve arr(1 To UBound(arr) + 1) As Variant

    ' add value on the end of the array
    arr (UBound(arr)) = a.value
Next
Leo Chapiro
  • 15,459
  • 5
  • 42
  • 45
  • Thanks but unfortunately this does not work the `UBound(arr)` requires that `arr` is initialized with some dimenstion e.g. `Dim arr(1) As Variant` but then later the `ReDim Preserve` is failing and says that the array already is dimensioned? with other words you can not redim an array in VBA? – megloff Sep 09 '14 at 08:41
  • According to http://msdn.microsoft.com/library/w8k3cys2.aspx you should can ... – Leo Chapiro Sep 09 '14 at 08:48
  • Well the example from msdn does also not work in excel vba. same error, complains that array already is dimensioned – megloff Sep 09 '14 at 09:18
  • It looks like that I should use instead of an array a `Collection` and convert it afterwards to an array. Any other suggestions? – megloff Sep 09 '14 at 09:21
  • I've got it: you need to Dim arr() As Variant - consider empty brackets! Elsewhere the array is static, e.g. Dim arr(1) As Variant will NOT work! – Leo Chapiro Sep 09 '14 at 09:31
  • Thanks, but with empty brackets `Dim arr() As Variant` the later statement `arr (UBound(arr)) = a.value` will not work, it complaints that the index is out of range (because the array is not yet dimensioned). – megloff Sep 09 '14 at 10:15
  • In this case just make ReDim first - I've edited my answer – Leo Chapiro Sep 09 '14 at 10:44
  • 2
    Thank you but it still does not wor k this way because as mentioned earlier the `UBound(arr)` requires an already a dimensioned array. Well It looks like that I have to use a collection instead. Thank you anyway – megloff Sep 09 '14 at 11:57
4

This is how I do it, using a Variant (array) variable:

Dim a As Range
Dim arr As Variant  'Just a Variant variable (i.e. don't pre-define it as an array)

For Each a In Range.Cells
    If IsEmpty(arr) Then
        arr = Array(a.value) 'Make the Variant an array with a single element
    Else
        ReDim Preserve arr(UBound(arr) + 1) 'Add next array element
        arr(UBound(arr)) = a.value          'Assign the array element
    End If
Next

Or, if you actually do need an array of Variants (to pass to a property like Shapes.Range, for example), then you can do it this way:

Dim a As Range
Dim arr() As Variant

ReDim arr(0 To 0)                       'Allocate first element
For Each a In Range.Cells
    arr(UBound(arr)) = a.value          'Assign the array element
    ReDim Preserve arr(UBound(arr) + 1) 'Allocate next element
Next
ReDim Preserve arr(LBound(arr) To UBound(arr) - 1)  'Deallocate the last, unused element
pstraton
  • 41
  • 2
1

If your range is a single vector, and, if in a column, the number of rows is less than 16,384, you can use the following code:

Option Explicit
Public Function toArray(RNG As Range)
    Dim arr As Variant
    arr = RNG

    With WorksheetFunction
        If UBound(arr, 2) > 1 Then
            toArray = Join((.Index(arr, 1, 0)), ",")
        Else
            toArray = Join(.Transpose(.Index(arr, 0, 1)), ",")
        End If
    End With
End Function
Ron Rosenfeld
  • 8,198
  • 3
  • 13
  • 17
0

The answer is in the accepted response in(without the ReDim problem):

https://stackoverflow.com/questions/12663879/adding-values-to-variable-array-vba

In resume:

Dim aArray() As Single ' or whatever data type you wish to use
ReDim aArray(1 To 1) As Single
If strFirstName = "henry" Then
    aArray(UBound(aArray)) = 123.45
    ReDim Preserve aArray(1 To UBound(aArray) + 1) As Single
End If
0
Dim arr()  As Variant: ReDim Preserve arr(0) ' Create dynamic array

' Append to dynamic array function
Function AppendArray(arr() As Variant, var As Variant) As Variant
    ReDim Preserve arr(LBound(arr) To UBound(arr) + 1) ' Resize array, add index
    arr(UBound(arr) - 1) = var ' Append to array
End Function
0

Thx. Doing the same with 2 functions if it can help other noobs like me :

Collection

Function toCollection(ByVal NamedRange As String) As Collection
  Dim i As Integer
  Dim col As New Collection
  Dim Myrange As Variant, aData As Variant
  Myrange = Range(NamedRange)
  For Each aData In Myrange
    col.Add aData '.Value
  Next
  Set toCollection = col
  Set col = Nothing
End Function

1D Array :

Function toArray1D(MyCollection As Collection)
    ' See http://superuser.com/a/809212/69050


  If MyCollection Is Nothing Then
    Debug.Print Chr(10) & Time & ": Collection Is Empty"
    Exit Function
  End If

  Dim myarr() As Variant
  Dim i As Integer
  ReDim myarr(1 To MyCollection.Count) As Variant

  For i = 1 To MyCollection.Count
      myarr(i) = MyCollection(i)
  Next i

  toArray1D = myarr
End Function

Usage

Dim col As New Collection
Set col = toCollection(RangeName(0))
Dim arr() As Variant
arr = toArray1D(col)
Set col = Nothing
hornetbzz
  • 211
  • 3
  • 13