The issue with using Redim Preserve
to combine arrays is it can be an expensive operation, since you're basically re-creating the array everytime it's called. Since you have 46 arrays you're combining, you may very well be waiting a while.
Instead, you can loop over the arrays to figure out the total number of elements you need, dimension out your master array, then loop over the arrays again to do the actual assignment/merging. Something like this:
' encapsulates code to determine length of an individual array
' note that because arrays can have different LBounds in VBA, we can't simply use
' Ubound to determine array length
Public Function GetArrayLength(anArray As Variant) As Integer
If Not IsArray(anArray) Then
GetArrayLength = -1
Else
GetArrayLength = UBound(anArray) - LBound(anArray) + 1
End If
End Function
Public Function CombineArrays(ParamArray arraysToMerge() As Variant) As Variant
' index for looping over the arraysToMerge array of arrays,
' and then each item in each array
Dim i As Integer, j As Integer
' variable to store where we are in the combined array
Dim combinedArrayIndex As Integer
' variable to hold the number of elements in the final combined array
Dim CombinedArrayLength As Integer
' we don't initialize the array with an array-length until later,
' when we know how long it needs to be.
Dim combinedArray() As Variant
' we have to loop over the arrays twice:
' First, to figure out the total number of elements in the combined array
' second, to actually assign the values
' otherwise, we'd be using Redim Preserve, which can get quite expensive
' because we're creating a new array everytime we use it.
CombinedArrayLength = 0
For i = LBound(arraysToMerge) To UBound(arraysToMerge)
CombinedArrayLength = CombinedArrayLength + GetArrayLength(arraysToMerge(i))
Next i
' now that we know how long the combined array has to be,
' we can properly initialize it.
' you can also use the commented code instead, if you prefer 1-based arrays.
ReDim combinedArray(0 To CombinedArrayLength - 1)
' Redim combinedArray(1 to CombinedArrayLength)
' now that the combinedarray is set up to store all the values in the arrays,
' we can begin actual assignment
combinedArrayIndex = LBound(combinedArray)
For i = LBound(arraysToMerge) To UBound(arraysToMerge)
For j = LBound(arraysToMerge(i)) To UBound(arraysToMerge(i))
combinedArray(combinedArrayIndex) = arraysToMerge(i)(j)
combinedArrayIndex = combinedArrayIndex + 1
Next j
Next i
' assign the function to the master array we've been using
CombineArrays = combinedArray
End Function
To use this function, you'd do something like the following:
Public Sub TestArrayMerge()
Dim myArray1() As Variant
Dim myArray2() As Variant
Dim myArray3() As Variant
Dim myArray4() As Variant
Dim combinedArray As Variant
myArray1 = Array(1, 2, 3, 4)
myArray2 = Array(5, 6, 7)
myArray3 = Array(8, 9)
myArray4 = Array(10, 11, 12, 13, 14)
combinedArray = CombineArrays(myArray1, myArray2, myArray3, myArray4)
If IsArray(combinedArray) Then
Debug.Print Join(combinedArray, ",")
End If
End Sub
Regarding your last bit, that you're using an inner loop to combine the values in your final combined array: Your inner loop doesn't need to start at LBound(myArray)
. For any value of i
, you've already compared it to the elements before it (e.g., when i = 2
, it's already been compared to the first element). So you really just need:
For i = LBound(combinedArray) To UBound(combinedArray) - 1
For j = i + 1 To UBound(combinedArray)
' do whatever you need
Next j
Next i