如何为多变量索引匹配公式创建 UDF

Posted

技术标签:

【中文标题】如何为多变量索引匹配公式创建 UDF【英文标题】:How to create UDF for multi-variable Index Match formula 【发布时间】:2019-09-06 18:25:48 【问题描述】:

我想为以下 Excel 索引匹配公式创建一个 UDF:

=INDEX($A$1:$J$7,MATCH(B9,$A$1:$A$7,0),MATCH(1,($A$1:$J$1=B10)*($A$2:$J$2=B11),0))

enter image description here

    AA  AA  AA  BB  BB  BB  CC  CC  CC
    a   b   c   a   b   c   a   b   c
1   10  55  24  48  95  19  5   28  65
2   16  48  3   62  46  50  59  80  17
3   63  47  19  23  67  26  14  16  9
4   55  91  4   55  72  79  27  39  50
5   75  53  7   42  45  19  58  41  12

Condition1  3                               
Condition2  AA                              
Condition3  c                               

index-Match 19  =INDEX($A$1:$J$7,MATCH(B9,$A$1:$A$7,0),MATCH(1,($A$1:$J$1=B10)*($A$2:$J$2=B11),0))                         

注意:CTRL + SHIFT + ENTER 在 excel 中返​​回数组结果

这在 excel 工作表中有效,但是当我尝试将其转换为 VBA 时,出现错误。

我认为我需要在以下代码中的某处应用 FormulaArray,非常感谢任何帮助。

我尝试了以下代码,但得到了#VALUE!

Public Function UDF_IndexMatch(Condition1, Condition2, COndition3)
    UDF_IndexMatch = Application.WorksheetFunction.Index(Range("$A$1:$J$7"), _
                                                  Application.WorksheetFunction.Match(Condition1, Range("$A$1:$A$7"), 0), _ 
                                                 Application.WorksheetFunction.Match(1, (Range("$A$1:$J$1") = Condition2) * (Range("$A$2:$J$2") = COndition3), 0))

End Function

最终结果应该是这样的:

= UDF_IndexMatch(Condition1, Condition2, COndition3) 

return:对应的索引匹配结果

【问题讨论】:

总是"$A$1:$J$7" 还是您也需要用户设置范围的能力? @ScottCraner 最终我将为表格/范围选择创建另一个参数,但现在只是为了让公式正常工作,“$A$1:$J$7”很好。 【参考方案1】:

起初我误读了您的帖子,并认为使用标准公式会更好,但是您专门寻找 UDF。只是为了提供其他选择,这里有一个:

Public Function ReturnVal(RNG As Range, Con1, Con2, Con3) As String
Dim SearchRng1 As String, SearchRng2 As String, SearchRng3 As String, SearchRng4 As String

With ActiveWorkbook.Sheets(RNG.Parent.Name)
    SearchRng1 = RNG.Parent.Name & "!" & RNG.Range(.Cells(3, 2), .Cells(RNG.Rows.Count, RNG.Columns.Count)).Address(False, False)
    SearchRng2 = RNG.Parent.Name & "!" & RNG.Range(.Cells(3, 1), .Cells(RNG.Rows.Count, 1)).Address(False, False)
    SearchRng3 = RNG.Parent.Name & "!" & RNG.Range(.Cells(1, 2), .Cells(1, RNG.Columns.Count)).Address(False, False)
    SearchRng4 = RNG.Parent.Name & "!" & RNG.Range(.Cells(2, 2), .Cells(2, RNG.Columns.Count)).Address(False, False)
End With
ReturnVal = Evaluate("=INDEX(" & SearchRng1 & ",MATCH(" & Con1 & "," & SearchRng2 & ",0),MATCH(""" & Con2 & """&""" & Con3 & """," & SearchRng3 & "&" & SearchRng4 & ",0))")

End Function

只要选择变量的范围,表格的位置或大小都没有关系。您也可以从另一个工作表中调用它。

【讨论】:

谢谢@JvdV 这效果很好,我唯一改变的是 Dim SearchRng4 As String 而不是 Double。 是的,那是我的错,应该是字符串 当从工作簿中的不同工作表中选择 RNG 时,您是否有任何建议可以使此 UDF 工作? @SteveC,请参阅我在编辑后的答案中使用Parent.Name 属性的建议。 感谢您的帮助。出于某种原因,您的代码对我不起作用,但我对其进行了一些更新,现在它可以按照我的意愿完美运行。谢谢!【参考方案2】:

您可以将数据保存在变量数组中并对其进行迭代:

Public Function UDF_IndexMatch(Condition1, Condition2, COndition3)
    Application.Volatile

    Dim rngarr As Variant
    rngarr = Application.Caller.Parent.Range("A1:J7").Value

    Dim irow As Long
    irow = 0

    Dim i As Long
    For i = LBound(rngarr, 1) To UBound(rngarr, 1)
        If rngarr(i, 1) = Condition1 Then
            irow = i
            Exit For
        End If
    Next i

    Dim jcolumn As Long
    jcolumn = 0

    If irow > 0 Then
        Dim j As Long
        For j = LBound(rngarr, 2) To UBound(rngarr, 2)
            If rngarr(1, j) = Condition2 And rngarr(2, j) = COndition3 Then
                jcolumn = j
            End If
        Next j
    End If

    If j > 0 Then

        UDF_IndexMatch = rngarr(irow, jcolumn)
    End If
End Function

【讨论】:

我希望有一种方法可以在不遍历数组的情况下做到这一点,但这很好用,非常感谢。 @ScottCraner 不要忘记将其设为 Volatile - 它引用不属于参数的数据

以上是关于如何为多变量索引匹配公式创建 UDF的主要内容,如果未能解决你的问题,请参考以下文章

使用索引/匹配的 Excel 公式

VBA替换索引匹配公式

如何为具有不同公式的多个 glm 调用仅加载一次数据?

Excel 技术篇 - 利用Match公式返回匹配的最后一个数据的索引

在每个单元格 Excel 中使用 VBA 而不是使用公式(索引和匹配)

如何为以下示例创建自定义格式、公式或 VBA 代码?