使用数组公式的值数组

时间:2021-02-18 15:10:25

标签: google-sheets

我想使用数组公式从多个条件返回一个值数组。 我设法制作了一个有效的公式,但没有数组公式,由于工作表中的填充冲突,女巫很烦人。

Here is the sheet

Note : current solution developped from this initial thread

1 个答案:

答案 0 :(得分:0)

TL;DR

使用这个公式:

=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)))

我将尝试解释我的思考过程,以便您将来能够进行更改或制定类似的公式并供其他人参考。

基本说明

我注意到一些可以帮助我们为这个问题制定公式的事情:

  1. Fprod 表中,您有供应商和物种的列表以及周。
  2. 每个批次只有一个列表。
  3. 您的语言环境不允许在公式中使用逗号。必须改用 \

该公式的基本思想是获取定义列的字符串。它基本上是 Fprod 上的值,填充分号以垂直移动它。之后,我们想将其转换为列(类似于在另一个问题中的使用方式)。例如,如果 CNC + shiitake(批次 2101)在第 4 周开始,我们希望实现 ;;;1;2;3;4;5;6 然后变成:

<头>
2101
<empty>
<empty>
<empty>
1
2
3
4
5
6

步骤 1:获取供应商物种的规格

有了供应商和物种,我们希望在 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:HFprod

它们连接为列。要查看它是如何工作的,请尝试 ={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)都会导致问题。

第 2 步:生成填充

要生成填充,我们需要使用一些 VLOOKUP 来检测值位于哪一行。我们需要其中的 3 个,每列一个。这个想法是,在第一列中,您有需要查找的值(批次),在第二列中,需要填充的数量。它看起来像:

={$B$5:$B\ARRAYFORMULA(ROW(A5:A)-5)}

$B$5:$B 只是从第 5 行开始的 B 列。ARRAYFORMULA(ROW(A5:A)-5) 是一个技巧: ARRAYFORMULA(ROW(Ai:Aj)) 将返回从 ij(含)的计数列表。例如 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
)

第 3 步:加入他们

您可以像加入常规字符串一样简单地加入它们。注意填充先

=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
)

第 4 步:一个公式中的所有列

现在是将公式应用于所有列的好时机。基本上,在您有 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
  )
)

请注意,如果您稍后在电子表格中有数据,则会出现错误。您可以删除它或设置最大列。

还要注意,如果该列没有正确的数据,它会给我们一个错误。我们稍后会解决这个问题。

第 5 步:拆分成列

要将表示拆分为列,我们需要使用 SPLIT。拆分会将值拆分为一行。这意味着我们需要转置 (see Wikipedia article)。所以我们应该转置,拆分,然后再转置。所以让我们添加 TRANSPOSESPLIT

=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
    )
  )
)

第 6 步:处理错误

我们可以处理3种情况:

  1. 未在 Fprod 上找到物种和供应商
  2. 批次不存在
  3. 该列为空

对于第一个,我们可以简单地在查找中添加一个 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 公式。

参考文献