0

我正在尝试使用 Application.match 查找范围 A1:Z1 和 A2:Z2 中的值匹配的列。例如,第一行包含不同的水果名称,第二行包含颜色。所以,假设我正在寻找一个带有蓝色香蕉的列,这样的事情应该可以工作:

 mycolumn = Application.Match("Banana" & "Blue", Worksheet("Coloured_Fruit").Range(A1:Z1) & Worksheet("Coloured Fruit").Range(A2:Z2), 0)

为了匹配以下数据表中的蓝色香蕉:

 A1:banana B1:apple C1:banana D1:orange
 A2:green  B2:blue  C2:blue   D2:green

这应该返回 C,因为 C 列是代表蓝色香蕉的列。

但我得到类型不匹配。这些范围与进行匹配的代码位于不同的工作表上。当我只尝试匹配一行而不是两行时,这很好用。网络搜索表明上述行应该有效。

我试过在表达式上使用 Evaluate,但这也不起作用。

任何建议如何做到这一点?

4

1 回答 1

1

代码中的 MATCH 失败,因为“&”运算符仅适用于 VBA 中的字符串。在 Excel 工作表中,如果“&”作为数组公式的一部分输入,则可以连接范围。

对 MATCH 公式的修改似乎应该在 VBA 中工作,也会返回“类型不匹配”错误。这些包括通过将两个范围分配给单个范围变量 (Range("A1:Z1","A2:Z2")) 或使用 UNION 函数( Union("A1:Z1","A2:Z2 ") ) 出于同样的目的。用“.Value”限定其中任何一个也无济于事。

以下代码可以解决问题:

  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

专注于 MATCH 表达式(并去掉 EVALUATE 函数所需的额外双引号),

  • ( nRng1 = "Banana" )( nRng2 = "Blue" )是命名范围内容和两个目标字符串的数组比较。

    每个都解析为一个布尔数组 {FALSE, FALSE, ..., TRUE, etc.},在包含目标字符串的每个单元格范围内的相对位置中具有 TRUE。

  • 双破折号,即"--( nRng1 = "Banana" )将每个布尔数组中的 FALSE 和 TRUE 值强制为零和一。

  • 然后将这两个数组相乘--( nRng1 = "Banana" ) * --( nRng2 = "Blue" ),生成一个数组,其中“Banana”和“Blue”都存在的位置为 1,并且为零别处。

    请注意,使用这种方法,比较不必仅限于两个。

  • 然后使用 MATCH 函数MATCH( 1, --( nRng1 = "Banana" ) * --( nRng2 = "Blue" ), 0 )来查找零和一数组中第一个 1 的相对位置.

    MATCH 公式中的最后一个 0 指定匹配是精确匹配。

  • 由于如果没有找到匹配项, MATCH 将返回错误,因此 IFERROR 会捕获错误,并返回零。

  • 最后,最终结果——匹配的列位置,如果找到一个,否则为 0——分配给mycolumn

由于子例程返回单个值,您可能需要考虑将其重新转换为 VBA 函数。

于 2013-01-19T03:20:55.743 回答