【问题标题】:Three Dimensional Lookup Using INDEX/MATCH使用 INDEX/MATCH 进行三维查找
【发布时间】:2016-09-30 14:45:23
【问题描述】:

这是从已被删除的问题中提取和改进的

对于那些可以看到已删除帖子的人,它来自这里:https://stackoverflow.com/questions/39793322/three-dimensional-lookup-no-concatenate-or-named-ranges-excel


我正在尝试在没有命名范围或连接的情况下进行三维查找。简而言之,我的数据在表格上:

    Column1 Column2 Column3
Scott           
P   1       2       3
M   4       5       6
N   7       8       9
George          
P   10      11      12
M   13      14      15
N   16      17      18

我现在想搜索特定名称,然后在该名称表中搜索特定字母,然后我想将此行号与特定列匹配。

我尝试了一个简单的 INDEX/MATCH:

=INDEX(A:D,MATCH("M",A:A,0),MATCH("Column1",1:1,0))

这适用于第一个名称,但不适用于其他名称,因为它会找到M 的第一个实例。

如何修改它以查找不同的名称?


我已经在下面回答了,但想看看有人有更好的解决方案。

【问题讨论】:

  • 这取决于数据输入的可能性。如果 P、M、N 并不总是字母(可能更多等)。空格也只出现在有名字的行上吗?
  • 正如您从当前答案中看到的那样,已经做出了这些假设。我的回答假设它可以按任何顺序排列。唯一需要注意的是数据集的大小为 4。这需要更改为最大的数据集以最小化误报。我正在寻找我们是否可以在没有任何警告的情况下做到这一点。当前的所有答案都有某种限制。 @MacroMarc

标签: excel excel-formula


【解决方案1】:

我使用IF() 语句array 公式来查找P 行号在George 行之后...我还需要使用MIN() 函数来获取第一个P名称后的行号。

除此之外,它是一个简单的INDEX() 函数....让我绞尽脑汁一个多小时:)。

=INDEX($A$1:$D$9,MIN(IF((ROW(A1:A9)>MATCH($F$4,A1:A9,0))*(A1:A9=$F$5),ROW(A1:A9),"")),MATCH($F$6,$A$1:$D$1,0))

别忘了!
完成公式时使用Ctrl+Shift+Enter,因此它被评估为array 公式。

【讨论】:

    【解决方案2】:

    您可以在第一个 MATCH 中使用另外两个 INDEX/MATCH 来设置查找范围。然后只需添加 MATCH() 即可找到名称的绝对位置。

    =INDEX(A:D,MATCH($H$4,INDEX(A:A,MATCH($H$3,A:A,0)):INDEX(A:A,MATCH($H$3,A:A,0)+4),0)+MATCH($H$3,A:A,0)-1,MATCH($H$5,$1:$1,0))
    


    这个效果更好,没有尺寸限制:

    =INDEX(A:D,MATCH(F4,INDEX(A:A,MATCH(F3,A:A,0)):A1040000,0)+MATCH(F3,A:A,0)-1,MATCH(F5,A1:D1,0))
    

    【讨论】:

      【解决方案3】:

      您只需将两个匹配的结果相加即可。一个匹配的名称加上一个匹配的字母等于总行数。

      =INDEX(A:D,MATCH(G5,A3:A5,0)+MATCH(G3,A:A,0),MATCH(G4,1:1,0))

      换句话说:索引(所有数据,匹配(名称,名称列,精确)+匹配(字母,字母列,精确),匹配(列名,列行,精确)

      Screen capture of working sheet

      【讨论】:

      • 如果字母以严格的一致性出现在每个名称之后,那么简单且非常好。对于严格一致的情况,这可能是最好的主意。但在问题的 cmets 中,Scott Craner 试图为更一般的情况找到公式结构,对数据输入的警告或假设最少。显然,数据集必须有某种结构,但我认为我们不应该将其限制为完全相同的四个字母以相同的确切顺序。
      【解决方案4】:

      我的回答尝试了一般情况,但只有一个警告:

      一个字母是单字符的文本,而一个名字是多于1个字符的。否则我觉得字母和名字在逻辑上没有区别,那就不可能真正做到.. .

      重新编辑以获得更好的功能构造:

      {=INDEX($A$1:$D$17, MATCH($H$3,$A1:$A17, 0)+MATCH($H$4, INDEX($A1:$A17, MATCH($H$3,$A1:$A17, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A1:$A17, 0)+POWER(SQRT(IF(LEN($A$1:$A$17)>1, ROW($A$1:$A$17), 0)-MATCH($H$3,$A$1:$A$17, 0)), 2)-1, ROWS($A$1:$A$17)), 2)), 0)-1, MATCH($H$5, $A$1:$D$1, 0))}
      

      这使用沿 A 列的数组公式,并检查长度是否 > 1 并将行 nums 放入数组中,其中字母为 0。

      然后从每个匹配行中减去唯一名称(例如 George)。

      然后我们使用最小值(在所有其他名称行中,最后一个数据行作为最终默认值 - 带有 2 个参数的 SMALL 函数)来查找下一个名称行(如果没有后续名称,则为最后一个数据行)。

      其余是标准索引/匹配等。

      如果所选名称下没有这样的字母,它将正确返回#N/A...

      我的数据集是 A1:A17,公式每次都可以用 A:A 代替,但是 IF 中的数组 calc 需要 A1:A17 来提高速度。

      编辑以获得更好的功能构造:

      如果我们想避免在数据长度发生变化时编辑公式,那么我们可以让 A:A 的完整列引用遍历整个构造(并降低速度/效率),并通过 ROWS 计算 colA 中的最后一个数据行(A:A):

      重新编辑:

      {=INDEX($A:$D, MATCH($H$3,$A:$A, 0)+MATCH($H$4, INDEX($A:$A, MATCH($H$3,$A:$A, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A:$A, 0)+POWER(SQRT(IF(LEN($A:$A)>1, ROW($A:$A), 0)-MATCH($H$3,$A:$A, 0)), 2)-1, ROWS($A:$A)), 2)), 0)-1, MATCH($H$5,1:1, 0))}
      

      这真的取决于设置...

      再次编辑以空格作为名称分隔符的版本

      如果您想使用空格作为名称的分隔符,其中数据结果中没有空格,但空格出现在有名称的 B 到 D 列中,则上述公式中的微小变化将导致:

      =INDEX($A$1:$D$17, MATCH($H$3,$A$1:$A$17, 0)+MATCH($H$4, INDEX($A:$A, MATCH($H$3,$A:$A, 0)):INDEX($A:$A, SMALL(IFERROR(MATCH($H$3,$A:$A, 0)+POWER(SQRT(IF($B$1:$B$17="", ROW($A$1:$A$17), 0)-MATCH($H$3,$A$1:$A$17, 0)), 2)-1, ROWS($A$1:$A$17)), 2)), 0)-1, MATCH($H$5, $A$1:$D$1, 0))

      这意味着名称和字母不必是任何指定的长度,但只有一个条件是在名称所在的行中出现空格。

      对条件的小修改,通过将 SQRT(IF(LEN($A$1:$A$17)>1, 替换为:

      SQRT(IF($B$1:$B$17="",

      【讨论】:

        【解决方案5】:

        我会使用 Index() 的面积(第 4 个参数)。下面是测试数据的截图。此示例假定相同的列和键已排序且一致。

        这通过使用 (Range1,Range2) 作为索引的第一个参数来工作。 index的第4个参数,用N表示你希望Index返回的()中的哪个区域。

        【讨论】:

        • 如果区域已知且区域很少,这是一个不错的选择。我的猜测是会有多个名称,因此为每个名称添加区域并计算区域以获得正确的名称可能会很乏味,而且公式很长。
        • 命名范围可以提供帮助,但它们只能做到这一点。另外,我们必须记住现实世界中所有符合要求的事物的实用性(我们可以做梦吗?)。
        【解决方案6】:

        我认为这可能会稍微整洁一些,并且可能更容易修改。

        =INDEX(OFFSET(INDIRECT("A"&MATCH($H$3,$A:$A,0),TRUE),0,0,4,4),MATCH($H$4,$A:$A,0),MATCH(H5,$1:$1,0))
        

        首先使用偏移量创建范围,我们可以使用 H3 中的名称来设置它,然后我们只是在该新范围内建立索引。

        现在这仍然取决于留在 A 列中的名称。

        【讨论】:

        • 是的,但我倾向于远离 OFFSET 和 INDIRECT,因为它是一个不稳定的函数。在这种情况下,它只是一个,这没什么大不了的,但是一个充满易变函数的页面会减慢计算时间。
        • 另外,由于名字在第 2 行而不是第 1 行,您需要对第一个匹配项 -1 进行调整,否则会显示错误的数字。 =INDEX(OFFSET(INDIRECT("A"&MATCH($H$3,$A:$A,0),TRUE),0,0,4,4),MATCH($H$4,$A:$A,0)-1,MATCH(H5,$1:$1,0))
        • 更整洁,更容易修改......也许,但你也涉及到 volatile 函数。
        • 嗯,有道理。是否有我可以参考的 volatile 函数列表,或者用于记住哪些是 volatile 的经验法则?
        【解决方案7】:

        假设数据的格式始终为Name,然后是PMN,则此公式有效:

        =INDEX($A:$D,
        MATCH($H$3,$A:$A,0)
        +LOOKUP($H$4,{"P",1;"M",2;"N",3}),
        MATCH($H$5,$1:$1,0))
        

        【讨论】:

          【解决方案8】:

          此解决方案几乎适用于所有条件。我发现的一个限制是,当一个主题 (Names) 没有任何细节(字母)的数据时,但到目前为止,所有其他答案都会出现同样的情况。

          公式假设数据位于B6:F30(以确保无论源范围位置如何都可以应用它)。

          公式使用 Index\Match 函数:

          首先,一个 MATCH 来检索Name 的位置:

          MATCH($H8,$B$6:$B$30,0)
          

          使用该信息,它使用 INDEX 构建一个范围,该范围用于使用第二个 MATCH 函数获取Detail(字母)的位置:

          + MATCH($I8,INDEX($B$6:$B$30, 1 + MATCH($H8,$B$6:$B$30,0))
          :INDEX($B$6:$B$30,ROWS($B$6:$B$30)),0),
          

          将第一个和第二个 MATCH 函数的结果相加得到Name`Detail` 组合的位置,并将其用于整个数据的索引中。需要的Data Column的位置是通过Match获得的:

          INDEX($B$6:$F$30, 1st.MATCH + 2nd.MATCH,
          MATCH(J$6,$B$6:$F$6,0))
          

          结果位于G6:L30,在J8 中输入此公式,然后复制到J8:L30

          = INDEX( $B$6:$F$30,
          MATCH( $H8, $B$6:$B$30, 0)
          +MATCH( $I8, INDEX( $B$6:$B$30 , 1 + MATCH( $H8, $B$6:$B$30 ,0))
          : INDEX( $B$6:$B$30, ROWS($B$6:$B$30) ),0),
          MATCH( J$6, $B$6:$F$6, 0)),"")
          

          【讨论】:

          • 同样,这只有在所有细节都相同的情况下才有效,是的,顺序无关紧要,但实际的细节才是。例如,从数据集中取出 George 的 Detail 2,突然 J8 将拉出第 16 行。它将返回误报。您的公式与我的非常相似,我将其限制为仅四行以减少误报。
          • "我发现的一个限制是,当其中一个主题(姓名)没有任何详细信息(字母)的数据时,但到目前为止,所有其他答案都发生了同样的情况。” - 如果名称没有字母(或任何字母),我的答案正确找到#N/A
          • @ScottCraner 这就是当其中一个主题(姓名)没有任何详细信息(字母)含义的数据时它不起作用的原因。
          • @ScottCraner 这个公式不像你发布的那个。要验证在这两种情况下只在数据之前插入一列(即列A)并且您发布的公式会产生不准确的结果,请插入三个并生成#REF!,而此答案中的公式将继续显示正确​​的结果(使用异常已经解释)。
          • @MacroMarc 抱歉,我不得不承认您的公式返回错误,但不幸的是,它仅在细节具有相同长度(在这种情况下为一个)的条件下才有效,这在现实生活中它不经常发生。此外,如果您在数据上方添加一行,您的公式就会变得不准确。
          【解决方案9】:

          此解决方案适用于迄今为止讨论的所有条件(如果有任何不适用的条件,请告诉我,我会尝试覆盖它)。 我将此作为单独的答案发布,因为先前答案中应用的公式正确地适用于其中所述的条件,因此它们将对具有这些特定场景的用户有用,因此他们不需要应用这些长公式。

          此公式假设数据位于B6:E30(以确保无论源范围位置如何都可以应用它)

          这个公式使用 Index\Match 函数,它是一个公式数组。

          FormulaArrays 输入按下 [Ctrl] + [Shift] + [Enter] 同时,你会看到 { } 如果输入正确,则在公式周围

          语法:

          =IFERROR(INDEX(DataRng,
          MATCH(Value1,NamesRng,0)
          +IFERROR(MATCH(Value2,INDEX(NamesRng,
          1+MATCH(Value1,NamesRng,0))
          :INDEX(NamesRng, IFERROR(MATCH(Value1,NamesRng,0)
          +MATCH("#",IF((INDEX(Col1Rng,1+MATCH(Value1,NamesRng,0))
          :INDEX(Col1Rng,ROWS(NamesRng)))="","#","!"),0),
          ROWS(NamesRng))),0),NA()),MATCH(ValCol,DataHdr,0)),"")
          

          参数: 假设数据位于 B6:E30。

          Value1= Name 可以在 Data 中找到,即 George、Scott 等。

          Value2= Detail 可在 Data 中找到,即 Detail1、Detalle2 等。

          ValCol = Column 可在数据中找到,即 Column1、Column2 等

          DataRng= $B$6:$E$30

          DataHdr= $B$6:$E$6

          NamesRng= $B$6:$B$30

          Col1Rng= $C$6:$C$30

          1st MATCH:检索名称的位置:

          MATCH(Value1,NamesRng,0)
          

          2nd MATCH:检索Name对应Details的结束位置,由C列中的空白值或数据范围的结束决定:

          MATCH("#",IF((INDEX(Col1Rng, 1 + 1stMATCH)
          :INDEX(Col1Rng,ROWS(NamesRng)))="","#","!"),0),
          

          构建一个范围 (vRange):使用第一个和第二个匹配函数包含名称的详细信息。如果 2nd Match 返回错误,则它使用数据范围的最后一行:

          INDEX(NamesRng, 1 + 1stMATCH )
          :INDEX(NamesRng, IFERROR( 1stMATCH + 2ndMATCH, ROWS(NamesRng)))
          

          3rd MATCH:检索Detail 在 vRange 中的位置。如果组合不存在,则返回 #NA

          IFERROR(MATCH(Value2, vRange,0), NA())
          

          将第1个和第3个匹配函数的结果相加得到Name`Detailcombination or#NAif no found. The Column index is obtained with a Match from the Header of the Data. It then applying the INDEX function to the Data Range returns the value of theName\Detail\Columncombination. If theName\Detail`组合的Row index没有找到它返回空白的。

          =IFERROR( INDEX( DataRng, 1stMATCH + 3rdMATCH, MATCH(Column,DataHdr,0)),"")
          

          将位于 H6:L37 的结果输入到 J8 中的公式数组,然后复制到 K8:L37 和 J9:L37:

          =IFERROR( INDEX($B$6:$E$30,
          MATCH($H8,$B$6:$B$30,0)
          +IFERROR( MATCH($I8, INDEX($B$6:$B$30,
          1+MATCH($H8,$B$6:$B$30,0))
          :INDEX($B$6:$B$30, IFERROR(MATCH($H8,$B$6:$B$30,0)
          +MATCH("#", IF((INDEX($C$6:$C$30,1+MATCH($H8,$B$6:$B$30,0))
          :INDEX($C$6:$C$30,ROWS($B$6:$B$30)))="","#","!"),0),
          ROWS($B$6:$B$30))),0),NA()),
          MATCH(J$6,$B$6:$E$6,0)), "")
          

          【讨论】:

            【解决方案10】:

            哇...已经有这么多解决方案了。

            我认为更简单的解决方案可能是使用偏移量来获得更通用的答案。

            =INDEX($A$1:$D$9, MATCH($G$3,OFFSET($A$1,MATCH($G$2,$A$1:$A$9,0),0,3,1),0)+MATCH($G$2,$A$1:$A$9,0), MATCH($G$4,$B$1:$D$1,0)+1)
            

            唯一要查找的变量是 3,它是存在的 M/N/P 选项的数量,因为这会影响行数。否则,该解决方案在所有可能的场景和不同的顺序下都能正常工作。

            【讨论】:

              【解决方案11】:

              当我有两个以上的数据搜索输入时,我更喜欢按图中所示组织数据,这样我就可以使用数据透视表并让它按照我喜欢的方式组织行和列中的数据。

              然后我使用GETPIVOTDATA 来搜索一个值。

              单元格G9 包含以下公式:

              =GETPIVOTDATA("Value";$F$3;"Name";G15;"Letter";G16;"Column";G17)

              【讨论】:

              • 如果可以重新排列数据,使用 SUMIFS 来获取数字会更简单:=SUMIFS(D:D,A:A,G15,B:B,G16,C:C,G17) 但挑战是在不改变数据结构的情况下做到这一点。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-03-27
              • 1970-01-01
              • 2019-09-27
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多