我想使用数组公式从多个条件返回一个值数组。 我设法制作了一个有效的公式,但没有数组公式,由于工作表中的填充冲突,女巫很烦人。
答案 0 :(得分:0)
使用这个公式:
=ARRAYFORMULA(TRANSPOSE(SPLIT(TRANSPOSE(IF((F$1:$1&F$2:$2&F$3:$3&F$4:$4)<>"";IFERROR(REPT(";";IFERROR(VLOOKUP(F$4:$4;{$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)};2;FALSE);-1)+IFERROR(VLOOKUP(F$4:$4;{$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)};2;FALSE);-1)+IFERROR(VLOOKUP(F$4:$4;{$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)};2;FALSE);-1)+2);"#Batch? ")&IFERROR(VLOOKUP(F$1:$1&"-----"&F$2:$2;{ARRAYFORMULA(IF(LEN(Fprod!$H$2:$H);Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G;))\Fprod!$H$2:$H};2;FALSE);"#Species/supplier?");";"));";";TRUE;FALSE)))
我将尝试解释我的思考过程,以便您将来能够进行更改或制定类似的公式并供其他人参考。
我注意到一些可以帮助我们为这个问题制定公式的事情:
Fprod
表中,您有供应商和物种的列表以及周。\
该公式的基本思想是获取定义列的字符串。它基本上是 Fprod
上的值,填充分号以垂直移动它。之后,我们想将其转换为列(类似于在另一个问题中的使用方式)。例如,如果 CNC
+ shiitake
(批次 2101
)在第 4 周开始,我们希望实现 ;;;1;2;3;4;5;6
然后变成:
2101 |
---|
<empty> |
<empty> |
<empty> |
1 |
2 |
3 |
4 |
5 |
6 |
有了供应商和物种,我们希望在 Fprod
上获得周数(即 CNC
+ shiitake
应该给我们 1;2;3;4;5;6
)。
为此,我们将使用 VLOOKUP 来获取本周的正确列表。问题是我们需要检查 2 列。所以诀窍是用中间的一些字符(例如-----
)连接两列以防止意外冲突。所以在 F 列上工作:
=VLOOKUP(
F$1&"-----"&F$2;
{ARRAYFORMULA(IF(LEN(Fprod!$H$2:$H); Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G;)) \ Fprod!$H$2:$H};
2;
FALSE
)
让我们拆开这个,因为已经有很多东西了。
让我们从第二个参数开始,因为它是最复杂的一个。它所做的是创建一个表(二维数组),其中第一列是 <supplier>-----<species>
上的每个条目 Fprod
,第二列是我们想要的值。要制作第一列,我们可以使用 ARRAYFORMULA 逐行添加两列:
=ARRAYFORMULA(Fprod!$F$2:$F & "-----" & Fprod!$G$2:$G)
第二列只是 H2:H
的 Fprod
。
它们连接为列。要查看它是如何工作的,请尝试 ={1\2}
(通常是 ,
,但由于您的语言环境需要 \
)。这将生成类似于以下内容的结果:
1 | 2 |
---|---|
CNC-----香菇 | 1;2;3;4;5;6 |
欧元-----香菇 | 1;2;3;4;5;6;7;8;9;10;11;12;13;14 |
欧元-----pleurote | 1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22 |
香菇-----香菇 | 1;2;3;4;5;6;7;8;9;10;11;12;13;14 |
Moser-----蘑菇 | 1;2;3;4;5;6 |
----- | |
----- |
如您所见,我们还生成了空条目。要忽略它们,我们将检查该行的 H 列是否为空:
=ARRAYFORMULA(IF(LEN(Fprod!$H$2:$H); Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G;))
现在我们可以简单地使用 VLOOKUP 来获取第二列中的值。我们搜索的值与第一列的格式相同。在这种情况下,我们将使用 F 列并在稍后进行概括。如果您将其添加到 F 列,您应该会看到 1;2;3;4;5;6
出现。
请务必注意最后一个参数,因为数据未排序,将其设置为 true 或不设置(默认为 true)都会导致问题。
要生成填充,我们需要使用一些 VLOOKUP 来检测值位于哪一行。我们需要其中的 3 个,每列一个。这个想法是,在第一列中,您有需要查找的值(批次),在第二列中,需要填充的数量。它看起来像:
={$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}
$B$5:$B
只是从第 5 行开始的 B 列。ARRAYFORMULA(ROW(A5:A)-5)
是一个技巧:
ARRAYFORMULA(ROW(Ai:Aj))
将返回从 i
到 j
(含)的计数列表。例如 ARRAYFORMULA(ROW(A5:A6))
将返回
结果 |
---|
5 |
6 |
在这种情况下,我们需要结果与另一个表的大小相同,因此我们不得不使用 ARRAYFORMULA(ROW(A5:A))
来这样做。由于这些值太大,所以我们需要减去 5,得到 ARRAYFORMULA(ROW(A5:A)-5)
。
将它们连接到一个表中,您就可以在何处查找:
=VLOOKUP(F$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE)
这与之前所做的非常相似。如果您将其添加到 F5
,您会看到它表示偏移量(# 周减一)。
就像我之前指出的,我们需要这三个列,但我们需要确保它不会崩溃。为此,如果列中没有,我们需要将默认值设置为 -1
。使用 IFERROR 很简单。
=IFERROR(VLOOKUP(F$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1)
我们不能使用 MAX 来连接它们,因为它不能与 ARRAYFORMULA 一起使用,因为 if 可以使用范围。因此我们需要发挥创意,所以我添加了它们。这意味着有 2 -1
和值;所以添加 2 补偿它:
=IFERROR(VLOOKUP(F$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
现在我们只需要根据需要使用 REPT 重复 ;
次:
=REPT(
";";
IFERROR(VLOOKUP(F$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
)
您可以像加入常规字符串一样简单地加入它们。注意填充先
=REPT(
";";
IFERROR(VLOOKUP(F$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
)&
VLOOKUP(
F$1&"-----"&F$2;
{ARRAYFORMULA(IF(LEN(Fprod!$H$2:$H); Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G;)) \ Fprod!$H$2:$H};
2;
FALSE
)
现在是将公式应用于所有列的好时机。基本上,在您有 F
列的地方,现在我们将针对该行上以 F
开头的范围更改它。例如,F4
将变成 F4:4
。
=ARRAYFORMULA(
REPT(
";";
IFERROR(VLOOKUP(F$4:$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
)&
VLOOKUP(
F$1:$1&"-----"&F$2:$2;
{ARRAYFORMULA(Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G) \ Fprod!$H$2:$H};
2;
FALSE
)
)
请注意,如果您稍后在电子表格中有数据,则会出现错误。您可以删除它或设置最大列。
还要注意,如果该列没有正确的数据,它会给我们一个错误。我们稍后会解决这个问题。
要将表示拆分为列,我们需要使用 SPLIT。拆分会将值拆分为一行。这意味着我们需要转置 (see Wikipedia article)。所以我们应该转置,拆分,然后再转置。所以让我们添加 TRANSPOSE 和 SPLIT:
=ARRAYFORMULA(
TRANSPOSE(
SPLIT(
TRANSPOSE(
REPT(
";";
IFERROR(VLOOKUP(F$4:$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
)&
VLOOKUP(
F$1:$1&"-----"&F$2:$2;
{ARRAYFORMULA(Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G) \ Fprod!$H$2:$H};
2;
FALSE
)
);
";";
TRUE;
FALSE
)
)
)
我们可以处理3种情况:
Fprod
上找到物种和供应商对于第一个,我们可以简单地在查找中添加一个 IFERROR,添加一条默认消息。对于第二个我们可以添加一个 IFERROR 包装 REPT 因为当数字为负数时(未找到时)它会抛出错误。对于最后一个,我们需要使用带有值“;”的 IF失败时(SPLIT 要求字符串不为空)。
将所有这些添加到我们的最终结果中:
=ARRAYFORMULA(
TRANSPOSE(
SPLIT(
TRANSPOSE(
IF(
(F$1:$1&F$2:$2&F$3:$3&F$4:$4)<>"";
IFERROR(
REPT(
";";
IFERROR(VLOOKUP(F$4:$4; {$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$C$5:$C\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
IFERROR(VLOOKUP(F$4:$4; {$D$5:$D\ARRAYFORMULA(ROW(A5:A)-5)}; 2; FALSE); -1) +
2
);
"#Batch? "
)&
IFERROR(
VLOOKUP(
F$1:$1&"-----"&F$2:$2;
{ARRAYFORMULA(IF(LEN(Fprod!$H$2:$H); Fprod!$F$2:$F&"-----"&Fprod!$G$2:$G;)) \ Fprod!$H$2:$H};
2;
FALSE
);
"#Species/supplier?"
);
";"
)
);
";";
TRUE;
FALSE
)
)
)
如果删除任何不必要的空格,就会得到 TL;DR 公式。