【问题标题】:Excel - Struggling with complex Index/Match/Match lookupExcel - 与复杂的索引/匹配/匹配查找作斗争
【发布时间】:2020-01-14 22:20:19
【问题描述】:

我有一个有 9 列和大约 6000 行的表。每行都有一个价格作为最后一列。其中一些价格应该是 0.00。

在另一个工作表中,我有大约 3700 行的“原始”表。我需要的价格在这些行中。但是,原始表格在行内水平显示价格,每个行旁边都有一个具有特定 gal 范围的单元格。基本上我的表格对于每个位置/加仑范围/价格组合都有唯一的行,原始的所有加仑范围/价格在单个位置行中顺序排列

例如,原始表中的一行如下所示:

... / 1-2000 / 2.8383 / 2001-4000 / 2.5382 / ...

在我的新表中,它们看起来像这样:

... / 1-2000 / 2.8383
... / 20001-4000 / 2.5382
etc

我的新表和原表中的所有内容都相同,除了 gal 范围和价格。

我要做的是使用数组多个条件索引/匹配(基于我的新表和原始表中的 3 个单元格)来查找行,找到与 gals 范围匹配的值,然后取那个 gal 范围单元格右侧的价格。

这是我试图在我的新表中获取值的行:

这是原始表中我需要的值的行:

下面是我构建的公式的详细介绍:

INDEX(old!$A$2:$Q$3755,MATCH(1,(A29=old!$A$2:$A$3755)*(F29=old!$F$2:$F$3755)*(G29=old!$G$2:$G3755),1),MATCH(H29,old!$J$2:$Q$3755,1)+1)

第一个标准索引/匹配部分效果很好...我索引表并匹配以查找行。如果我只是为 Col 输入一个数字(例如 1、2、3),它将完美地从相应的单元格返回值。但是,我似乎无法使 Col 匹配部分工作......我不断收到 REF 和 N/A 错误。

进行双向搜索有什么技巧吗?似乎只需在行中找到该值并在 if... 之后获取下一个单元格应该是一件简单的事情?

这里的一个问题是我正在寻找的 gal 范围值不是唯一的……至少有 20 个其他参考具有相同的范围(例如,“1-2000”)。有没有办法将 col 匹配限制为我通过行匹配找到的行?

非常感谢任何帮助。

谢谢, 瑞克

【问题讨论】:

  • 您使用了很多词,但仍然不清楚您的数据是什么样的。我从您的样本中看到的唯一区别是中间的三个点而不是末端。在真实的 Excel 网格中查看真实的数据样本将大有帮助。 DropBox 或 OneDrive 等无广告服务的屏幕截图或工作簿都可以使用。一个简化的例子,而不是你的整个工作簿。编辑问题。然后发表评论。不要在 cmets 中发布说明。
  • 对不起,我以为我的解释很透彻。不幸的是,共享原始数据是不可行的,因为它很敏感。基本上,我需要了解为什么在上面提供的索引匹配公式中,列号的匹配会失败。
  • 在 Index(match,match) 组合中,第二个匹配项标识列并且通常只在一行中查找,即标题行,在该行中找到并匹配列的标题。你给它整张桌子。这是故意的吗?
  • 是的,抱歉,Stack 修改了那些快速比较示例...第二个示例应该在不同的行(而不是在同一行,因为它们在原始行中)具有 gal 范围/价格。对于您的第二条评论,好吧,仅与第一行(标题)匹配的 col 将不起作用,因为我要查找的值可能在每行 5 个不同列中的任何一个中(例如,gal 范围可能是“ 1500-3000”,可能在第 7 列、第 9 列、第 11 列等)。我需要在 Index/Match 返回的行中查找 gal 范围值,然后在有意义的情况下获取它旁边的单元格中的值?

标签: excel indexing match


【解决方案1】:

这可以通过索引/匹配来完成,但你必须保持冷静。

我的截图供参考

单元格F7中的公式是

=INDEX(
INDEX(A2:A3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0))
  :INDEX(L2:L3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0)),
MATCH(E7,
     INDEX(A2:A3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0))
     :INDEX(L2:L3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0)),0)
+1)

解释一下:首先我们在 A 列上建立一个索引,找到三个值串联的行。这与联合运算符: 与列 L 上的索引相结合,使用相同的匹配。

此索引将返回从 A 列到 L 列的一行数据。然后将其用作另一个索引/匹配的范围参数,在该行数据中,匹配查找“g 值”并将 1 添加到将一个移动到找到的单元格的右侧。

请注意,您不希望在此公式中使用整列,因为计算起来会很慢。

【讨论】:

  • 感谢您的帮助!该解决方案似乎有点......复杂,并且在处理方面有点沉重?我的意思是,似乎应该更容易找到我正在寻找的值,因为我可以明确地使用多条件匹配函数来告诉我值所在的确切行......?我错过了什么吗?
  • 查找行号只是问题的一部分。由于您想在找到的行中进行搜索,因此您需要整个范围,而不仅仅是行号。索引/匹配肯定存在重复,但由于 Excel 工作表公式没有可重复使用的变量,因此无法解决。
  • 顺便说一句,这种方法的另一个问题是我不知道我需要的价格值在哪一列...您在特定价格列的公式中有 L2:L3 引用。但是,使用您的示例,我需要的价格可能是 H、J 或 L……这取决于 G 值(E7)的匹配位置。这里的根本问题实际上是我不知道哪一列可能具有该 G 值,以及在哪里寻找价格。我必须检测它...
  • 不,L 列只是范围的末尾。开头是 Index(A...):Index(L ...)
  • 明白了。无法让 sumproduct 正常工作,所以我决定返回并加强最初的间接解决方案。让它工作并且没有+1索引,看起来很完美!干得好,感谢您的帮助!
【解决方案2】:

解决这种情况的一种方法是使用#powerquery

请参阅此article,了解如何在您的 Excel 版本上使用 Power Query。它在 Excel 2010 Professional Plus 及更高版本中可用。我的演示使用的是 Excel 2016

步骤如下:

  1. 将旧数据加载/添加到 Power Query 编辑器。我的样本数据只有一行,但数千行都是一样的;

  1. 使用Transform 选项卡下的合并列 功能将前7 列与分隔符合并,例如分号;
  2. 对每对GALLONSTOTAL PRICES 重复合并列,并使用相同的分隔符;。如果你做得正确,你应该有如下的东西:

  1. 使用Transform 选项卡下的Unpivot Columns 功能取消旋转GALLONS;TOTAL PRICE 的所有合并列,然后删除Attribute 列;

  1. 使用Transform 标签下的Split Column 功能以分隔符; 分割每一列。如果你做得正确,你应该有如下的东西:

  1. 复制GALLONS 范围列的列(这是上面屏幕截图中的倒数第二列),然后用分隔符- 拆分原始GALLONS 范围列。那么你应该有:

  1. 根据需要重命名列标题;

  1. 关闭并加载新表到新工作表(默认情况下),或者您可以更改默认设置并为新表创建连接并将其加载到工作簿中的所需位置。

第二个表是输出表,你可以从这个新表中进行INDEX+MATCH,这应该比旧表容易得多。如果数据相同但结构不同,那么您可以直接使用输出表,而不必担心查找缺失的价格。

我已在我的源表中添加了一条测试行,这是通过单击按钮刷新输出:

这里是后台电源查询M码,仅供参考。所有步骤都使用编辑器的内置功能执行,非常简单。

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"IATA", Int64.Type}, {"ST", type text}, {"FUELER", type text}, {"UPDATED", type datetime}, {"RESTRICTIONS", type text}, {"BASEF UEL", type text}, {"NOTES", type any}, {"GALLONS1", type text}, {"TOTAL PRICES1", type text}, {"GALLONS2", type text}, {"TOTAL PRICES2", type text}, {"GALLONS3", type text}, {"TOTAL PRICES3", type text}, {"GALLONS4", type text}, {"TOTAL PRICES4", type text}, {"GALLONS5", type text}, {"TOTAL PRICES5", type text}}),
    #"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Changed Type", {{"IATA", type text}, {"UPDATED", type text}, {"NOTES", type text}}, "en-AU"),{"IATA", "ST", "FUELER", "UPDATED", "RESTRICTIONS", "BASEF UEL", "NOTES"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged"),
    #"Merged Columns1" = Table.CombineColumns(#"Merged Columns",{"GALLONS1", "TOTAL PRICES1"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.1"),
    #"Merged Columns2" = Table.CombineColumns(#"Merged Columns1",{"GALLONS2", "TOTAL PRICES2"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.2"),
    #"Merged Columns3" = Table.CombineColumns(#"Merged Columns2",{"GALLONS3", "TOTAL PRICES3"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.3"),
    #"Merged Columns4" = Table.CombineColumns(#"Merged Columns3",{"GALLONS4", "TOTAL PRICES4"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.4"),
    #"Merged Columns5" = Table.CombineColumns(#"Merged Columns4",{"GALLONS5", "TOTAL PRICES5"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.5"),
    #"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Merged Columns5", {"Merged"}, "Attribute", "Value"),
    #"Removed Columns" = Table.RemoveColumns(#"Unpivoted Columns",{"Attribute"}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Removed Columns", "Merged", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Merged.1", "Merged.2", "Merged.3", "Merged.4", "Merged.5", "Merged.6", "Merged.7"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Merged.1", Int64.Type}, {"Merged.2", type text}, {"Merged.3", type text}, {"Merged.4", type datetime}, {"Merged.5", type text}, {"Merged.6", type text}, {"Merged.7", type text}}),
    #"Split Column by Delimiter1" = Table.SplitColumn(#"Changed Type1", "Value", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Value.1", "Value.2"}),
    #"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Delimiter1",{{"Value.1", type text}, {"Value.2", type text}}),
    #"Duplicated Column" = Table.DuplicateColumn(#"Changed Type2", "Value.1", "Value.1 - Copy"),
    #"Reordered Columns" = Table.ReorderColumns(#"Duplicated Column",{"Merged.1", "Merged.2", "Merged.3", "Merged.4", "Merged.5", "Merged.6", "Merged.7", "Value.1 - Copy", "Value.1", "Value.2"}),
    #"Split Column by Delimiter2" = Table.SplitColumn(#"Reordered Columns", "Value.1", Splitter.SplitTextByDelimiter("-", QuoteStyle.Csv), {"Value.1.1", "Value.1.2"}),
    #"Changed Type3" = Table.TransformColumnTypes(#"Split Column by Delimiter2",{{"Value.1.1", Int64.Type}, {"Value.1.2", Int64.Type}}),
    #"Renamed Columns" = Table.RenameColumns(#"Changed Type3",{{"Merged.1", "IATA"}, {"Merged.2", "ST"}, {"Merged.3", "FUELER"}, {"Merged.4", "UPDATED"}, {"Merged.5", "RESTRICTIONS"}, {"Merged.6", "BASEF UEL"}, {"Merged.7", "NOTES"}, {"Value.1 - Copy", "GALLONS"}, {"Value.1.1", "Min Fuel"}, {"Value.1.2", "Max Fuel"}, {"Value.2", "TOTAL PRICE"}}),
    #"Changed Type4" = Table.TransformColumnTypes(#"Renamed Columns",{{"UPDATED", type date}})
in
    #"Changed Type4"

【讨论】:

    【解决方案3】:

    这是另一种方法,根本不使用索引/匹配,而是使用 Sumproduct。在 F7 中:

    =SUMPRODUCT($B$2:$L$3,($A$2:$A$3=B7)*($C$2:$C$3=C7)*($F$2:$F$3=D7)*($A$2:$K$3=E7))
    

    请注意,一列的偏移量是通过第一个范围从 B 到 L 和最后一个范围从 A 到 K 来实现的。

    【讨论】:

    • 有趣,简单多了。但是,当我为我的工作表定制它时,我会得到 #VALUE 结果。 :( 我使用的公式如下...作为参考,您示例中的“顶部”表是我的“旧”工作表,底部参考是新工作表(我有我的参考值)=SUMPRODUCT(老!$B$2:$Q$3755,(老!$A$2:$A$3755=A29)*(老!$C$2:$C$3755=C29)*(老!$F$2:$F$3755=F29 )*(旧!$J$2:$P$3755=H29))
    • 查看参考资料。第一个是B到Q,所以如果你想向右偏移一列的值,最后一个引用需要是C到R。或者第一个是A到P,最后一个是B到Q ??
    • 从头开始,我对其进行了调整以方便偏移,但由于某种原因,我只得到 0? =SUMPRODUCT(旧!$B$2:$Q$3755,(旧!$A$2:$A$3755=A29)*(旧!$C$2:$C$3755=C29)*(旧!$F$2:$F $3755=F29)*(旧!$A$2:$P$3755=H29))
    • 现在您将返回找到的单元格左侧的一个单元格。
    • 我认为你需要交换第一个和最后一个范围 =SUMPRODUCT(old!$A$2:$P$3755,(old!$A$2:$A$3755=A29)*(old!$ C$2:$C$3755=C29)*(旧!$F$2:$F$3755=F29)*(旧!$B$2:$Q$3755=H29))
    猜你喜欢
    • 2018-11-01
    • 1970-01-01
    • 2021-07-09
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多