【问题标题】:Excel: using vlookup but with wildcards in the arrayExcel:使用 vlookup 但在数组中使用通配符
【发布时间】:2016-09-09 23:47:35
【问题描述】:

我在一张纸的一列中有一个值列表。在另一张纸上,我有两列。一个是通配符列表,另一个是另一个值列表。在第一张表上的列旁边,我想要一个额外的列包含一个公式,该公式将根据第二张表中的通配符检查第一列中的值。如果找到匹配项,则应在该通配符旁边显示该值。

有没有办法做到这一点?玩了几个小时,我无法让它工作。

提前致谢。

一些样本数据:

第一张

A栏

randomunnecessarydataUSEFULTHINGS123INFOmoregarbage

morerandomstuffIMPORTANT456junkjunkjunk

IMPORTANT456lotsofmorejunk

morejunkUSEFULTHINGS789INFO垃圾

B 栏

<some formula>

<some formula>

"

"

等等

第二张

A栏

*usefulthings???INFO*

*important456*

B 栏

有用的东西 - 信息

重要的 456

我希望<some formula> 对照工作表 2 中的表格检查工作表 1 列 A 中的值。如果工作表 2 列 A 中的通配符之一匹配,则包含公式的单元格应显示工作表 2 中的内容B 列。

【问题讨论】:

  • 一些数据会有所帮助。请模拟一些数据并使用编辑选项将其放入原始帖子中

标签: arrays excel wildcard vlookup


【解决方案1】:

如果我没听错,你想要这样的东西(在 B1 中然后复制下来):

=IF(MIN(IFERROR(MATCH(Sheet2!$A$1:$A$100,A1,0)*ROW($1:$100),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A$1:$A$100,A1,0)*ROW($1:$100),FALSE))),"")

这是一个数组公式,必须用ctrl+shift+enter确认。


左侧是带有查找项的工作表 1,右侧是带有通配符列表和值的工作表 2。

编辑
要自动调整范围,只需使用以下公式:

=IF(MIN(IFERROR(MATCH(Sheet2!$A$1:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE)),INDEX(Sheet2!B:B,MIN(IFERROR(MATCH(Sheet2!$A$1:INDEX(Sheet2!A:A,MATCH("zzz",Sheet2!A:A)),A1,0)*ROW(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE))),"")

是的,只有第一个值会被输出...如果你想获得多个值,你可以使用这个公式(像往常一样在 B1 然后向下复制,这次也是向左复制):

*² =IFERROR(IF(SMALL(IFERROR(MATCH(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A$1: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$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1),INDEX(Sheet2!$B:$B,SMALL(IFERROR(MATCH(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A)),$A1,0)*ROW(Sheet2!$A$1:INDEX(Sheet2!$A:$A,MATCH("zzz",Sheet2!$A:$A))),FALSE),COLUMN()-1)),""),""))

还要记住,所有公式都是数组公式;)

*² 如果对 B 列使用第一个 EDIT 公式,对 C+ 列使用 EDIT 2 公式,则不需要第二个 EDIT 公式。

编辑 3

对于 UDF 方式,请转到您的 VBA 编辑器(点击 alt+F11),然后点击“插入”->“模块”。然后放入这个模块的代码窗口:

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

现在您可以像使用其他工作表函数一样使用 UDF。详细解释一下。

getLikeLookup(lookup_string,lookup_range,[#_occurrence,[output_range]])
  • lookup_string:要检查的字符串(整个字符串,不能使用占位符)

  • lookup_range:此范围内最左侧的列将被检查为 like lookup_string。如果output_range 被省略,那么lookup_range 中最右边的列将用于输出。

  • #_occurrence:[可选] 指示要输出的匹配项。如果省略(如 1),则将选择第一个。

  • output_range:[可选]output_range 中的第一列将用于输出。

现在您可以使用的示例(从 B1 开始):

=getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1)

为了加快一点使用速度(仍然从 B1 开始):

=IF(A1="","",getLikeLookup($A1,Sheet2!$A:$B,COLUMN()-1))

这两个公式不是数组,只需点击 enter 即可确认。

【讨论】:

  • 让我测试一下。与此同时,有什么方法可以在没有 100 行限制的情况下做到这一点?
  • 另外我猜如果一个值匹配多个通配符,它​​会与列表中的第一个匹配?
  • 我不会完全反对在这里使用结构化引用以及表 2 中的数据是在带有标题的表格中
  • 对于A1:INDEX(A:A,MATCH("zzz",A:A)):partMATCH("zzz",A:A) 将返回包含文本的最后一行(将“zzz”更改为 1E+99 以获取最后一个数值)并且知道 INDEX 可以返回一个 REF A1:INDEX(...) 可以返回一个范围,在这种情况下,在 A1969 中具有最后一个值,然后 A1:INDEX(A:A,MATCH("zzz",A:A)) 会将 ref 返回到 A1:A1969(就像您直接输入它一样)...我将添加一个 UDF-很快;)
  • 应该使用命名范围(也可以是表和其他任何东西,只要返回的是一个范围而不是数组)。 column()-1 用于获取计数。在 B 列中,它将是 2-1 (1),因此第一个匹配项将用于 b 列,在 C 列中,它将是 3-1 (2),因此将使用第二个匹配项 D = 3 / E = 4 等. 因此,如果第一个匹配项在 D 列中,第二个在 E 列中等等,那么它将是column()-3。 ;)
猜你喜欢
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多