Passing a VBA array to a formula


I have two rows of data looking like this:


I am trying to return all the position numbers for each ID in an array. I have tried


But it fails whenever the ID I am searching for is not the first in column A. (I did try to sort column A with no luck).

So I have come up with this workaround: instead I would use this formula


where positions is a VBA function that return an array of rows that match specified ID. The function positions is coded so that it return a Variant. But it seems that the VBA Array is not passing to the formula in excel. When I evaluate the formula, positions(E2) is equal to 0. (I have checked in VBA, and my array is correctly populated).

So how do I make my formula correctly interpret the VBA array?

UPDATE: Here is my code:

Function positions(idrange As Range) As Variant
Dim V As Variant
Dim l, nb As Integer
Dim id As Double

nb = 4
ReDim V(nb) As Variant

id = idrange.Value
Set cible = Sheet2.Range("B1")
For l = 1 To nb
    Set cible = Sheet2.Columns(2).Find(What:=id, After:=cible, _

    V(l) = cible.Row - 1   
Next l
positions = Application.Transpose(V)

End Function

UPDATE 2: Here is the desired output

enter image description here

Show source
| excel-vba   | vba   | excel   | arrays   2017-01-05 18:01 2 Answers

Answers ( 2 )

  1. 2017-01-05 19:01

    Put this array formula in F2:


    Confirm with Ctrl-Shift-Enter instead of Enter. If done correctly then Excel will put {} around the formula.

    Then copy over and down sufficient to cover all the data.

    enter image description here

    EDIT #1

    If you can sort the data then you can avoid the array formula and use this normal formula:

    =IF(COLUMN(A:A) <= COUNTIF($A:$A,$E2),INDEX($B:$B,MATCH($E2,$A:$A,0)+COLUMN(A:A)-1),"")

    enter image description here

  2. 2017-01-06 02:01

    Drawing on Is it possible to fill an array with row numbers which match a certain criteria without looping?, you can do this with array and VBA as so:

    1. This line Filter(Application.Transpose(Application.Evaluate("=IF(A2:A100=OFFSET(E2," & lngCnt - 1 & ",0), (B2:B100),""x"")")), "x", False) returns a string of the matching B values

    "1","4","7","10" for A2

    1. This line [e2].Offset(lngCnt - 1, 1).Resize(1, UBound(x) + 1) = Split(Join(x, "|"), "|") puts the string to each array


    Sub GetEm()
    Dim lngCnt As Long
    'range of your codes from E2 down
    y = [E2:E4]
    For lngCnt = 1 To UBound(y)
         x = Filter(Application.Transpose(Application.Evaluate("=IF(A2:A100=OFFSET(E2," & lngCnt - 1 & ",0), (B2:B100),""x"")")), "x", False)
        [e2].Offset(lngCnt - 1, 1).Resize(1, UBound(x) + 1) = Split(Join(x, "|"), "|")
    End Sub

    enter image description here

◀ Go back