查找公式除了一列外,效果很好

时间:2013-12-11 16:21:14

标签: excel excel-formula vlookup array-formulas excel-indirect

我有一个已经上传的excel文件

http://www58.zippyshare.com/v/99974349/file.html

除了具有降序值的列之外,该公式效果很好。

=INDEX(
  INDIRECT("'"&LOOKUP(B5,TblA)&"'!A6:A36"),
   LOOKUP(9.99999999999999E+307,
    SEARCH("-"&C8&"-","-"&INDIRECT("'"&LOOKUP(B5,TblA)&"'!C6:C36")&"-"),
    ROW(C6:C36)-ROW(C6)+1))

让我解释一下excel文件。

我有一张主页'报告',另外4张相应于4个年龄组。 - 4.2.0至4.7.30,4.8.0至5.1.30,5.2.0至5.7.30和5.8.0至6.1.30。根据工作表“报告”中的年龄(B5),我选择4个工作表中的一个来从中选择值。我使用表名 TblA 选择正确的工作表,其中包含所有工作表名称,并在“报告”表中从A24到B27定义。

在上传的样本表中,B5包含值5.7,这意味着我们必须选择表5.2.0至5.7.30。

现在从表5.2.0到5.7.30,我必须为“报告”中输入的每个原始分数寻找相应的标准分数(第1列)。

以下是步骤:

一个。在工作表“报告”C7到C15中输入原始分数

B中。根据年龄(B5细胞)搜索相应的表格,在我们的情况下5.2.0至5.7.30,因为年龄为5.7

℃。通过选择4张表中的相应列,从原始分数中填充标准分数。例如,如果Col1的原始分数为25(C7),则选择Col1的标准分数从5.2.0到5.7.30并输入D7,依此类推。

d。这样,所有标准分数都填入D7到D15。

除了表单'Report'中的 D13 之外,该公式效果很好,因为如果您在5.2.0到5.7.30中观察到ColD,则它按降序排列。

如何更改公式以容纳此唯一列?

2 个答案:

答案 0 :(得分:2)

嗯,这不是导致错误的顺序,因为你没有任何结果!您使用的公式是尝试查找年龄表中根本找不到的-159-。你真的需要一些东西来查看范围,所以如果你有159,当你尝试匹配139-160时,它会返回一个肯定的结果。

我已经用较小的公式制作了一个公式,但是当组装时,重复单元使它变得令人生畏......而且,它是一个数组公式,所以你需要使用 Ctrl + Shift + 输入,使其按预期工作。您仍然可以拖动公式。

=INDEX(
    INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),
    IFERROR(
        MATCH(
            C7,
            INDEX(
                INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
                0,
                MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
            )*1,
            0
        ),
        MATCH(
            1,
            IF(
                1*LEFT(
                    INDEX(
                        INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
                        0,
                        MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
                    ),
                    FIND(
                        "-",
                        INDEX(
                            INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
                            0,
                            MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
                        )
                    )-1
                )<=C7,
                1,
                0
            )*
            IF(
                1*MID(
                    INDEX(
                        INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
                        0,
                        MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
                    ),
                    FIND(
                        "-",
                        INDEX(
                            INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
                            0,
                            MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
                        )
                    )+1,
                    100
                )>=C7,
                1,
                0
            )
            ,0
        )
    )
)

单行版本......

=INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),IFERROR(MATCH(C7,INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0))*1,0),MATCH(1,IF(1*LEFT(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))-1)<=C7,1,0)*IF(1*MID(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))+1,100)>=C7,1,0),0)))

您可以注意到有一些重复的块,即:

INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36")

对于工作表名称;

INDEX(
    INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),
    0,
    MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)

这是一个更大的块,使公式更灵活(它自动选择正确的列,例如,如果您将B8 Exclusion更改为Col1,公式将自动调整自己)

如果我拨打第一个Sheet和第二个Column,它会变得更短,也许更容易理解:

=INDEX(
    Sheet,
    IFERROR(
        MATCH(
            C7,
            Column*1,
            0
        ),
        MATCH(
            1,
            IF(
                1*LEFT(
                    Column,
                    FIND(
                        "-",
                        Column
                    )-1
                )<=C7,
                1,
                0
            )*
            IF(
                1*MID(
                    Column,
                    FIND(
                        "-",
                        Column
                    )+1,
                    100
                )>=C7,
                1,
                0
            )
            ,0
        )
    )
)

或者

=INDEX(Sheet,IFERROR(MATCH(C7,Column*1,0),MATCH(1,IF(1*LEFT(Column,FIND("-",Column)-1)<=C7,1,0)*IF(1*MID(Column,FIND("-",Column)+1,100)>=C7,1,0),0)))

免责声明:我不确定是否有任何方法可以让它更短,但我想只要它现在正在工作^^

您可以下载更新的表格here


说明:

正如我之前提到的,这个公式是基于几个较小的公式和相当多的重复公式。

INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36")

正如您已经知道的那样(它是您自己公式的一部分的变体),这给出了包含所有不同年龄的区域。使用它和下面的内容,我们得到了这个:

INDEX(
    INDIRECT('"&LOOKUP($B$5,TblA)&"'!B6:J36"),
    0,
    MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)
)

分为:

INDEX(
    'Sheet'!B6:J36,
    0,
    MATCH(B7,'Sheet'!B5:J5,0)
)

索引将调查范围'Sheet'!B6:J360表示它将占用任何列,MATCH(B7,'Sheet'!B5:J5,0)返回 n B7的值(如果是电子表格,Col1),并将其查看'Sheet'!B5:J5,其中1。因此,上面将返回范围'Sheet'!B6:B36。让我们把它放在公式中:

=INDEX(
    'Sheet'!A6:A36,
    IFERROR(
        MATCH(
            C7,
            'Sheet'!B6:B36*1,
            0
        ),
        MATCH(
            1,
            IF(
                1*LEFT(
                    'Sheet'!B6:B36,
                    FIND(
                        "-",
                        'Sheet'!B6:B36
                    )-1
                )<=C7,
                1,
                0
            )*
            IF(
                1*MID(
                    'Sheet'!B6:B36,
                    FIND(
                        "-",
                        'Sheet'!B6:B36
                    )+1,
                    100
                )>=C7,
                1,
                0
            )
            ,0
        )
    )
)

此公式本身就是一个巨大的INDEX公式,范围为'Sheet'!A6:A36,行号为大IFERROR组。首先评估IFERROR()的第一部分:

MATCH(
    C7,
    'Sheet'!B6:B36*1,
    0
)

这应该很容易理解。它会查找原始分数(从C7)到我们之前获得的范围,第1次将所有内容转换为数字(您无法查找数字和文本并期望匹配)。因此,如果数字完全匹配,它将返回找到的原始分数的行号并将其提供给INDEX()。例如,如果返回第一行,我们得到:

=INDEX('Sheet'!A6:A36,1)

哪个是'Sheet'!B6。但是,如果没有匹配(即无法找到原始分数),MATCH将返回错误。当IFERROR的第二部分发挥作用时,那就是:

MATCH(
    1,
    IF(
        1*LEFT(
            'Sheet'!B6:B36,
            FIND(
                "-",
                'Sheet'!B6:B36
            )-1
        )<=C7,
        1,
        0
    )*
    IF(
        1*MID(
            'Sheet'!B6:B36,
            FIND(
                "-",
                'Sheet'!B6:B36
            )+1,
            100
        )>=C7,
        1,
        0
    )
    ,0
)

MATCH尝试在1 s内找到IF;第一个是:

IF( 1*LEFT('Sheet'!B6:B36,FIND("-",'Sheet'!B6:B36)-1)<=C7 , 1 , 0)

FIND("-",'Sheet'!B6:B36)-1获取-列中'Sheet'!B6:B36之前的最后一个字符的位置。

使用这些值,此FIND将返回:

12-13       -> 2
145-155     -> 3
1567-1865   -> 4

IF因此变为:

IF( 1*LEFT('Sheet'!B6:B36,{2,3,4})<=C7 , 1 , 0)

注意这里的括号;它们表示一个数组,这就是为什么这是一个数组公式。 LEFT然后在-之前提取所有字符(请记住您的其他问题,我用与此非常类似的技巧回答):

12-13       -> 2  ->  12
145-155     -> 3  ->  145
1567-1865   -> 4  ->  1567

哪个是......

IF( 1*{12,145,1567}<=C7 , 1 , 0)

同样,1*将这些转换为实际数字,因为LEFT默认返回文本字符。这样做非常重要,因为我们要使用比较器<=,这样如果C7左边的值(原始分数),那么IF应该返回1,否则它应该返回0。让我们说原始分数为154。结果将是:

IF( {12,145,1567}<=154 , 1 , 0)
IF( {TRUE,TRUE,FALSE} , 1 , 0)
{1,1,0}

我刚才意识到公式可以缩短一点xD无论如何,我们稍后会看到。下一个IF的行为方式类似,但会检查-右侧的值:

IF( 1*MID('Sheet'!B6:B36,FIND("-",'Sheet'!B6:B36)+1,100)>=C7 , 1 , 0)

使用...                    找到MID(&#39; Sheet&#39;!B6:B36,X,100)     12-13 - &gt; 4 - &gt; 13     145-155 - &gt; 5 - &gt; 155     1567-1865 - &gt; 6 - &gt; 1865年

您可以注意到,如果此处有超过100个字符的内容,此公式将停止工作。无论如何,IF因此变成:

IF( {13,155,1865}>=154 , 1 , 0)
IF( {FALSE,TRUE,TRUE} , 1 , 0)
{0,1,1}

现在我们有了这些,之前的MATCH变为:

MATCH( 1 , {1,1,0}*{0,1,1} , 0)

一些简单的数学运算将其变为:

MATCH( 1 , {0,1,0} , 0)

1在那里的位置是什么?那是对的,位置2!

我们的原始公式变为:

=INDEX( 'Sheet'!A6:A36 , IFERROR( #Error! , 2 ) )

因此,如果一开始没有找到任何内容,则会返回错误(在这种情况下为#N/A),而是返回2=INDEX( 'Sheet'!A6:A36 , 2 )提供'Sheet'!A7


略微更短的版本是:

=INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!A6:A36"),IFERROR(MATCH(C7,INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0))*1,0),MATCH(1,(1*LEFT(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))-1)<=C7)*(1*MID(INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)),FIND("-",INDEX(INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B6:J36"),0,MATCH(B7,INDIRECT("'"&LOOKUP($B$5,TblA)&"'!B5:J5"),0)))+1,100)>=C7),0)))

我实际上删除了内部IF,因为(a>b)*(c>b)已经返回0和1,因为TRUE乘以TRUE得到1 in excel。

答案 1 :(得分:1)

在Excel 2007中,公式返回了许多循环引用警告,因此可能需要为Excel版本添加标记。我的是Excel 2007,但有了它你想要的结果似乎可以实现如下:

  1. 缩短公式并减少我在报告C5“表格”和D5 =VLOOKUP(B5,TblA,2,1)中添加的计算。
  2. 我还在5.2.0到5.7.30的ColumnH(“ColD”)右侧立即插入了一列,并在H列上应用了Text To Columns,并以-作为分隔符。
  3. 然后我申请报告E7并复制到E15:

    =INDEX(INDIRECT("'"&D$5&"'!A6:A36"),MATCH(C7,INDIRECT("'"&D$5&"'!"&CHAR(ROW()+59)&"6:"&CHAR(ROW()+59)&"36"),0))

    并将59 s调整为最后三行中的60 s。如果ColumnI向右移动得足够远,则无需进行此类调整。

  4. 在E13中,我将匹配从完全更改为下一个更高(最终0-1)。

  5. 对于数字,我作弊并将5.23中的K23从21-22更改为5.7.30至22,但对于其他列,此类条带可以与我对ColD的处理方式大致相同。