Populating VBA dynamic arrays
up vote
38
down vote
favorite
The following code gives me error 9 "subscript out of range". I meant to declare a dynamic array so that the dimension changes as I add elements to it. Do I have to create a "spot" on the array before I store something in it like in JS?
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
arrays vba
add a comment |
up vote
38
down vote
favorite
The following code gives me error 9 "subscript out of range". I meant to declare a dynamic array so that the dimension changes as I add elements to it. Do I have to create a "spot" on the array before I store something in it like in JS?
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
arrays vba
add a comment |
up vote
38
down vote
favorite
up vote
38
down vote
favorite
The following code gives me error 9 "subscript out of range". I meant to declare a dynamic array so that the dimension changes as I add elements to it. Do I have to create a "spot" on the array before I store something in it like in JS?
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
arrays vba
The following code gives me error 9 "subscript out of range". I meant to declare a dynamic array so that the dimension changes as I add elements to it. Do I have to create a "spot" on the array before I store something in it like in JS?
Sub test_array()
Dim test() As Integer
Dim i As Integer
For i = 0 To 3
test(i) = 3 + i
Next i
End Sub
arrays vba
arrays vba
asked Jan 13 '12 at 13:01
sebastien leblanc
25011025
25011025
add a comment |
add a comment |
5 Answers
5
active
oldest
votes
up vote
51
down vote
accepted
in your for loop use a Redim on the array like here:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
17
Why would you do it in the loop?ReDim
, and especially when you addPreserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need thePreserve
.
– Cody Gray♦
Jan 13 '12 at 13:10
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like3
, you're still specifying an upper-bound in theFor
statement. Use that to dynamically initialize the size of the array.
– Cody Gray♦
Jan 13 '12 at 13:30
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
|
show 1 more comment
up vote
24
down vote
Yes, you're looking for the ReDim
statement, which dynamically allocates the required amount of space in the array.
The following statement
Dim MyArray()
declares an array without dimensions, so the compiler doesn't know how big it is and can't store anything inside of it.
But you can use the ReDim
statement to resize the array:
ReDim MyArray(0 To 3)
And if you need to resize the array while preserving its contents, you can use the Preserve
keyword along with the ReDim
statement:
ReDim Preserve MyArray(0 To 3)
But do note that both ReDim
and particularly ReDim Preserve
have a heavy performance cost. Try to avoid doing this over and over in a loop if at all possible; your users will thank you.
However, in the simple example shown in your question (if it's not just a throwaway sample), you don't need ReDim
at all. Just declare the array with explicit dimensions:
Dim MyArray(0 To 3)
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
add a comment |
up vote
20
down vote
As Cody and Brett mentioned, you could reduce VBA slowdown with sensible use of Redim Preserve
. Brett suggested Mod
to do this.
You can also use a user defined Type
and Sub
to do this. Consider my code below:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
This calls ReDim Preserve
only when the size has doubled. The member variable eSize
keeps track of the actual data size of eElems
. This approach has helped me improve performance when final array length is not known until run time.
Hope this helps others too.
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error atUBound(.eElems)
when callingPushBackIntArray
for the first time... any thoughts?
– minovsky
Aug 4 '14 at 16:16
add a comment |
up vote
9
down vote
In addition to Cody's useful comments it is worth noting that at times you won't know how big your array should be. The two options in this situation are
- Creating an array big enough to handle anything you think will be thrown at it
Sensible use ofRedim Preserve
The code below provides an example of a routine that will dimension myArray
in line with the lngSize
variable, then add additional elements (equal to the initial array size) by use of a Mod
test whenever the upper bound is about to be exceeded
Option Base 1
Sub ArraySample()
Dim myArray() As String
Dim lngCnt As Long
Dim lngSize As Long
lngSize = 10
ReDim myArray(1 To lngSize)
For lngCnt = 1 To lngSize*5
If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
myArray(lngCnt) = "I am record number " & lngCnt
Next
End Sub
add a comment |
up vote
8
down vote
I see many (all) posts above relying on LBound
/UBound
calls upon yet potentially uninitialized VBA dynamic array, what causes application's inevitable death ...
Erratic code:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
Correct code:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
... i.e. any code where Dim arr1()
is followed immediatelly by LBound(arr1)
/UBound(arr1)
calls without ReDim arr1(...)
in between, crashes. The roundabout is to employ an On Error Resume Next
and check the Err.Number
right after the LBound(arr1)
/UBound(arr1)
call - it should be 0 if the array is initialized, otherwise non-zero. As there is some VBA built-in misbehavior, the further check of array's limits is needed. Detailed explanation may everybody read at Chip Pearson's website (which should be celebrated as a Mankind Treasure Of VBA Wisdom ...)
Heh, that's my first post, believe it is legible.
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
add a comment |
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
51
down vote
accepted
in your for loop use a Redim on the array like here:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
17
Why would you do it in the loop?ReDim
, and especially when you addPreserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need thePreserve
.
– Cody Gray♦
Jan 13 '12 at 13:10
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like3
, you're still specifying an upper-bound in theFor
statement. Use that to dynamically initialize the size of the array.
– Cody Gray♦
Jan 13 '12 at 13:30
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
|
show 1 more comment
up vote
51
down vote
accepted
in your for loop use a Redim on the array like here:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
17
Why would you do it in the loop?ReDim
, and especially when you addPreserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need thePreserve
.
– Cody Gray♦
Jan 13 '12 at 13:10
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like3
, you're still specifying an upper-bound in theFor
statement. Use that to dynamically initialize the size of the array.
– Cody Gray♦
Jan 13 '12 at 13:30
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
|
show 1 more comment
up vote
51
down vote
accepted
up vote
51
down vote
accepted
in your for loop use a Redim on the array like here:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
in your for loop use a Redim on the array like here:
For i = 0 to 3
ReDim Preserve test(i)
test(i) = 3 + i
Next i
answered Jan 13 '12 at 13:08
Fluffi1974
71477
71477
17
Why would you do it in the loop?ReDim
, and especially when you addPreserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need thePreserve
.
– Cody Gray♦
Jan 13 '12 at 13:10
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like3
, you're still specifying an upper-bound in theFor
statement. Use that to dynamically initialize the size of the array.
– Cody Gray♦
Jan 13 '12 at 13:30
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
|
show 1 more comment
17
Why would you do it in the loop?ReDim
, and especially when you addPreserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need thePreserve
.
– Cody Gray♦
Jan 13 '12 at 13:10
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like3
, you're still specifying an upper-bound in theFor
statement. Use that to dynamically initialize the size of the array.
– Cody Gray♦
Jan 13 '12 at 13:30
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
17
17
Why would you do it in the loop?
ReDim
, and especially when you add Preserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need the Preserve
.– Cody Gray♦
Jan 13 '12 at 13:10
Why would you do it in the loop?
ReDim
, and especially when you add Preserve
, is a potential performance killer. You know how many times the loop is going to iterate, so definitely do it outside of the loop. Then you're only resizing the array once, and you don't need the Preserve
.– Cody Gray♦
Jan 13 '12 at 13:10
9
9
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
@CodyGray You are absolutely right if the final array size is already defined on entering the loop. Putting the Redim inside of the loop would be a performance killer. However, I assumed that the size of the array is not determined on entering the loop. Otherwise the whole sample doesn't make sense at all...
– Fluffi1974
Jan 13 '12 at 13:29
3
3
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like
3
, you're still specifying an upper-bound in the For
statement. Use that to dynamically initialize the size of the array.– Cody Gray♦
Jan 13 '12 at 13:30
It has to be defined upon entering the loop. You have to define the range of the loop. Even if it's a variable rather than a constant like
3
, you're still specifying an upper-bound in the For
statement. Use that to dynamically initialize the size of the array.– Cody Gray♦
Jan 13 '12 at 13:30
2
2
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
You could leave the array using "Exit For"
– Fluffi1974
Jan 13 '12 at 13:35
3
3
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
Maybe this solution is not very nice regarding optimalisation, but if you would not know the size in front - e.g. doing a while loop with some condition - then this may be the easiest solution
– Asped
Aug 1 '14 at 11:43
|
show 1 more comment
up vote
24
down vote
Yes, you're looking for the ReDim
statement, which dynamically allocates the required amount of space in the array.
The following statement
Dim MyArray()
declares an array without dimensions, so the compiler doesn't know how big it is and can't store anything inside of it.
But you can use the ReDim
statement to resize the array:
ReDim MyArray(0 To 3)
And if you need to resize the array while preserving its contents, you can use the Preserve
keyword along with the ReDim
statement:
ReDim Preserve MyArray(0 To 3)
But do note that both ReDim
and particularly ReDim Preserve
have a heavy performance cost. Try to avoid doing this over and over in a loop if at all possible; your users will thank you.
However, in the simple example shown in your question (if it's not just a throwaway sample), you don't need ReDim
at all. Just declare the array with explicit dimensions:
Dim MyArray(0 To 3)
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
add a comment |
up vote
24
down vote
Yes, you're looking for the ReDim
statement, which dynamically allocates the required amount of space in the array.
The following statement
Dim MyArray()
declares an array without dimensions, so the compiler doesn't know how big it is and can't store anything inside of it.
But you can use the ReDim
statement to resize the array:
ReDim MyArray(0 To 3)
And if you need to resize the array while preserving its contents, you can use the Preserve
keyword along with the ReDim
statement:
ReDim Preserve MyArray(0 To 3)
But do note that both ReDim
and particularly ReDim Preserve
have a heavy performance cost. Try to avoid doing this over and over in a loop if at all possible; your users will thank you.
However, in the simple example shown in your question (if it's not just a throwaway sample), you don't need ReDim
at all. Just declare the array with explicit dimensions:
Dim MyArray(0 To 3)
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
add a comment |
up vote
24
down vote
up vote
24
down vote
Yes, you're looking for the ReDim
statement, which dynamically allocates the required amount of space in the array.
The following statement
Dim MyArray()
declares an array without dimensions, so the compiler doesn't know how big it is and can't store anything inside of it.
But you can use the ReDim
statement to resize the array:
ReDim MyArray(0 To 3)
And if you need to resize the array while preserving its contents, you can use the Preserve
keyword along with the ReDim
statement:
ReDim Preserve MyArray(0 To 3)
But do note that both ReDim
and particularly ReDim Preserve
have a heavy performance cost. Try to avoid doing this over and over in a loop if at all possible; your users will thank you.
However, in the simple example shown in your question (if it's not just a throwaway sample), you don't need ReDim
at all. Just declare the array with explicit dimensions:
Dim MyArray(0 To 3)
Yes, you're looking for the ReDim
statement, which dynamically allocates the required amount of space in the array.
The following statement
Dim MyArray()
declares an array without dimensions, so the compiler doesn't know how big it is and can't store anything inside of it.
But you can use the ReDim
statement to resize the array:
ReDim MyArray(0 To 3)
And if you need to resize the array while preserving its contents, you can use the Preserve
keyword along with the ReDim
statement:
ReDim Preserve MyArray(0 To 3)
But do note that both ReDim
and particularly ReDim Preserve
have a heavy performance cost. Try to avoid doing this over and over in a loop if at all possible; your users will thank you.
However, in the simple example shown in your question (if it's not just a throwaway sample), you don't need ReDim
at all. Just declare the array with explicit dimensions:
Dim MyArray(0 To 3)
edited Jan 13 '12 at 13:23
answered Jan 13 '12 at 13:09
Cody Gray♦
190k34370459
190k34370459
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
add a comment |
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
3
3
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:
ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
+1 though I would add that the lower bound can and in my opinion should be specified explicitly:
ReDim MyArray(0 To 3)
– Jean-François Corbett
Jan 13 '12 at 13:22
1
1
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
@Jean: That's good advice. A lot of people are bitten by the fact that VB(A) supports lower bounds other than 0. Being explicit is always good practice.
– Cody Gray♦
Jan 13 '12 at 13:24
add a comment |
up vote
20
down vote
As Cody and Brett mentioned, you could reduce VBA slowdown with sensible use of Redim Preserve
. Brett suggested Mod
to do this.
You can also use a user defined Type
and Sub
to do this. Consider my code below:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
This calls ReDim Preserve
only when the size has doubled. The member variable eSize
keeps track of the actual data size of eElems
. This approach has helped me improve performance when final array length is not known until run time.
Hope this helps others too.
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error atUBound(.eElems)
when callingPushBackIntArray
for the first time... any thoughts?
– minovsky
Aug 4 '14 at 16:16
add a comment |
up vote
20
down vote
As Cody and Brett mentioned, you could reduce VBA slowdown with sensible use of Redim Preserve
. Brett suggested Mod
to do this.
You can also use a user defined Type
and Sub
to do this. Consider my code below:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
This calls ReDim Preserve
only when the size has doubled. The member variable eSize
keeps track of the actual data size of eElems
. This approach has helped me improve performance when final array length is not known until run time.
Hope this helps others too.
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error atUBound(.eElems)
when callingPushBackIntArray
for the first time... any thoughts?
– minovsky
Aug 4 '14 at 16:16
add a comment |
up vote
20
down vote
up vote
20
down vote
As Cody and Brett mentioned, you could reduce VBA slowdown with sensible use of Redim Preserve
. Brett suggested Mod
to do this.
You can also use a user defined Type
and Sub
to do this. Consider my code below:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
This calls ReDim Preserve
only when the size has doubled. The member variable eSize
keeps track of the actual data size of eElems
. This approach has helped me improve performance when final array length is not known until run time.
Hope this helps others too.
As Cody and Brett mentioned, you could reduce VBA slowdown with sensible use of Redim Preserve
. Brett suggested Mod
to do this.
You can also use a user defined Type
and Sub
to do this. Consider my code below:
Public Type dsIntArrayType
eElems() As Integer
eSize As Integer
End Type
Public Sub PushBackIntArray( _
ByRef dsIntArray As dsIntArrayType, _
ByVal intValue As Integer)
With dsIntArray
If UBound(.eElems) < (.eSize + 1) Then
ReDim Preserve .eElems(.eSize * 2 + 1)
End If
.eSize = .eSize + 1
.eElems(.eSize) = intValue
End With
End Sub
This calls ReDim Preserve
only when the size has doubled. The member variable eSize
keeps track of the actual data size of eElems
. This approach has helped me improve performance when final array length is not known until run time.
Hope this helps others too.
edited Nov 11 at 19:27
anothermh
2,80411226
2,80411226
answered Aug 21 '13 at 18:23
a505999
30147
30147
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error atUBound(.eElems)
when callingPushBackIntArray
for the first time... any thoughts?
– minovsky
Aug 4 '14 at 16:16
add a comment |
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error atUBound(.eElems)
when callingPushBackIntArray
for the first time... any thoughts?
– minovsky
Aug 4 '14 at 16:16
1
1
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
you realize this question was asked (and answered) 18 months ago, right?
– David Zemens
Aug 21 '13 at 19:07
16
16
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
yes! wanted to offer an alternative for other readers as well. i realize the op has accepted the previous answer already. thanks.
– a505999
Aug 21 '13 at 19:08
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
Well then here's a +1 for you, interesting alternative! :)
– David Zemens
Aug 21 '13 at 19:13
5
5
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
+1. this is similar to how dynamic arrays are implemented in C++ standard library. I would make push_back a method and the type a class, for encapsulation purposes.
– Ioannis
Aug 21 '13 at 20:40
I got a subscript out of range error at
UBound(.eElems)
when calling PushBackIntArray
for the first time... any thoughts?– minovsky
Aug 4 '14 at 16:16
I got a subscript out of range error at
UBound(.eElems)
when calling PushBackIntArray
for the first time... any thoughts?– minovsky
Aug 4 '14 at 16:16
add a comment |
up vote
9
down vote
In addition to Cody's useful comments it is worth noting that at times you won't know how big your array should be. The two options in this situation are
- Creating an array big enough to handle anything you think will be thrown at it
Sensible use ofRedim Preserve
The code below provides an example of a routine that will dimension myArray
in line with the lngSize
variable, then add additional elements (equal to the initial array size) by use of a Mod
test whenever the upper bound is about to be exceeded
Option Base 1
Sub ArraySample()
Dim myArray() As String
Dim lngCnt As Long
Dim lngSize As Long
lngSize = 10
ReDim myArray(1 To lngSize)
For lngCnt = 1 To lngSize*5
If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
myArray(lngCnt) = "I am record number " & lngCnt
Next
End Sub
add a comment |
up vote
9
down vote
In addition to Cody's useful comments it is worth noting that at times you won't know how big your array should be. The two options in this situation are
- Creating an array big enough to handle anything you think will be thrown at it
Sensible use ofRedim Preserve
The code below provides an example of a routine that will dimension myArray
in line with the lngSize
variable, then add additional elements (equal to the initial array size) by use of a Mod
test whenever the upper bound is about to be exceeded
Option Base 1
Sub ArraySample()
Dim myArray() As String
Dim lngCnt As Long
Dim lngSize As Long
lngSize = 10
ReDim myArray(1 To lngSize)
For lngCnt = 1 To lngSize*5
If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
myArray(lngCnt) = "I am record number " & lngCnt
Next
End Sub
add a comment |
up vote
9
down vote
up vote
9
down vote
In addition to Cody's useful comments it is worth noting that at times you won't know how big your array should be. The two options in this situation are
- Creating an array big enough to handle anything you think will be thrown at it
Sensible use ofRedim Preserve
The code below provides an example of a routine that will dimension myArray
in line with the lngSize
variable, then add additional elements (equal to the initial array size) by use of a Mod
test whenever the upper bound is about to be exceeded
Option Base 1
Sub ArraySample()
Dim myArray() As String
Dim lngCnt As Long
Dim lngSize As Long
lngSize = 10
ReDim myArray(1 To lngSize)
For lngCnt = 1 To lngSize*5
If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
myArray(lngCnt) = "I am record number " & lngCnt
Next
End Sub
In addition to Cody's useful comments it is worth noting that at times you won't know how big your array should be. The two options in this situation are
- Creating an array big enough to handle anything you think will be thrown at it
Sensible use ofRedim Preserve
The code below provides an example of a routine that will dimension myArray
in line with the lngSize
variable, then add additional elements (equal to the initial array size) by use of a Mod
test whenever the upper bound is about to be exceeded
Option Base 1
Sub ArraySample()
Dim myArray() As String
Dim lngCnt As Long
Dim lngSize As Long
lngSize = 10
ReDim myArray(1 To lngSize)
For lngCnt = 1 To lngSize*5
If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
myArray(lngCnt) = "I am record number " & lngCnt
Next
End Sub
answered Jan 14 '12 at 12:21
brettdj
47.6k1692148
47.6k1692148
add a comment |
add a comment |
up vote
8
down vote
I see many (all) posts above relying on LBound
/UBound
calls upon yet potentially uninitialized VBA dynamic array, what causes application's inevitable death ...
Erratic code:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
Correct code:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
... i.e. any code where Dim arr1()
is followed immediatelly by LBound(arr1)
/UBound(arr1)
calls without ReDim arr1(...)
in between, crashes. The roundabout is to employ an On Error Resume Next
and check the Err.Number
right after the LBound(arr1)
/UBound(arr1)
call - it should be 0 if the array is initialized, otherwise non-zero. As there is some VBA built-in misbehavior, the further check of array's limits is needed. Detailed explanation may everybody read at Chip Pearson's website (which should be celebrated as a Mankind Treasure Of VBA Wisdom ...)
Heh, that's my first post, believe it is legible.
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
add a comment |
up vote
8
down vote
I see many (all) posts above relying on LBound
/UBound
calls upon yet potentially uninitialized VBA dynamic array, what causes application's inevitable death ...
Erratic code:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
Correct code:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
... i.e. any code where Dim arr1()
is followed immediatelly by LBound(arr1)
/UBound(arr1)
calls without ReDim arr1(...)
in between, crashes. The roundabout is to employ an On Error Resume Next
and check the Err.Number
right after the LBound(arr1)
/UBound(arr1)
call - it should be 0 if the array is initialized, otherwise non-zero. As there is some VBA built-in misbehavior, the further check of array's limits is needed. Detailed explanation may everybody read at Chip Pearson's website (which should be celebrated as a Mankind Treasure Of VBA Wisdom ...)
Heh, that's my first post, believe it is legible.
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
add a comment |
up vote
8
down vote
up vote
8
down vote
I see many (all) posts above relying on LBound
/UBound
calls upon yet potentially uninitialized VBA dynamic array, what causes application's inevitable death ...
Erratic code:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
Correct code:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
... i.e. any code where Dim arr1()
is followed immediatelly by LBound(arr1)
/UBound(arr1)
calls without ReDim arr1(...)
in between, crashes. The roundabout is to employ an On Error Resume Next
and check the Err.Number
right after the LBound(arr1)
/UBound(arr1)
call - it should be 0 if the array is initialized, otherwise non-zero. As there is some VBA built-in misbehavior, the further check of array's limits is needed. Detailed explanation may everybody read at Chip Pearson's website (which should be celebrated as a Mankind Treasure Of VBA Wisdom ...)
Heh, that's my first post, believe it is legible.
I see many (all) posts above relying on LBound
/UBound
calls upon yet potentially uninitialized VBA dynamic array, what causes application's inevitable death ...
Erratic code:
Dim x As Long
Dim arr1() As SomeType
...
x = UBound(arr1) 'crashes
Correct code:
Dim x As Long
Dim arr1() As SomeType
...
ReDim Preserve arr1(0 To 0)
...
x = UBound(arr1)
... i.e. any code where Dim arr1()
is followed immediatelly by LBound(arr1)
/UBound(arr1)
calls without ReDim arr1(...)
in between, crashes. The roundabout is to employ an On Error Resume Next
and check the Err.Number
right after the LBound(arr1)
/UBound(arr1)
call - it should be 0 if the array is initialized, otherwise non-zero. As there is some VBA built-in misbehavior, the further check of array's limits is needed. Detailed explanation may everybody read at Chip Pearson's website (which should be celebrated as a Mankind Treasure Of VBA Wisdom ...)
Heh, that's my first post, believe it is legible.
edited May 8 at 21:48
Community♦
11
11
answered Mar 27 '14 at 12:25
Petr Pivonka
8111
8111
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
add a comment |
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
That comment re all coded above relying on ubound/lbound is incorrect
– brettdj
Apr 27 '15 at 11:08
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8850984%2fpopulating-vba-dynamic-arrays%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown