使用 ARRAYFORMULA 计算应付账款的运行总计(替代间接)

问题描述 投票:0回答:4

我使用谷歌电子表格来跟踪每个供应商的应付账款。电子表格中每个供应商都有一张表。简化的sheet看起来像这样:

当我收到新发票时,会在

Credit
列中输入金额;当我发放付款时,会在
Debit
列中输入金额。我在
AC Payable
列中跟踪运行总计。我通过在
AC Payable
列的每个单元格中使用公式来实现此目的(下面的示例来自单元格
E4
):

=IF(
  ISNUMBER(INDIRECT(ADDRESS(ROW()-1,COLUMN()))),
  INDIRECT(ADDRESS(ROW()-1,COLUMN()))+C4-D4,
  C4-D4
)

逻辑很简单。第

n
行的运行总计由以下公式计算:

AC Payable(n - 1) + Credit(n) - Debit(n)

此设置工作正常,只是我必须将公式拖到新添加的行中。有没有办法通过使用

ARRAYFORMULA
来实现这一目标?

PS:我找到了解决方案:

= ARRAYFORMULA(
    SUMIF(
      ROW(C3:C),
      "<="&ROW(C3:C),
      C3:C) 
    - 
    SUMIF(
      ROW(D3:D),
      "<="&ROW(D3:D),
      D3:D
    )
  )

我觉得这是一个次优的(原始工作表可以追溯到 2018 年。它有很多行)解决方案,因为在每一行中,它都会计算直到当前行的

Debit
Credit
列的总和然后从
Debit
列的总和中减去
Credit
列的总和。

我期待一个解决方案,该解决方案将利用前一行中可用的运行总计,而不是重做每行的整个计算。

google-sheets sum flatten cumulative-sum sumifs
4个回答
3
投票

最多 1581 行的解决方案:

=ARRAYFORMULA(QUERY(QUERY(MMULT(TRANSPOSE((SEQUENCE(COUNTA(A3:A)*2)<=
 SEQUENCE(1, COUNTA(A3:A)*2))*FLATTEN(INDIRECT("C3:D"&COUNTA(A3:A)+ROW(A3)-1)*{1, -1})), 
 SEQUENCE(COUNTA(A3:A)*2, 1, 1, 0)), "offset 1", ), "skipping 2", ))

技能:

  • 速度很快
  • 很聪明
  • 添加的行越多,速度就越慢
  • 在 1581 行后死亡

它基于标准 MMULT 运行/累积总计/总和公式:

=ARRAYFORMULA(MMULT(TRANSPOSE((ROW(B1:B6) 
 <=TRANSPOSE(ROW(B1:B6)))*B1:B6), SIGN(B1:B6)))

但是有一个修改,因为总共有 2 列

我们使用实际数据计数序列乘以 2 来代替

ROW(B1:B6)
(因为您有 2 列):

SEQUENCE(COUNTA(A3:A)*2)
我们再次使用

而不是

TRANSPOSE(ROW(B1:B6))

SEQUENCE(1, COUNTA(A3:A)*2)

这些作品的组合:

=ARRAYFORMULA(TRANSPOSE((SEQUENCE(COUNTA(A3:A)*2)<=SEQUENCE(1, COUNTA(A3:A)*2))))

将产生一个矩阵,如:

这就是它在行数很多时死掉的原因,因为虽然您可能认为如果两列中只有 1500 行,那么公式将仅适用于

1500*2=3000
虚拟单元格,但实际上 MMULT 公式会处理
(1500*2)*(1500*2)=9000000
虚拟细胞。不过,值得注意的是,如果小规模部署,这个 MMULT fx 会很棒。

接下来,我们使用:

代替
*B1:B6

*FLATTEN(INDIRECT("C3:D"&COUNTA(A3:A)+ROW(A3)-1)*{1, -1}))

例如。使用 INDIRECT,我们只采用 C3:D 的“有效”范围,在您的示例表中只是 C3:D5,我们将 C 列乘以

1
,将 D 列乘以
-1
来模拟减法,然后我们将两列扁平化为一列单列。
+ROW(A3)-1
部分只是一个偏移量,因为你从第3行开始

标准 RT fx 的最后一部分 -

SIGN(B1:B6)
被替换为一列:

SEQUENCE(COUNTA(A3:A)*2, 1, 1, 0)

然后我们将内部 QUERY 的输出偏移 1,因为我们对减法后的总计感兴趣,最后我们使用

skipping 2
这意味着我们过滤掉每个第二个值 - 同样,我们对 D 列减去后的总计感兴趣。


超过1581行的解决方案:

=ARRAYFORMULA(
 SUMIF(SEQUENCE(COUNTA(A3:A)), "<="&SEQUENCE(COUNTA(A3:A)), INDIRECT("C3:C"&COUNTA(A3:A)))-
 SUMIF(SEQUENCE(COUNTA(A3:A)), "<="&SEQUENCE(COUNTA(A3:A)), INDIRECT("D3:D"&COUNTA(A3:A))))

技能:

  • 支持更多行
  • 看起来不太聪明
  • 遗憾的是 SUMIF 的第三个参数始终需要是一个范围
  • 行数越多,速度就越慢
  • 喂一万行它就会生病
  • 它可能会耗尽你 11000 多行的工作表

1
投票

这里是 Ben Collins 的运行总公式的修改版

=ARRAYFORMULA(
  IF(ISBLANK(A2:A),,
   MMULT(TRANSPOSE((ROW(C2:C)<=TRANSPOSE(ROW(C2:C)))*C2:C),SIGN(C2:C))-
   MMULT(TRANSPOSE((ROW(D2:D)<=TRANSPOSE(ROW(D2:D)))*D2:D),SIGN(D2:D))))

1
投票

MMULT 的另一种替代方案:

=INDEX(QUERY(FLATTEN(QUERY(QUERY(TRANSPOSE(QUERY(QUERY(TRANSPOSE(
 (SEQUENCE(COUNTA(A3:A)*2)<=SEQUENCE(1, COUNTA(A3:A)*2))*
 FLATTEN(INDIRECT("C3:D"&COUNTA(A3:A)+ROW(A3)-1)*{1, -1})), 
 "offset 1", ), "skipping 2", )), "select "&QUERY( 
 "sum(Col"&SEQUENCE(COUNTA(A3:A))&"),",, 9^9)&"' '"), 
 "offset 1", )), "where Col1 is not null", ))

但是,LTE (

<=
) 10M 单元的限制不会让您在您的案例中使用超过 1581 行,或者在标准累积和案例中使用超过 3162 行

(1581 rows * 2 columns) raised on 2nd power < 10 million cells

(1581*2)^2 = 9998244

0
投票

C 列总计的计算公式:-

={"Running Total";
ArrayFormula(if(C2:C="",,scan(0,C2:C,lambda(a,v,(a+v)))))
}

如果您希望结果显示在空白行上,请删除 IF 语句。

© www.soinside.com 2019 - 2024. All rights reserved.