8

I'm looping through a named range and appending an array based on if the cell is empty or not. I'm not too familiar with arrays in VBA, so perhaps my logic is incorrect. The code keeps overwriting the 1st element in the array and it never gets incremented. I"m not sure why the UBound(myArray) always stays at 0 even after an element has been assigned to the 1st index.

My code looks something like:

Dim myArray() As Double

ReDim Preserve myArray(0)

    For Each cell In [myRange]
        If cell <> "" Then
            If UBound(myArray) > 0 Then
                ReDim Preserve myArray(0 To UBound(myArray) + 1)
            End If
            myArray(UBound(myArray)) = cell.value
        End If
    Next
0

3 Answers 3

20

Use a variable and increment it, it makes no difference if the variable is larger than the ubound when the code completes:

Sub Test()
Dim myArray() As Double, X As Long
X = 0
ReDim Preserve myArray(X)
For Each cell In Range("Hello")
    If cell <> "" Then
        ReDim Preserve myArray(0 To X)
        myArray(X) = cell.Value
        X = X + 1
    End If
Next
End Sub
Sign up to request clarification or add additional context in comments.

2 Comments

Not a fan of introducing a new variable but this does fix my problem. Thank you very much.
If you want to do it without another variable note my comment on Jeanno's solution, it may be what you are after
5

Change If UBound(myArray) > 0 Then to If UBound(myArray) >= 0 Then that will solve the problem.

Sub Test()
    Dim myArray() As Double
    ReDim Preserve myArray(0)
    For Each cell In Range("Hello")
        If cell <> "" Then
            If UBound(myArray) >= 0 Then
                myArray(UBound(myArray)) = cell.Value
                ReDim Preserve myArray(0 To UBound(myArray) + 1)
            End If
        End If
    Next
End Sub

2 Comments

We all have them - My only critique now is that the UBound will be incremented after the last element is entered, so you'll have an array one "size" bigger than the range of values.
Get round this by putting ReDim Preserve myArray(0 To UBound(myArray) - 1) just before End Sub
3

Expanding Dan Donoghue's solution to avoid excessive redim (and excessive recalculation in the case of Jeanno's solution through use of variables), I would use

Dim rng as Range
Set rng = Range("Hello")

Dim myArray() As Double, X As Long, N As Long
X = 0
N = WorksheetFunction.CountIf(rng, "<>")
ReDim Preserve myArray(X)

For Each cell In rng
    If cell <> "" And X < N Then
        myArray(X) = cell.Value
        X = X + 1
        If X < N Then ReDim Preserve myArray(0 to X)
    End If
Next

1 Comment

I like this, in theory you could save even more cost by using worksheetfunction.counta to determine the redim amount once without looping.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.