Search code examples
excelvbamultidimensional-arrayfindfill

Use findnext to fill multidimensional array VBA Excel


My question actually concerns a matter that extends on EXCEL VBA Store search results in an array?

Here Andreas tried to search through a column and save hits to an array. I am trying the same. But differing in that on (1) finding a value (2) I want to copy different value types from (3) cells in the same row as where the searched value was found, (4) to a two dimensional array.

So the array would (conceptually) look something like:

Searchresult.1st SameRow.Cell1.Value1 SameRow.Cell2.Value2 SameRow.Cell3.Value3
Searchresult.2nd SameRow.Cell1.Value1 SameRow.Cell2.Value2 SameRow.Cell3.Value3
Searchresult.3rd SameRow.Cell1.Value1 SameRow.Cell2.Value2 SameRow.Cell3.Value3

Etc.

The code I use looks like this:

Sub fillArray()

Dim i As Integer
Dim aCell, bCell As Range
Dim arr As Variant

i = 0 

Set aCell = Sheets("Log").UsedRange.Find(What:=("string"), _
                    LookIn:=xlValues, _
                    LookAt:=xlWhole, _
                    SearchOrder:=xlByRows, _
                    SearchDirection:=xlNext, _
                    MatchCase:=False, _
                    SearchFormat:=False)

If Not aCell Is Nothing Then
    Set bCell = aCell
    ReDim Preserve arr(i, 5)
    arr(i, 0) = True 'Boolean
    arr(i, 1) = aCell.Value 'String
    arr(i, 2) = aCell.Cells.Offset(0, 1).Value 
    arr(i, 3) = aCell.Cells.Offset(0, 3).Value
    arr(i, 4) = aCell.Cells.Offset(0, 4).Value
    arr(i, 5) = Year(aCell.Cells.Offset(0, 3).Value)

    i = i + 1

    Do While exitLoop = False
            Set aCell = Sheets("Log").UsedRange.FindNext(after:=aCell)

            If Not aCell Is Nothing Then
                If aCell.Address = bCell.Address Then Exit Do
                'ReDim Preserve arrSwUb(i, 5)
                    arr(i, 0) = True
                    arr(i, 1) = aCell.Value
                    arr(i, 2) = aCell.Cells.Offset(0, 1).Value
                    arr(i, 3) = aCell.Cells.Offset(0, 3).Value
                    arr(i, 4) = aCell.Cells.Offset(0, 4).Value
                    arr(i, 5) = Year(aCell.Cells.Offset(0, 3).Value)

                    i = i + 1
            Else
                exitLoop = True
            End If
    Loop


End If

End Sub

It seems to go wrong on redimming the array in the loop. I get a Subscript out of range error. I guess I can't redim the array as I'm doing now, but I can't figure out how it is supposed to be done.

I’d be greatful for any clues as to what I’m doing wrong.


Solution

  • ReDim Preserve can only resize the last dimension of your array: http://msdn.microsoft.com/en-us/library/w8k3cys2(v=vs.71).aspx

    From the above link:

    Preserve

    Optional. Keyword used to preserve the data in the existing array when you change the size of only the last dimension.

    Edit: That's not enormously helpful, is it. I suggest you transpose your array. Also, those error messages from the array functions are AWFUL.

    At the suggestion of Siddarth, try this. Let me know if you have any problems:

    Sub fillArray()
        Dim i As Integer
        Dim aCell As Range, bCell As Range
        Dim arr As Variant
    
        i = 0
        Set aCell = Sheets("Log").UsedRange.Find(What:=("string"), _
                                                 LookIn:=xlValues, _
                                                 LookAt:=xlWhole, _
                                                 SearchOrder:=xlByRows, _
                                                 SearchDirection:=xlNext, _
                                                 MatchCase:=False, _
                                                 SearchFormat:=False)
        If Not aCell Is Nothing Then
            Set bCell = aCell
            ReDim Preserve arr(0 To 5, 0 To i)
            arr(0, i) = True 'Boolean
            arr(1, i) = aCell.Value 'String
            arr(2, i) = aCell.Cells.Offset(0, 1).Value
            arr(3, i) = aCell.Cells.Offset(0, 3).Value
            arr(4, i) = aCell.Cells.Offset(0, 4).Value
            arr(5, i) = Year(aCell.Cells.Offset(0, 3).Value)
            i = i + 1
            Do While exitLoop = False
                Set aCell = Sheets("Log").UsedRange.FindNext(after:=aCell)
                If Not aCell Is Nothing Then
                    If aCell.Address = bCell.Address Then Exit Do
                    ReDim Preserve arrSwUb(0 To 5, 0 To i)
                    arr(0, i) = True
                    arr(1, i) = aCell.Value
                    arr(2, i) = aCell.Cells.Offset(0, 1).Value
                    arr(3, i) = aCell.Cells.Offset(0, 3).Value
                    arr(4, i) = aCell.Cells.Offset(0, 4).Value
                    arr(5, i) = Year(aCell.Cells.Offset(0, 3).Value)
                    i = i + 1
                Else
                    exitLoop = True
                End If
            Loop
        End If
    End Sub
    

    Note: in the declarations, you had:

    Dim aCell, bCell as Range
    

    Which is the same as:

    Dim aCell as Variant, bCell as Range
    

    Some test code to demonstrate the above:

    Sub testTypes()
    
        Dim a, b As Integer
        Debug.Print VarType(a)
        Debug.Print VarType(b)
    
    End Sub