如何制作一个已经很复杂的 Arrayformula 的 Arrayformula?

How Can I make an Arrayformula of an already complex Arrayformula?

这类问题已经在这里被问过很多次(我知道),我已经尝试将半打答案转化为我的特定公式但没有成功 ()。我想我不知道如何或在哪里将它实现到我已经非常复杂的公式中(它将多行的开放时间文本块解析为一周中每一天的单个 start/end 时间格式(和次要times if present)。我所有的尝试要么不起作用,要么第一行的计算结果在整列中重复。

我已经支持我的所有尝试,并将分享我希望最终在整个列(数千行)中“排列”的基本公式。

Here's the Google Sheet

这是目前为止的基本公式:

=if(isblank($A3:$A),,iferror(
  regexreplace(
    concatenate(
      arrayformula(
        text(
          split(
            INDEX(
              REGEXEXTRACT(
                regexreplace($A3:$A,"–","-"),
                "(\s?" & B & ":\s)((\d?\d:\d\d\s[AMP]*\s?\W\s\d?\d:\d\d\s[AMP]{2})|(Closed)|(Open\s24\shours))"
              ),1,2 
            ),"-",true,true
          ),"HH:MM-"
        )
      )
    ),"(\d\d:\d\d\-\d\d:\d\d)\-",""
  ),
))

在此先感谢您的帮助。

编辑:我被要求澄清公式的作用。该公式正在将一段文本解析为机器可读格式(我将把它导入数据库),其中包含从周一到周日的企业营业时间。如果企业有时间段(比如一家餐馆午餐时间营业,休息一下,然后重新营业晚餐),相邻单元格中的公式也会考虑到这一点。

尝试:

=ARRAYFORMULA(IFERROR(HLOOKUP(B2:O2, QUERY(SPLIT(FLATTEN(IF(IFERROR(
 SPLIT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"))<>"", 
 COUNTIFS(
 INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 
 INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 
      ROW(INDIRECT("A1:A"&COUNTA(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))))),
 "<="&ROW(INDIRECT("A1:A"&COUNTA(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))))))&"♣"&LOWER(
  LEFT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 3))&COLUMN(A:B)&"♣"&
 SUBSTITUTE(SUBSTITUTE({TRANSPOSE(QUERY(TRANSPOSE(TEXT(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,1), "–"),  "hh:mm")),,9^9)),
 TRANSPOSE(QUERY(TRANSPOSE(TEXT(IFERROR(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,2), "–")), "hh:mm")),,9^9))}, 
 "00:00 00:00", ), " ", "-"), 
 COUNTIFS(
 INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 
 INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 
      ROW(INDIRECT("A1:A"&COUNTA(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))))),
 "<="&ROW(INDIRECT("A1:A"&COUNTA(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))))))&"♣"&LOWER(
  LEFT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,1), 3))&COLUMN(A:B))), "♣"), 
 "select max(Col3) group by Col1 pivot Col2"), ROW(INDIRECT("A2:A"&COUNTA(A3:A)+ROW(A3)-1)), 0)))


更新:

=ARRAYFORMULA(IFERROR(HLOOKUP(B2:O2, IFNA(VLOOKUP({""; ROW(A3:A)}, QUERY(SPLIT(FLATTEN(IF(IFERROR(
 SPLIT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"))<>"", 
 LOWER(LEFT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, IF(A3:A="",,
 REGEXREPLACE(A3:A, "^|(\n)", ""&ROW(A3:A)&"♣"))), CHAR(10))), ": ", ),,1), 5))&COLUMN(A:B)&"♣"&
 SUBSTITUTE(SUBSTITUTE(SUBSTITUTE({TRANSPOSE(QUERY(TRANSPOSE(TEXT(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,1), "–"),  "hh:mm")),,9^9)),
 TRANSPOSE(QUERY(TRANSPOSE(TEXT(IFERROR(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,2), "–")), "hh:mm")),,9^9))}, 
 "00:00 00:00", ), "Closed 00:00", "Closed"), " ", "-"), 
 LOWER(LEFT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, IF(A3:A="",,
 REGEXREPLACE(A3:A, "^|(\n)", ""&ROW(A3:A)&"♣"))), CHAR(10))), ": ", ),,1), 5))&COLUMN(A:B))), "♣"), 
 "select Col1,max(Col3) group by Col1 pivot Col2"), COLUMN(B:O), 0)), ROW(INDIRECT("A2:A"&COUNTA(A3:A)+ROW(A3)-1)), 0)))

spreadsheet demo


修复:

=ARRAYFORMULA(IFERROR(HLOOKUP(B2:O2, IFNA(VLOOKUP({""; ROW(A3:A)}, QUERY(SPLIT(FLATTEN(IF(IFERROR(
 SPLIT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"))<>"", 
 LOWER(REGEXEXTRACT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, IF(A3:A="",,
 REGEXREPLACE(A3:A, "^|(\n)", ""&ROW(A3:A)&"♣"))), CHAR(10))), ": ", ),,1), "\d+♣..."))&COLUMN(A:B)&"♣"&
 SUBSTITUTE(SUBSTITUTE(SUBSTITUTE({TRANSPOSE(QUERY(TRANSPOSE(TEXT(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,1), "–"),  "hh:mm")),,9^9)),
 TRANSPOSE(QUERY(TRANSPOSE(TEXT(IFERROR(SPLIT(INDEX(SPLIT(INDEX(
 SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, A3:A), CHAR(10))), ": ", ),,2), ",;"),,2), "–")), "hh:mm")),,9^9))}, 
 "00:00 00:00", ), "Closed 00:00", "Closed"), " ", "-"), 
 LOWER(REGEXEXTRACT(INDEX(SPLIT(FLATTEN(SPLIT(TEXTJOIN(CHAR(10), 1, IF(A3:A="",,
 REGEXREPLACE(A3:A, "^|(\n)", ""&ROW(A3:A)&"♣"))), CHAR(10))), ": ", ),,1), "\d+♣..."))&COLUMN(A:B))), "♣"), 
 "select Col1,max(Col3) group by Col1 pivot Col2"), COLUMN(B:O), 0)), ROW(INDIRECT("A2:A"&MAX(IF(A:A="", ROW(A:A))))), 0)))

这是另一个建议,它更短但效果更好。

这是一个数组公式,将填充一个完整的行。然后你只需将它拖到 B 列下即可。我已将其放入单元格 B4 中名为“Erik Help”的新 sheet:

=ArrayFormula(IF(A4="","",IF(B:="","",IFERROR(TRIM(SUBSTITUTE(" "&VLOOKUP(LEFT(B:,3)&"*",{TRIM(QUERY(SPLIT(FLATTEN(SPLIT(A4,";")),": ",0),"Select Col1")),TEXT(TRIM(SPLIT(QUERY(SPLIT(FLATTEN(SPLIT(A4,";")),": ",0),"Select Col2"),"–,",1)),"hh:mm")},IF(VALUE(RIGHT(B:,1))=1,2,4),FALSE)&"-"&VLOOKUP(LEFT(B:,3)&"*",{TRIM(QUERY(SPLIT(FLATTEN(SPLIT(A4,";")),": ",0),"Select Col1")),TEXT(TRIM(SPLIT(QUERY(SPLIT(FLATTEN(SPLIT(A4,";")),": ",0),"Select Col2"),"–,",1)),"hh:mm")},IF(VALUE(RIGHT(B:,1))=1,3,5),FALSE)," -",""))))))

...然后我把它拖到B5和B6.

注意:FLATTEN 仍然是一个非官方的 Google 函数,因此请在理解的情况下使用它。

根据您添加的评论,我添加了另一个 sheet,名为“Erik Help 2”。您会发现新的数组公式位于单元格 B3(青色)中。它填充整个行和列网格,包括来自那个单元格的 sub-headers(例如,mon1、mon2 等):

=ArrayFormula({IF(B:O<>"",LOWER(LEFT(B:O,3))&"1",LOWER(LEFT(A:N,3))&2);IF(TRIM($A4:A)="","",IF(B:O<>"",
TEXT(TRIM(MID(TRIM($A4:A),FIND(":",TRIM($A4:A),FIND(B:O,TRIM($A4:A)))+1,9)),"hh:mm")&"-"&TEXT(TRIM(SUBSTITUTE(SUBSTITUTE(MID(TRIM($A4:A),FIND(":",TRIM($A4:A),FIND(B:O,TRIM($A4:A)))+12,9),",",""),";","")),"hh:mm"),
IF(FIND(";",TRIM($A4:A),FIND(A:N,TRIM($A4:A)))-FIND(":",TRIM($A4:A),FIND(A:N,TRIM($A4:A)))>25,
TEXT(TRIM(MID(TRIM($A4:A),FIND(",",TRIM($A4:$A),FIND(A:N,TRIM($A4:A)))+1,9)),"hh:mm")&"-"&TEXT(TRIM(SUBSTITUTE(MID(TRIM($A4:A),FIND(",",TRIM($A4:$A),FIND(A:N,TRIM($A4:A)))+12,9),";","")),"hh:mm"),"")))})

您需要仔细检查它以获得准确的结果,但我认为它是正确的。

请记住,这个复杂的公式 依赖于 您在 A 列中保留当前结构。即:

1.) 工作日拼写后跟一个冒号和 space.

2.) 同一天的两个时段用逗号分隔。

3.) 每个 工作日的条目以分号结尾。

如果更改此设置,公式将不起作用,因为它将无法找到所需的标记。