您也可以使用 Windows Excel 2010+ 和 O365 中提供的 Power Query 执行此操作
这实际上只是按 A 列分组的一个步骤,并对 B..F 列进行正确的聚合。下面 MCode 的第三行是所有魔法发生的地方。
-
注意使用以下任一方法,都不需要对数据进行排序。
- 此外,任何一个都可以轻松修改以添加/删除列;和/或决定为哪些行返回 SUM 或 FIRST 条目。
虽然您可以将 M 代码粘贴到高级编辑器中,但我建议您自己完成生成它的步骤,特别是如果您的列具有不同的名称,或者值不是整数时
- 选择表格中的某个单元格
- 数据/获取&转换/来自表/范围
- 当 PQ 编辑器打开时
- 选择A列和
group by
- 选择高级
- 为每列 B..F 输入一个
Sum 聚合
- 完成之后
- 主页 / 高级编辑器
- 您会看到 Table.Group 行对每个聚合列都有多个
List.Sum 操作。
- 将第二列和最后一列的 List.Sum 更改为 List.First。
- 您还可以在同一行代码中更改列标题。
M 码
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"A", type text}, {"B", Int64.Type}, {"C", Int64.Type}, {"D", Int64.Type}, {"E", Int64.Type}, {"F", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"A"}, {{"First B", each List.First([B]), type nullable number},
{"Sum C", each List.Sum([C]), type nullable number}, {"Sum D", each List.Sum([D]), type nullable number},
{"Sum E", each List.Sum([E]), type nullable number},{"First F", each List.First([F]), type nullable number}})
in
#"Grouped Rows"
如果您必须使用 VBA,我建议将 A 列中每个项目的数据收集到一个字典中,其中字典条目是另一个字典,它对每一列的值求和(第一个除外和最后一列,仅保留第一个值)。
请注意,我们在 VBA 数组中工作,因为它通常比在工作表中工作/从工作表中工作快一个数量级。
'Set reference to Microsoft Scripting Runtime (preferable)
'or convert to late binding
Option Explicit
Sub mergeCategoryValues()
Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
Dim vSrc As Variant, vRes As Variant
Dim Da As Dictionary, Dv As Dictionary
Dim I As Long, J As Long, sKeyA As String
Dim v, w
'set the Source and results worksheets, ranges
Set wsSrc = Worksheets("sheet6")
Set wsRes = Worksheets("sheet6")
Set rRes = wsRes.Cells(12, 16)
'read source data into vba array for faster processing
With wsSrc
vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=6)
End With
'read the values into dictionaries
'each dictionary of col a will contain dictionary with the other column values, either summed or just first
Set Da = New Dictionary
Da.CompareMode = TextCompare
For I = 2 To UBound(vSrc, 1) 'skip the header row
sKeyA = vSrc(I, 1)
'initial set up for column A ID
If Not Da.Exists(sKeyA) Then
Set Dv = New Dictionary
Dv.CompareMode = TextCompare
For J = 2 To UBound(vSrc, 2)
Dv.Add Key:=vSrc(1, J), Item:=vSrc(I, J)
Next J
Da.Add Key:=sKeyA, Item:=Dv
Else 'Column A entry already exists
'we just add the value from column C..next to last column
' leaving the first entry in columns A and the last column
For J = 3 To UBound(vSrc, 2) - 1
Da(sKeyA)(vSrc(1, J)) = Da(sKeyA)(vSrc(1, J)) + vSrc(I, J)
Next J
End If
Next I
'can sort the Da keys if necessary
'create results array
ReDim vRes(0 To Da.Count, 1 To UBound(vSrc, 2))
'Headers
For J = 1 To UBound(vSrc, 2)
vRes(0, J) = vSrc(1, J)
Next J
'Data
I = 0
For Each v In Da.Keys
I = I + 1
vRes(I, 1) = v
J = 1
For Each w In Da(v)
J = J + 1
vRes(I, J) = Da(v)(w)
Next w
Next v
'write to the worksheet
Set rRes = rRes.Resize(rowsize:=UBound(vRes, 1) + 1, columnsize:=UBound(vRes, 2))
Application.ScreenUpdating = False
With rRes
.EntireColumn.Clear
.Value = vRes
.HorizontalAlignment = xlCenter
.Style = "Output" 'can change or ignore this, especially if non-english version
.EntireColumn.AutoFit
End With
End Sub