【问题标题】:Index Match using VBA Function in Microsoft Excel在 Microsoft Excel 中使用 VBA 函数进行索引匹配
【发布时间】:2021-04-04 18:41:54
【问题描述】:

我是 Excel VBA 的新手,我正在尝试编写一个函数,让我可以使用 INDEXMATCHCOUNTIFS 函数通过匹配其他列(多个)中的条件来查找给定列的值。

我有一个名为 Price 的表,其中包含根据指定类别在不同位置提供的一些价格:

Area    Category    Cost    Retail Price    Wholesale Price
USA Bad 1   13  25
Canada  Okay    2   14  26
Mexico  Good    3   15  27
USA Excellent   4   16  28
Canada  Bad 5   17  29
Mexico  Okay    6   18  30
USA Good    7   19  31
Canada  Excellent   8   20  32
Mexico  Bad 9   21  33
USA Okay    10  22  34
Canada  Good    11  23  35
Mexico  Excellent   12  24  36

在 Excel 中,我可以使用数组公式来得到这个(参见视频示例 here)。下面的公式让我在Mexico 中获得Okay 类别的Wholesale Price

{=INDEX(Price,MATCH(1,COUNTIFS(L12,Price[Area],M12,Price[Category]),0),MATCH(N12,Price[#Headers],0))}

在哪里

L12 = Mexico
M12 = Okay 
N12 = Wholesale Price 

我想创建一个 VBA 函数ProdPrice,它可以返回这个值,而没有看起来凌乱的公式。这是我目前所拥有的:

Function ProdPrice(locs, cat, pricetype)
    
    'Get column number corresponding to selected "pricetype"
    col_num = WorksheetFunction.Match( _
                pricetype, _
                ActiveSheet.ListObjects("Price").HeaderRowRange.Select, _
                0)
                
    ProdPrice = WorksheetFunction.Index( _
                    ActiveSheet.ListObjects("Price"), _
                    WorksheetFunction.Match( _
                        1, _
                        WorksheetFunction.CountIfs( _
                            ActiveSheet.ListObjects("Price").ListColumns("Area").DataBodyRange.Select, _
                            locs, _
                            ActiveSheet.ListObjects("Price").ListColumns("Category").DataBodyRange.Select, _
                            cat), _
                        0), _
                    col_num)

End Function

为了提高可读性,我使用_ 将函数分成两个部分,而不是单个调用。

当我运行它时,我得到一个#VALUE! 输出。

关于如何解决这个问题有什么建议吗?同样据我了解,上述函数将在调用该函数的工作表中查找名为 price 的表 - 我希望它能够在工作簿中查看 price

【问题讨论】:

  • countifs 的第一个参数是一个范围
  • @RicardoDiaz 我更改了它,但仍然没有输出。我也做了一些addl。代码更改 - 立即更新帖子。
  • SUMIFS() 公式不能为您提供所需的结果吗?像=SUMIFS($N:$N,$L:$L,"Mexico",$M:$M,"Okay") 之类的东西(假设Wholesale PriceN 列中)
  • @kevin9999 不确定我是否关注 - 你能发布答案吗?我还需要确保category 匹配。
  • 我的评论假设countryL 列中,categoryM 列中,并且要求和的值在N 列中。尝试将建议的公式放在工作表上的备用单元格中,然后告诉我它返回的结果。

标签: excel vba indexing match countif


【解决方案1】:

我假设您的值始终在 Excel 结构化表格中

备注:

  • 函数不区分大小写
  • 表头和值不包含| 字符
  • 函数将返回第一个匹配值(areacategory
  • 列顺序无关

请阅读代码的 cmets 并根据您的需要进行调整

代码

Public Function lookupPrice(ByVal table As Range, ByVal lookup_area As String, ByVal lookup_category As String, ByVal pricetype_header As String) As Variant
    
    ' Define column headers
    Dim areaHeader As String
    Dim categoryHeader As String
    areaHeader = "Area"
    categoryHeader = "Category"
    
    ' Get area column number from headers
    Dim areaColumn As Long
    areaColumn = Application.Match(areaHeader, table.ListObject.HeaderRowRange, False)
    
    ' Get category column number from headers
    Dim categoryColumn As Long
    categoryColumn = Application.Match(categoryHeader, table.ListObject.HeaderRowRange, False)
    
    ' Get price column number from headers according to function parameter
    Dim priceColumn As Long
    priceColumn = Application.Match(pricetype_header, table.ListObject.HeaderRowRange, False)
    
    
    ' Get area column values into 1d array
    Dim areaValues As Variant
    areaValues = WorksheetFunction.Transpose(Application.Index(table.Columns(areaColumn), 0, 1))
    
    ' Get category column values into 1d array
    Dim categoryValues As Variant
    categoryValues = WorksheetFunction.Transpose(Application.Index(table.Columns(categoryColumn), 0, 1))
    
    ' Define and redimension an array to hold the concatenated area and category values
    Dim areaCategoryValues() As Variant
    ReDim areaCategoryValues(1 To UBound(areaValues))
    
    ' Concatenate the area and category values and store them in an array
    Dim counter As Long
    For counter = 1 To UBound(areaValues)
        areaCategoryValues(counter) = areaValues(counter) & "|" & categoryValues(counter)
    Next counter
    
    ' Get the matching row according to lookup values
    Dim resultRow As Long
    resultRow = Application.Match(lookup_area & "|" & lookup_category, areaCategoryValues, False)
    
    ' Get the result value according to the price column number
    Dim result As Variant
    result = Application.Index(table.Columns(priceColumn), resultRow)
    
    ' Return the value
    lookupPrice = result
    
End Function

让我知道它是否有效

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 2016-11-30
    • 2020-07-05
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多