As the title states, is there a way to prevent extra elements from showing up in VBA dynamic arrays when they are non-zero based?
For example, when using code similar to the following:
While Cells(ndx, 1).Value <> vbNullString ReDim Preserve data(1 To (UBound(data) + 1)) ndx = ndx + 1 Wend
You have an extra empty array element at the end of processing. While this can be eliminated with the following:
ReDim Preserve data(1 To (UBound(data) - 1))
This doesn’t seem like the best way of resolving this problem.
As such, is there a way to prevent that extra element from being created in the first place? Preferably something that doesn’t require additional logic inside of the loop.
So this has turned out to be an annoying little problem as it looks like there really isn’t a way to prevent the issue from coming up. Based upon the answers provided by the other users, I tired the following approaches to solving the problem.
Using a Collection – While this approach works quite will in situations where you need to read and store data, you can’t use user-defined types with a Collection. Being able to define the item key is useful as you can use it to cross-reference two Collections; however, in VBA there is no way to get the list of keys in the Collection which can be limiting.
Reading an Excel Range into an Array – Another extremely nice approach, but it seems to work best when you know what the ranges are going to be ahead of time. If you have to figure out the ranges on the fly then you might find yourself in a situation where using a Collection or a smaller ReDim array easier to work with.
Building the Array on the fly with ReDim Preserve – While this can be a fairly straightforward operation, there are two issues involved with it. One is that ReDim can be an expensive operation as Visual Basic actually creates a new array with the given size, copies the old array, and then deletes the old array (or releases it for the Garbage Collector in Visual Basic .NET). So you would want to minimize the calls to ReDim if you are going to be working with extremely large arrays.
Additionally, you are likely going to run into a situation similar to the one in the question where you have an extra element at the start of the array or at the end of the array that is empty. The only way around this seems to be to either check to see if you need to resize before doing the operation, or to delete the empty element before returning the results.