Excel / VBA - 使用动态范围的索引匹配功能

时间:2013-04-23 18:36:27

标签: excel vba excel-formula excel-match

如何在VBA中有效使用Index/Match公式?

背景:我的工作表很大程度上依赖于使用公式来检索输出,该公式基于将特定名称与其名称范围匹配以及特定日期到其日期范围。

=INDEX(OutputRange,MATCH(1,(Name=NameRange)*(Date=DateRange),FALSE),1)

此外,还有一个硬编码的VBA子产生相同的输出

Sub ExampleHardCode() 
Dim Result As Variant
  Result = Evaluate("INDEX($C$4:$C$13,MATCH(1,($G$6=$A$4:$A$13)*($G8=$B$4:$B$13),FALSE),1)")
  ActiveCell.Value = Result
End Sub

问题:我想生成一个函数,它返回与上述选项相同的输出,但允许用户(i)通过引用相应的单元格选择Name和Date值,以及(ii)选择每个范围(名称范围) ,日期范围和输出范围)。在excel中基本上使用= examplefunction(名称值,名称范围,日期值,日期范围,输出范围)。

我尝试了许多不同的解决方案但没有成功。下面是我到目前为止尝试过的一个示例,我认为匹配部分存在问题,即使我尝试设置范围(使用硬编码范围)也会返回错误。

Function TestIndexMatch1(NameVal As Variant, DateVal As Date)

Dim NameRng As Range
Dim DateRng As Range
Dim OutputRng As Range
Dim Var1 As Variant  'should this be a range or integer?
Dim Result As Variant 

Set NameRng = Range("$A$4:$A$13")
Set DateRng = Range("$B$4:$B$13")
Set OutputRng = Range("$C$4:$D$13")

With Application.WorksheetFunction
    Var1 = .Match(1, (NameVal = NameRng) * (DateVal = DateRng), False)
    Result = .Index(OutputRng, Var1, 1)
End With
End Function

我有一个示例工作簿,如果它可以帮助我分享。我不确定这是否非常可行,但如果是这样,它确实能帮助很多不熟悉excel的用户正确使用索引/匹配excel公式。不幸的是,我的excel技能远远超过了我的VBA技能。

1 个答案:

答案 0 :(得分:2)

在VBA代码中使用数组公式将Application对象的ReferenceStyle设置为xlR1C1 (暂时,仅在执行函数期间)。最后调用Evaluate 以获取公式的结果。

Private Const TEMPLATE As String = "=INDEX({0},MATCH(1,({1}={2})*({3}={4}),{5}))"
Private Const MATCH_TYPE = 0

Public Function TestIndexMatch1(ByRef outputRange As Range, _
                                ByRef nameCriteria As Range, _
                                ByRef dateCriteria As Range, _
                                ByRef nameRange As Range, _
                                ByRef dateRange As Range)

    On Error GoTo Err_Handler
    Err.Number = 0

    Dim originalReferenceStyle
    originalReferenceStyle = Application.ReferenceStyle
    Application.ReferenceStyle = xlR1C1

    Dim myFormula As String
    myFormula = Replace(TEMPLATE, "{0}", outputRange.Address())
    myFormula = Replace(myFormula, "{1}", nameCriteria.Address())
    myFormula = Replace(myFormula, "{2}", nameRange.Address())
    myFormula = Replace(myFormula, "{3}", dateCriteria.Address())
    myFormula = Replace(myFormula, "{4}", dateRange.Address())
    myFormula = Replace(myFormula, "{5}", MATCH_TYPE)

    TestIndexMatch1 = Application.Evaluate(myFormula)

Err_Handler:
    If (Err.Number <> 0) Then MsgBox Err.Description
    Application.ReferenceStyle = originalReferenceStyle
End Function

所以它看起来就是这样:

enter image description here

enter image description here