无法在同一公式中使用 BYCOL 和 SCAN

vso*_*ler 1 excel excel-formula

我正在尝试计算某个范围内每列的运行(累积)总计(请参见下图)。

如果我每列使用一个 SCAN 函数,它就可以工作。但我必须编写与我有的列一样多的 SCAN 函数。

问题是我想使用一个包含所有列的动态数组公式,无论是当前列还是将来列。

当我尝试将 BYCOL 与 LAMBDA 和 SCAN 一起使用时,它不起作用。我想知道 BYCOL 是否能够与 SPILL 的函数一起使用。

如果 BYCOL 与 SCAN 不兼容,是否有解决方法可以对我的所有运行总计使用单个公式?

在此输入图像描述

Dav*_*eal 5

在单元格上D2输入以下公式:

=LET(set, A2:B5, m, COLUMNS(set), seq, SEQUENCE(m,1),
 CUMULATE, LAMBDA(x, SCAN(0, x, LAMBDA(acc,item, acc+item))),
 DROP(REDUCE(0,seq, LAMBDA(acc,idx, HSTACK(acc, CUMULATE(INDEX(set,,idx))))),,1)
)
Run Code Online (Sandbox Code Playgroud)

这是输出:

示例 Excel 文件

如果累加器正确初始化,并且第一列的累积和,它也可以在不删除DROP第一列的情况下工作,如下所示:

=LET(set, A2:B5, m, COLUMNS(set), seq, SEQUENCE(m,1),
 CUMULATE, LAMBDA(x, SCAN(0, x, LAMBDA(acc,item, acc+item))),
 REDUCE(0,seq, LAMBDA(acc,idx, IF(idx = 1, CUMULATE(INDEX(set,,idx)),
  HSTACK(acc, CUMULATE(INDEX(set,,idx))))))
)
Run Code Online (Sandbox Code Playgroud)

更新

另一种选择是使用MAP与输入范围相同的形状的以下解决方案,因此无需通过DROP/REDUCE/HSTACK模式添加列:

=LET(n, ROWS(A2:B5), m, COLUMNS(A2:B5), 
  rows, MAKEARRAY(n, m, LAMBDA(r, c, r)),cols, MAKEARRAY(n, m, LAMBDA(r, c, c)),
  MAP(rows, cols, LAMBDA(r, c, SUM(INDEX(A2:B5, 1, c):INDEX(A2:B5, r, c)) ))
)
Run Code Online (Sandbox Code Playgroud)

注意:您不能传递名称来表示函数内的LET范围,以使用需要范围的函数/操作,例如构建范围如下:。检查@JosWoolley对此问题的答案:使用来自 LET 的名称变量会产生#VALUE!在 MAP 内部使用 SUM 并将范围定义为 INDEX : INDEXA2:B5LAMBDAINDEX() : INDEX()

解释

BYCOL每列返回一个单元格,这就是为什么您会收到与Nested Array Error#CALC!相关的错误。可以使用模式来规避,例如此处解释:如何将 Excel 中的表格从垂直转换为水平,但具有@DavidLeal 提供的不同长度答案。DROP/REDUCE/HSTACK

对于您的特定情况,我们需要计算每列的累积和。我们LAMBDA为此创建了一个用户函数CUMULATE

LAMBDA(x, SCAN(0, x, LAMBDA(acc, item, acc+item)))
Run Code Online (Sandbox Code Playgroud)

现在我们使用该模式来迭代所有列。REDUCE函数需要一个输入数组,因此我们创建一个seq包含列位置的名称。我们可以通过 访问输入范围 ( set)的每一列INDEX(set,,idx),其中idx表示列号。

DROP/REDUCE/HSTACK现在我们使用上面链接中解释的模式来生成每一列:

DROP(REDUCE(0, arr, LAMBDA(acc, x, HSTACK(acc, func(x)))),,1)
Run Code Online (Sandbox Code Playgroud)

在我们的例子func(x)中将是LAMBDA我们刚刚创建的用户函数:CUMULATE,所以在我们的例子中它将是:

DROP(REDUCE(0,seq, LAMBDA(acc,idx, HSTACK(acc, CUMULATE(INDEX(set,,idx))))),,1)
Run Code Online (Sandbox Code Playgroud)

它的作用是调用函数的每一列setCUMULATE LAMBDA并通过HSTACK附加在每次迭代中创建的列。该变量acc代表累加器,因此我们从累加器的初始值开始0,然后通过以下列递归添加HSTACK。最后,我们需要删除DROP(result,,1)代表第一次迭代的第一列 via ,该迭代不计算累积和并仅生成如下所示的列:

0
#N/A
#N/A
#N/A
Run Code Online (Sandbox Code Playgroud)

注意:如果数组的行数少于所选数组的最大宽度,则在附加行中HSTACK返回错误。#N/A这就是为什么你会得到这样的价值观。最重要的是,需要删除第一列,因为我们在第一次迭代时没有使用有效值进行初始化。我提供了第二种替代方案,不需要删除此列,但最后是一个更详细的公式。这是个人喜好的问题。