Issue with Redim Preserve (2D array) - vba

Yet another topic with multidimensional array and Redim Preserve, I know. I read a lot of them but still can not understand why my code is not working.
I kwow that you can only extend the last dimension and it is what I want: add a new column to my 2D array.
In order to isolate the issue, I test 2 code:
Sub test_Redim_Preserve()
Dim arr() As Variant
ReDim arr(10, 10)
ReDim Preserve arr(UBound(arr,1), UBound(arr,2) + 1)
End Sub
This work fine
Sub test_Redim_Preserve2()
Dim arr() As Variant
ReDim arr(10, 10)
arr = Range("A1:J10")
ReDim Preserve arr(UBound(arr,1), UBound(arr,2) + 1)
End Sub
This give me an error.
I just gave a range to populate my array and then I can´t Redim it. I don´t understand what is missing for it to accept the Redim.
Could someone explain me?

The default lower bound, in the absence of an Option Base statement to the contrary, is 0 but you assign a range to an array, it always has a lower bound of 1, so your code is actually trying to resize the first dimension of the array too by altering its lower bound. Use:
ReDim Preserve arr(1 To UBound(arr, 1), 1 To UBound(arr, 2) + 1)

You can use Option Base 1 at the top of your code, and then your original code will work fine.
Full code:
Option Base 1
Sub test_Redim_Preserve2()
Dim arr() As Variant
ReDim arr(10, 10)
arr = Range("A1:J10")
ReDim Preserve arr(UBound(arr, 1), UBound(arr, 2) + 1)
End Sub

Related

Redim array after it is filled

Before filling my array I don't know how big it's going to get, but at a certain point (after all data has been inserted) I want to redim the array so there are no empty values in the end of the array. If I dim it as
valuesForSix() As Double
I cannot add values with
valuesForSix(0) = 9.654
Can somebody help me?
ReDim it!
Dim valuesForSix() As Double
ReDim valuesForSix(1) As Double
valuesForSix(0) = 9.654
valuesForSix(1) = 10.25
ReDim Preserve valuesForSix(10) As Double
Debug.Print valuesForSix(0)
Debug.Print valuesForSix(1)
The "Preserve" Keyword means that existing data is kept if the array size is increased.
You can use ReDim Preserve to redefine the array's dimensions. The Preserve keyword means the array retains all existing data. See this MSDN language reference for details.
This example initialises an empty array, then loops from 1 to 10 adding an extra element each time:
Dim v() As Double, i As Long
For i = 1 To 10
ReDim Preserve v(1 To i) As Double
v(i) = i
Next i
' v = [1 2 3 4 5 6 7 8 9 10]
You can extend the array by n elements using LBound and UBound:
Dim v(0 To 10) As Double, n As Long
n = 7
ReDim Preserve v(LBound(v) To UBound(v) + n)
' Now v is Double(0 to 17)

How to work with string()()

I have a string()() array that it must be redim in for loop.So How can i do this.
A code like this.
dim arr as string()()=nothing
dim z as integer=nothing
for i= 1 to 5
for j=0 to 536
if j mod i =0 then
redim preserve arr(z)(i)=i.tostring
z+=1
end if
next
next
I found that i must redim arr step by step like below:
redim arr(z)
redim arr(z)(i)
Here is a good reference on Redim. Do not forget to preserve your values.
https://msdn.microsoft.com/en-us/library/w8k3cys2.aspx

Run-time error '9': Subscript out of range with Dynamic Array

Im trying to add a value to a dynamic array but keep getting a run-time error with this. I've found a few different sources saying that this should be the answer, so I cant figure out what I have done wrong...
Sub addtoarray()
Dim catSheets() As String
ReDim Preserve catSheets(UBound(catSheets) + 1)
catSheets(UBound(catSheets)) = "Chemicals"
End Sub
When you create the catSheets() array, it's dimensionless. Therefore, you cannot use UBound() to determine the array's upper boundary.
You can certainly follow up a Dim () with a ReDim if you want to specify an array size, but you won't be able to query the array dimensions until after you've given it some.
So you have a few options. First, you could follow up your Dim () with an immediate ReDim to give your array an initial size:
Dim catSheets() As String
ReDim catSheets(0) As String
...
ReDim Preserve catSheets(...) As String
Or, you could just use ReDim from the start to assign an initial size and still have the ability to ReDim later:
ReDim catSheets(0) As String
...
ReDim Preserve catSheets(...) As String
Alternatively, you could use the Array() function and store it as a Variant. Done this way, you can query the UBound(). For example:
Dim catSheets As Variant
catSheets = Array()
Debug.Print UBound(catSheets) ' => -1
ReDim Preserve catSheets(UBound(catSheets) + 1)
catSheets(UBound(catSheets)) = "Chemicals" ' Works fine
What you can do is to use Variant if you want to preserve the way to use the code.
Sub addtoarray()
Dim catSheets As Variant
catSheets = Array() ' Initially Empty (0 to -1)
Redim Preserve catSheets(Ubound(catSheets) + 1) ' Now it's 0 to 0
catSheets(Ubound(catSheets)) = "Chemicals" ' index here is 0
End Sub

Debugging VBA code - appending values to array

I am trying to use code of the following form to populate an array of x rows:
Dim myarray() As Variant
Dim string1 As String
Dim myarray_ubound As Integer
myarray_ubound = 0
For i = 1 to x
myarray_ubound = myarray_ubound + 1
ReDim Preserve myarray(1 To myarray_ubound, 1 To 2)
myarray(myarray_ubound,1) = i
myarray(myarray_ubound,2) = string1
Next i
However, when I run it it gets stuck after the first loop, telling me that a subscript is out of range. Debugging takes me to the ReDim command.
I used myarray_ubound as an alternative to calling the UBound function many times, but I have tried using this as well and I get the same error.
Can anyone spot what's gone wrong?
See: http://msdn.microsoft.com/en-us/library/aa266231.aspx
"If you use the Preserve keyword, you can resize only the last array dimension and you can't change the number of dimensions at all."
Try
ReDim Preserve myarray(1 To 2, 1 To myarray_ubound)
instead.
you can only redim the last element of the array (not the first), see below. As you know x I would suggest to redim your array with this value from the beginning.
Dim myarray() As Variant
Dim string1 As String
Dim myarray_ubound As Integer
myarray_ubound = 0
For i = 1 To 10
myarray_ubound = myarray_ubound + 1
ReDim Preserve myarray(1 To 2, 1 To myarray_ubound)
myarray(1, myarray_ubound) = i
myarray(2, myarray_ubound) = string1
Next i
Since you are declaring the variable as a Variant i don't see why you need to re-dim. (maybe related to memory issues, feel free to fill in).
I would suggest:
For i = 1 to 10
myArray(1, i-1) = i
myArray(2, i-1) = string1
next i

Subscript out of range when filling data in string array

I'm trying to store some reference data in a string array and then use that later on to compare with another string array. However, the code is not working since I'm getting a "subscript out of range" error (see code comment below).
Sub StoreBaseReferences()
Dim cell As Range
Dim val As Variant
Dim stringValues() As String
Dim i, rowCounter, columnCounter As Integer
rowCounter = 0
columnCounter = 0
For i = 2 To Sheets("sheet").UsedRange.rows.Count
For Each cell In Range(Cells(i, 2), Cells(i, 4))
stringValues(rowCounter, columnCounter) = cell.Value 'this is throwing the subscript ouf of range error
columnCounter = columnCounter + 1
Next cell
rowCounter = rowCounter + 1
columnCounter = 0
Next i
MsgBox (stringValues(0, 0))
End Sub
What is missing here?
Arrays in VBA need to be dimensioned with the number of elements that are expected to be used. You've defined the dimension, but not specified how many elements will be added to it. Try adding the following line just before the For loop:
ReDim stringValues(Sheets("sheet").UsedRange.Rows.Count, 3)
you are declaring a 1d array Dim stringValues() As String
but trying to use it as a 2d array stringValues(rowCounter, columnCounter)
Also, you are not declaring the size of the array and you are trying to use it. In VBA you have to make sure you tell the size of the array at the declaration time.
To delcare the count of elements that the array is capable of storing
Dim stringArray(0 to 10) or Dim stringArray(10)
and when iterating the counter starts at 0.
Using ReDim stringValues() allows you to resize the bounds at a later stage.
The topic is too broad to go over in one answer so check out the links to learn out how to dimension your array
VBA arrays
Array in Excel VBA