The MATCH in your code fails because the "&" operator only works on strings in VBA. In Excel worksheets, an "&" can join ranges if it is entered as part of an array formula.
Modifications to the MATCH formula that seem like they should work in VBA also return a "Type Mismatch" error. These include putting the two ranges together by assigning them to a single Range variable (Range("A1:Z1","A2:Z2")), or using the UNION function ( Union("A1:Z1","A2:Z2") ) for the same purpose. Qualifying either of those with ".Value" does not help, either.
The following code does the trick:
Sub matchit()
Dim mycolumn As Long
Dim oRng1 As Range, oRng2 As Range
With ThisWorkbook.Sheets("Coloured_Fruit")
Set oRng1 = .Range("A1:Z1")
Set oRng2 = .Range("A2:Z2")
.Names.Add Name:="nRng1", RefersTo:=oRng1
.Names.Add Name:="nRng2", RefersTo:=oRng2
mycolumn = Evaluate("IFERROR(MATCH(1,--(nRng1=""Banana"")*--(nRng2=""Blue""),0),0)")
.Names("nRng1").Delete
.Names("nRng2").Delete
End With
End Sub
Focusing on the MATCH expression (and stripping out the extra double-quotes needed for the EVALUATE function),
- ( nRng1 = "Banana" ) and ( nRng2 = "Blue" ) are arrays comparisons of the contents of the named ranges and the two target strings.
Each resolves to an array of booleans {FALSE, FALSE, ..., TRUE, etc.}, with a TRUE in the relative position in the range of each cell that contains the target string.
- The double-dashes, i.e., "--( nRng1 = "Banana" ) force the FALSE and TRUE values in each of the boolean arrays to zeroes and ones.
- The two arrays are then multiplied, --( nRng1 = "Banana" ) * --( nRng2 = "Blue" ), producing a single array with ones in the positions where both "Banana" and "Blue" are found, and zeroes elsewhere.
Note that using this approach the comparisons need not be limited to just two.
- The MATCH function is then used, MATCH( 1, --( nRng1 = "Banana" ) * --( nRng2 = "Blue" ), 0 ), to find the relative position of the first 1 in the array of zeroes and ones.
The final 0 in the MATCH formula specifies that the match be an exact one.
- Since MATCH will return an error if no match is found, IFERROR catches the error, returning zero in its stead.
- Finally, the end result - the column position of the match, if one is found, and 0 otherwise -- is assigned to mycolumn.
Since the subroutine returns a single value, you may want to consider recasting it as a VBA function.