【问题标题】:Sum multiple rows based on duplicate column data without formula根据没有公式的重复列数据对多行求和
【发布时间】:2026-01-25 16:15:02
【问题描述】:

根据 A 到 D 列中可用的数据(可以是任何 100 列),我想总结 E 到 K 列的所有行(可以是任何 100 列)

各行应根据A到D行的重复数据求和,所需结果如下

使用 sumif 很容易做到这一点,但想知道是否可以在 excel 或 power 查询中本地实现,而无需为每列创建唯一 id 或使用 sumif 函数或任何类型的公式

【问题讨论】:

标签: excel powerquery


【解决方案1】:

在 powerquery 中.. unpivot、group、pivot、done。

更多细节:

单击选择前4列,右键单击,取消透视其他列

点击选择前4列和新的属性列,右键,分组

使用操作:对列求和:值名称:计数并点击确定

单击选择属性列并转换..枢轴列...,对于值列选择计数

文件关闭并加载

完整示例代码:

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(Source, {"Code1", "Code2", "Code3", "Code4"}, "Attribute", "Value"),
#"Grouped Rows" = Table.Group(#"Unpivoted Other Columns", {"Code1", "Code2", "Code3", "Code4", "Attribute"}, {{"Count", each List.Sum([Value]), type number}}),
#"Pivoted Column" = Table.Pivot(#"Grouped Rows", List.Distinct(#"Grouped Rows"[Attribute]), "Attribute", "Count", List.Sum)
in  #"Pivoted Column"

【讨论】:

  • 我理解问题的重点是 - 如果您有数百列,您将如何执行此操作。我回答的第一步是按照和你一样的方式进行分组,但是你如何用很多列来做呢?您是否假设它们意味着数百行?
  • 一个你取消透视的,无论你从多少列开始,都只有一列可以分组
【解决方案2】:

为了解决这样的问题,我先做一个具体的例子,然后概括一下。我在 Excel 中制作了一个小表格,如下所示:

Code1 Code2 2-Jul-20 3-Jul-20 4-Jul-20 5-Jul-20 6-Jul-20
ERT EXC 10 6 15 2
ERT EXC 2 3 23 1
CON HOR 3
CON HOR 6 2 356 3

然后我在表中单击并创建了一个引用它的 Power Query。打开 Power Query 编辑器后,主页选项卡上有一个分组依据功能。在这样的玩具示例中选择所需的列和 Sum 函数非常简单。

然后,我打开高级编辑器查看自动生成的代码。它看起来像这样:

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    
    #"Grouped Rows orig" = Table.Group(Source, {"Code1", "Code2"}, {{"2-Jul-20", each List.Sum([#"2-Jul-20"]), type nullable number}, {"3-Jul-20", each List.Sum([#"3-Jul-20"]), type nullable number}, {"4-Jul-20", each List.Sum([#"4-Jul-20"]), type nullable number}, {"5-Jul-20", each List.Sum([#"5-Jul-20"]), type nullable number}, {"6-Jul-20", each List.Sum([#"6-Jul-20"]), type nullable number}})
in
    #"Grouped Rows orig"

通常,Power Query 表达式是应用于表的一系列转换,其中每个转换都对从前一个返回的表进行操作。在这里,我们从原始表作为“源”开始,然后进行分组。参数有点乱,但我们拥有的是:(1)输入表,(2)要分组的列名列表,以及(3)3项列表的列表,每个列表描述一个聚合列。子列表具有输出列名、进行聚合的函数和数据类型。

在 Power Query 中,“each”是单个参数函数的语法糖,其参数只是一个下划线。而且,当您有记录或行时,您可以只使用 [column] 而不是 _[column]。

那么如何概括你想做的操作呢?我的第一个想法是,根据您的描述,一个方便的分组函数应该有两个参数。第一个是要分组的表,第二个是从左边开始分组的列数。如果您没有将它们连续排列,当然,您可以做其他事情。

    sumFromColumn = (t, n) => let
                                    cList = Table.ColumnNames(t),
                                    toGroup = List.FirstN(cList, n),
                                    toSum = List.RemoveFirstN(cList, n),
                                    sumFunc = (cName) => {cName, each List.Sum(Record.Field(_, cName)), type nullable number}
                                in Table.Group(t, toGroup, List.Transform(toSum, each sumFunc(_))),

    #"Grouped Rows" = sumFromColumn(Source, 2), // Group by the first 2 columns and sum the rest

这是我做的泛化函数,看起来和接口生成的原始Table.Group操作相匹配。

let 语句安排事物的可读性,但并不暗示它们发生的特定顺序。Power Query 找出依赖关系并以所需的任何顺序执行语句。

表的列名列表定义为cList,分为toGroup和toSum。然后, sumFunc 被定义为一个函数,该函数采用列名并返回定义聚合操作所需的 3 项列表。在 Power Query 中,函数可以以任何方式返回其他函数。所以在这里我们定义了一个返回列表的函数,其中包含一个函数。然后我们可以使用 List.Transform 获取聚合列的列表并将其转换为 Table.Group 的适当参数。

最后,实际的 group by 是通过 sumFromColumn(Source, 2) 之类的调用完成的,这相当于对列名进行硬编码的原始语句。

Code1 Code2 2-Jul-20 3-Jul-20 4-Jul-20 5-Jul-20 6-Jul-20
ERT EXC 12 3 6 38 3
CON HOR 6 5 356 3

这可以很容易地更改为 sumFromColumn(Source, 1),在这种情况下它将减少到两行,但是第二列是非数字的,将成为错误值。

或者,您可以使用 sumFromColumn(Source, 3),它不会相加,因为按列组合在一起的分组是不同的。

通过这种方式,您可以轻松聚合任意数量的列,而无需关心它们的名称。我推荐 microsoft.com 上的 Power Query M 文档和一般的函数式编程。

【讨论】: