Populating VBA dynamic arrays











up vote
38
down vote

favorite
19












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









share|improve this question


























    up vote
    38
    down vote

    favorite
    19












    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









    share|improve this question
























      up vote
      38
      down vote

      favorite
      19









      up vote
      38
      down vote

      favorite
      19






      19





      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









      share|improve this question













      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 13 '12 at 13:01









      sebastien leblanc

      25011025




      25011025
























          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





          share|improve this answer

















          • 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








          • 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 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




            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


















          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)





          share|improve this answer



















          • 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




















          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.






          share|improve this answer



















          • 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 at UBound(.eElems) when calling PushBackIntArray for the first time... any thoughts?
            – minovsky
            Aug 4 '14 at 16:16


















          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




          1. Creating an array big enough to handle anything you think will be thrown at it


          2. Sensible use of Redim 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





          share|improve this answer




























            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.






            share|improve this answer























            • That comment re all coded above relying on ubound/lbound is incorrect
              – brettdj
              Apr 27 '15 at 11:08











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            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

























            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





            share|improve this answer

















            • 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








            • 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 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




              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















            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





            share|improve this answer

















            • 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








            • 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 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




              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













            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





            share|improve this answer












            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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 13 '12 at 13:08









            Fluffi1974

            71477




            71477








            • 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








            • 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 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




              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




              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




              @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 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




              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












            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)





            share|improve this answer



















            • 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

















            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)





            share|improve this answer



















            • 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















            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)





            share|improve this answer














            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)






            share|improve this answer














            share|improve this answer



            share|improve this answer








            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
















            • 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












            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.






            share|improve this answer



















            • 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 at UBound(.eElems) when calling PushBackIntArray for the first time... any thoughts?
              – minovsky
              Aug 4 '14 at 16:16















            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.






            share|improve this answer



















            • 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 at UBound(.eElems) when calling PushBackIntArray for the first time... any thoughts?
              – minovsky
              Aug 4 '14 at 16:16













            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.






            share|improve this answer














            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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 at UBound(.eElems) when calling PushBackIntArray for the first time... any thoughts?
              – minovsky
              Aug 4 '14 at 16:16














            • 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 at UBound(.eElems) when calling PushBackIntArray 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










            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




            1. Creating an array big enough to handle anything you think will be thrown at it


            2. Sensible use of Redim 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





            share|improve this answer

























              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




              1. Creating an array big enough to handle anything you think will be thrown at it


              2. Sensible use of Redim 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





              share|improve this answer























                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




                1. Creating an array big enough to handle anything you think will be thrown at it


                2. Sensible use of Redim 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





                share|improve this answer












                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




                1. Creating an array big enough to handle anything you think will be thrown at it


                2. Sensible use of Redim 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






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 14 '12 at 12:21









                brettdj

                47.6k1692148




                47.6k1692148






















                    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.






                    share|improve this answer























                    • That comment re all coded above relying on ubound/lbound is incorrect
                      – brettdj
                      Apr 27 '15 at 11:08















                    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.






                    share|improve this answer























                    • That comment re all coded above relying on ubound/lbound is incorrect
                      – brettdj
                      Apr 27 '15 at 11:08













                    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.






                    share|improve this answer














                    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.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    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


















                    • 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


















                    draft saved

                    draft discarded




















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Xamarin.iOS Cant Deploy on Iphone

                    Glorious Revolution

                    Dulmage-Mendelsohn matrix decomposition in Python