Excel: 使用 vlookup 但在数组中使用通配符
Excel: using vlookup but with wildcards in the array
我在一个 sheet 的列中有一个值列表。在另一个 sheet 上,我有两列。一个是通配符列表,另一个是另一个值列表。在第一个 sheet 的列旁边,我想要一个额外的列来包含一个公式,该公式将根据第二个 sheet 中的通配符检查第一列中的值。如果找到匹配项,它应该显示该通配符旁边的值。
有什么办法吗?已经用了几个小时了,我无法让它工作。
提前致谢。
一些示例数据:
Sheet一个
A 列
随机不必要数据USEFULTHINGS123INFO更多垃圾
morerandomstuffIMPORTANT456junkjunkjunk
重要 456 很多垃圾
更多垃圾USEFULTHINGS789INFO垃圾
B 列
<some formula>
<some formula>
等等
Sheet两个
A 列
*usefulthings???INFO*
*important456*
B 列
有用的东西 - 信息
重要 456
我希望<some formula>
检查它旁边的sheet 1列A中的值与Sheet中的table 2.如果[=中的通配符之一=68=] 2 列 A 匹配,包含公式的单元格应显示 Sheet 2 列 B.
中的内容
如果我没看错你想要这样的东西(在 B1 中然后向下复制):
=IF(MIN(IFERROR(MATCH(Sheet2!$A:$A0,A1,0)*ROW(:0),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A:$A0,A1,0)*ROW(:0),FALSE))),"")
This is an array formula and must be confirmed with ctrl+shift+enter.
左边是带有查找项的 sheet1,右边是带有通配符列表和值的 sheet2。
编辑
要自动调整范围,只需使用以下公式:
=IF(MIN(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE))),"")
是的,只有第一个值会被输出...如果你想获得多个值,你可以使用这个公式(像往常一样在 B1 中然后向下复制,这次也向左复制):
*² =IFERROR(IF(SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1)),""),"")
但请记住,所有公式都会减慢您的 excel 越多的单元格使用它们(最后一个最多)。如果你的列表很长,我建议使用 UDF。
编辑 2
要再次加快速度,您可以对 C1 使用此公式(向下/向右复制)(仅对 B 列使用最后一个公式):
=IF(B1="","",IFERROR(IF(SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1)),""),""))
还要记住,所有公式都是数组公式 ;)
*² 如果对 B 列使用第一个 EDIT 公式,对 C+ 列使用 EDIT 2 公式,则不需要第二个 EDIT 公式。
编辑 3
对于 UDF 方式,转到您的 VBA-编辑器(点击 alt+F11)然后 "Insert" -> "Module"。然后为这个模块输入代码window:
Option Explicit
Public Function getLikeLookup(str As String, rng As Range, Optional nCou As Long, Optional outCol As Range) As String
'for not case sensitive
str = LCase(str)
'set ranges
If nCou < 1 Then nCou = 1
If outCol Is Nothing Then Set outCol = rng.Offset(, rng.Columns.Count - 1).Resize(, 1)
Set rng = Intersect(rng.Resize(, 1), rng.Parent.UsedRange.EntireRow)
Set outCol = Intersect(outCol.Resize(, 1), outCol.Parent.UsedRange.EntireRow)
'get check-array (will be faster than running the sheet directly)
Dim inArr As Variant
inArr = rng.Value
'run checks
Dim i As Long
For i = 1 To UBound(inArr)
'If str Like inArr(i, 1) Then nCou = nCou - 1
If str Like LCase(inArr(i, 1)) Then nCou = nCou - 1 'for not case sensitive
If nCou = 0 Then Exit For
Next
'check for valid output
If i > UBound(inArr) Or i > outCol.Rows.Count Then Exit Function
'set output
getLikeLookup = outCol.Offset(i - 1).Resize(1, 1).Value
End Function
现在您可以像使用其他工作sheet 函数一样使用您的 UDF。详细解释一下。
getLikeLookup(lookup_string,lookup_range,[#_occurrence,[output_range]])
lookup_string
:您要检查的字符串(整个字符串,不适用于占位符)
lookup_range
:该范围最左边的列将被检查为like lookup_string
。如果 output_range
被省略,那么 lookup_range
中最右边的列将用于输出。
#_occurrence
: [optional] 表示输出哪个匹配项。如果省略(如 1),则将选择第一个。
output_range
: [可选] output_range
中的第一列将用于输出。
现在您可以使用示例(从 B1 开始):
=getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1)
为了加快速度,使用(仍然从 B1 开始):
=IF(A1="","",getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1))
这 2 个公式不是数组,只需按 enter.
即可确认
我在一个 sheet 的列中有一个值列表。在另一个 sheet 上,我有两列。一个是通配符列表,另一个是另一个值列表。在第一个 sheet 的列旁边,我想要一个额外的列来包含一个公式,该公式将根据第二个 sheet 中的通配符检查第一列中的值。如果找到匹配项,它应该显示该通配符旁边的值。
有什么办法吗?已经用了几个小时了,我无法让它工作。
提前致谢。
一些示例数据:
Sheet一个
A 列
随机不必要数据USEFULTHINGS123INFO更多垃圾
morerandomstuffIMPORTANT456junkjunkjunk
重要 456 很多垃圾
更多垃圾USEFULTHINGS789INFO垃圾
B 列
<some formula>
<some formula>
等等
Sheet两个
A 列
*usefulthings???INFO*
*important456*
B 列
有用的东西 - 信息
重要 456
我希望<some formula>
检查它旁边的sheet 1列A中的值与Sheet中的table 2.如果[=中的通配符之一=68=] 2 列 A 匹配,包含公式的单元格应显示 Sheet 2 列 B.
如果我没看错你想要这样的东西(在 B1 中然后向下复制):
=IF(MIN(IFERROR(MATCH(Sheet2!$A:$A0,A1,0)*ROW(:0),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A:$A0,A1,0)*ROW(:0),FALSE))),"")
This is an array formula and must be confirmed with ctrl+shift+enter.
左边是带有查找项的 sheet1,右边是带有通配符列表和值的 sheet2。
编辑
要自动调整范围,只需使用以下公式:
=IF(MIN(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE))),"")
是的,只有第一个值会被输出...如果你想获得多个值,你可以使用这个公式(像往常一样在 B1 中然后向下复制,这次也向左复制):
*² =IFERROR(IF(SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1)),""),"")
但请记住,所有公式都会减慢您的 excel 越多的单元格使用它们(最后一个最多)。如果你的列表很长,我建议使用 UDF。
编辑 2
要再次加快速度,您可以对 C1 使用此公式(向下/向右复制)(仅对 B 列使用最后一个公式):
=IF(B1="","",IFERROR(IF(SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1)),""),""))
还要记住,所有公式都是数组公式 ;)
*² 如果对 B 列使用第一个 EDIT 公式,对 C+ 列使用 EDIT 2 公式,则不需要第二个 EDIT 公式。
编辑 3
对于 UDF 方式,转到您的 VBA-编辑器(点击 alt+F11)然后 "Insert" -> "Module"。然后为这个模块输入代码window:
Option Explicit
Public Function getLikeLookup(str As String, rng As Range, Optional nCou As Long, Optional outCol As Range) As String
'for not case sensitive
str = LCase(str)
'set ranges
If nCou < 1 Then nCou = 1
If outCol Is Nothing Then Set outCol = rng.Offset(, rng.Columns.Count - 1).Resize(, 1)
Set rng = Intersect(rng.Resize(, 1), rng.Parent.UsedRange.EntireRow)
Set outCol = Intersect(outCol.Resize(, 1), outCol.Parent.UsedRange.EntireRow)
'get check-array (will be faster than running the sheet directly)
Dim inArr As Variant
inArr = rng.Value
'run checks
Dim i As Long
For i = 1 To UBound(inArr)
'If str Like inArr(i, 1) Then nCou = nCou - 1
If str Like LCase(inArr(i, 1)) Then nCou = nCou - 1 'for not case sensitive
If nCou = 0 Then Exit For
Next
'check for valid output
If i > UBound(inArr) Or i > outCol.Rows.Count Then Exit Function
'set output
getLikeLookup = outCol.Offset(i - 1).Resize(1, 1).Value
End Function
现在您可以像使用其他工作sheet 函数一样使用您的 UDF。详细解释一下。
getLikeLookup(lookup_string,lookup_range,[#_occurrence,[output_range]])
lookup_string
:您要检查的字符串(整个字符串,不适用于占位符)lookup_range
:该范围最左边的列将被检查为likelookup_string
。如果output_range
被省略,那么lookup_range
中最右边的列将用于输出。#_occurrence
: [optional] 表示输出哪个匹配项。如果省略(如 1),则将选择第一个。output_range
: [可选]output_range
中的第一列将用于输出。
现在您可以使用示例(从 B1 开始):
=getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1)
为了加快速度,使用(仍然从 B1 开始):
=IF(A1="","",getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1))
这 2 个公式不是数组,只需按 enter.
即可确认