[英]Index Match using VBA Function in Microsoft Excel
I'm new to Excel VBA and am trying to write a function that lets me use INDEX
, MATCH
and COUNTIFS
functions to find value for a given column by matching criteria in other columns (multiple).我是 Excel VBA 的新手,我正在尝试编写一个 function 让我在其他列中使用INDEX
、 MATCH
和COUNTIFS
函数来查找多个匹配值。
I have a table named Price
which contains some prices offered in different locations based on an assigned category:我有一个名为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
In Excel I can use the an array formula to get this (see video example here ).在 Excel 中,我可以使用数组公式来获得它(请参见此处的视频示例)。 The below formula lets me get Wholesale Price
for Okay
category in Mexico
下面的公式让我得到Mexico
Okay
类别的Wholesale Price
{=INDEX(Price,MATCH(1,COUNTIFS(L12,Price[Area],M12,Price[Category]),0),MATCH(N12,Price[#Headers],0))}
Where在哪里
L12 = Mexico
M12 = Okay
N12 = Wholesale Price
I'd like to make a VBA function ProdPrice
that can return this value without a messy-looking formula.我想制作一个 VBA function ProdPrice
,它可以返回这个值,而没有一个看起来凌乱的公式。 Here's what I have so far:这是我到目前为止所拥有的:
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
Instead of a single call, I broke the function into two segments with _
for better readability.为了更好的可读性,我将_
分成两个部分,而不是单个调用。
When I run this I get a #VALUE!
当我运行它时,我得到一个#VALUE!
output. output。
Any suggestions on how I can go about this?关于我如何 go 对此有何建议? Also from what I understand, the above function will look for a table called price
in the worksheet where the function is called - I'd like for it to be able to look at price
in the workbook instead.同样据我了解,上述 function 将在工作表中查找名为price
的表,其中 function 被调用 - 我希望它能够在工作簿中查看price
。
I assume that your values are always in an Excel structured table我假设您的值始终在 Excel 结构化表中
Remarks:评论:
|
表头和值不包含|
character特点area
and category
) Function 将返回第一个匹配值( area
和category
)Please read code's comments and adjust it to fit your needs请阅读代码的注释并根据您的需要进行调整
Code代码
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
Let me know if it works让我知道它是否有效
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.