查看: 132|回复: 3

Python对Excel工作表行分组与列分组:折叠展开、多级嵌套与汇总

[复制链接]
发表于 半小时前 | 显示全部楼层 |阅读模式
明细表超过二三十行后,读者往往只关心每组的第一行。月度报表按部门收起明细、项目计划按阶段折叠任务、宽表把中间几列临时藏起来,本质都是在工作表上加一层分级显示:左侧或上方出现层级按钮,点一下把一组行或列折叠成一行,再点一次展开。Excel 里这对应「组合」功能,落到代码上就是 GroupByRows 与 GroupByColumns 两个方法,再配合 CollapseGroup / ExpandGroup 控制初始状态。

本文使用 Free Spire.XLS for Python,安装命令:
  1. pip install Spire.XLS.Free
复制代码

需要先弄清对象模型。分组挂在 Worksheet 上,按行或按列成组;每组的折叠状态由区域方法与 GroupByType 决定;汇总行的位置在 PageSetup 上。具体分工是:Workbook 是工作簿容器,提供 Worksheets 与 SaveToFile;Worksheet 是行分组和列分组的入口;CellRange 代表参与分组的区域,提供 CollapseGroup、ExpandGroup、RowGroupLevel 等成员;PageSetup 负责打印与大纲设置,其中 IsSummaryRowBelow 决定折叠标记的朝向。

GroupByRows(start, end, collapsed) 的三个参数依次是起始行、结束行和「建组时是否折叠」。这里的行号是工作表上的真实行号,从 1 起算,与按区域内偏移计数的参数不同。RowGroupLevel 用于读回某行所属层级,未参与分组的行返回 0。

一、基础行分组:把明细收进一组

给连续行建组后,左侧会出现分级条与折叠按钮,左上角显示层级按钮 1、2:
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. workbook = Workbook()
  4. workbook.CreateEmptySheets(1)
  5. sheet = workbook.Worksheets[0]
  6. rows = [
  7.     ["阶段", "任务", "工时"],
  8.     ["阶段一", "需求梳理", 12],
  9.     ["阶段一", "接口设计", 18],
  10.     ["阶段一", "页面开发", 26],
  11.     ["阶段二", "联调测试", 20],
  12.     ["阶段二", "性能验证", 14],
  13.     ["阶段二", "上线准备", 9],
  14. ]
  15. for r, row in enumerate(rows, start=1):
  16.     for c, value in enumerate(row, start=1):
  17.         cell = sheet.Range[r, c]
  18.         if isinstance(value, str):
  19.             cell.Text = value
  20.         else:
  21.             cell.NumberValue = value
  22. sheet.GroupByRows(2, 4, False)
  23. sheet.GroupByRows(5, 7, False)
  24. workbook.SaveToFile("grouped.xlsx", ExcelVersion.Version2016)
  25. workbook.Dispose()
复制代码

两个组分别覆盖第 2–4 行与第 5–7 行,第三个参数为 False,建组后保持展开。表头留在第 1 行且不参与分组,因此它的 RowGroupLevel 为 0。

二、建组时就收起

把第三个参数改成 True,建组的同时收起明细,只留一行占位。沿用上面的数据填充代码,只替换末尾的分组调用:
  1. sheet.GroupByRows(2, 4, True)
  2. sheet.GroupByRows(5, 7, False)
复制代码

第一组收起后,行号从 1 直接跳到 5,折叠位置留一个加号按钮;第二组仍展开。整张表只剩四行可见,点开加号后明细回到原位。行号跳过的位置就是被隐藏的行,数据本身没有被删除。

三、多级嵌套:先外层,再内层

先给大范围建组,再给其中的子范围建组,层级会依次加深:外层为第 1 级,内层为第 2 级,左上角的层级按钮随之变成 1、2、3。
  1. sheet.GroupByRows(2, 7, False)
  2. sheet.GroupByRows(2, 4, False)
  3. sheet.GroupByRows(5, 7, False)
复制代码

此时第 2–7 行读回的 RowGroupLevel 为 2,外层对应 1。最深层级为 2 时,左上角出现 1、2、3 三个按钮,按级别控制展开深度;分组越深,按钮越多。

四、统一收起与展开

建好的组可以随时折叠或展开。CollapseGroup 与 ExpandGroup 按区域操作,用 GroupByType.ByRows 指明方向:
  1. sheet.GroupByRows(2, 7, False)
  2. sheet.GroupByRows(2, 4, False)
  3. sheet.GroupByRows(5, 7, False)
  4. sheet.Range["A2:C7"].CollapseGroup(GroupByType.ByRows)
复制代码

收起后整段明细隐去,只留第 1 行与折叠位置的一个加号;ExpandGroup 是反向操作,把该层重新打开,展开子组时可用 ExpandCollapseFlags.ExpandParent 一并展开外层。这两个方法作用于该范围所在的层级:折叠内层时外层随之收起,展开时同一层的分组一起打开。如果想让某一组展开、另一组收起,状态应在建组时就定下来——GroupByRows 的第三个参数按组分别取值。批量报表里常见的做法是建组时全部收起,再按当期数据把需要看的那一层展开。

五、汇总行位置决定按钮落在哪一端

大纲的折叠按钮默认落在明细的下方。把 PageSetup.IsSummaryRowBelow 设为 False 后,折叠标记移到组的上方,适合「小计在上、明细在下」的报表:
  1. sheet.GroupByRows(2, 7, False)
  2. sheet.PageSetup.IsSummaryRowBelow = False
复制代码

这里改的是大纲的汇总方向,不是数据顺序:行的先后不变,只是折叠按钮从组的下沿移到上沿,层级按钮 1、2 仍留在左上角。

六、列分组:把中间的列收起来

列方向用法相同,入口换成 GroupByColumns,分级条出现在列标上方:
  1. rows = [
  2.     ["阶段", "任务", "工时", "备注"],
  3.     ["阶段一", "需求梳理", 12, "常规"],
  4.     ["阶段一", "接口设计", 18, "常规"],
  5.     ["阶段一", "页面开发", 26, "加急"],
  6.     ["阶段二", "联调测试", 20, "常规"],
  7.     ["阶段二", "性能验证", 14, "加急"],
  8.     ["阶段二", "上线准备", 9, "常规"],
  9. ]
  10. for r, row in enumerate(rows, start=1):
  11.     for c, value in enumerate(row, start=1):
  12.         cell = sheet.Range[r, c]
  13.         if isinstance(value, str):
  14.             cell.Text = value
  15.         else:
  16.             cell.NumberValue = value
  17. sheet.GroupByColumns(2, 3, False)
复制代码

第 2–3 列成组后,列标上方多出一条横向分级条,折叠时这两列收起,阶段与备注仍并排显示。列分组同样支持嵌套与折叠状态,第三个参数的语义与行分组一致。

七、API 速查

核心类:Workbook 是工作簿对象,提供工作表集合;Worksheet 是工作表,行分组与列分组的入口;CellRange 是区域,用于折叠、展开与读取层级;PageSetup 负责页面与大纲设置。

常用方法与属性:Worksheet.GroupByRows(start, end, collapsed) 对第 start 至 end 行建组;Worksheet.GroupByColumns(start, end, collapsed) 对第 start 至 end 列建组;CellRange.CollapseGroup(GroupByType.ByRows) 收起区域所在的组;CellRange.ExpandGroup(GroupByType.ByRows, flags) 展开区域所在的组;CellRange.RowGroupLevel 返回该行所属层级,未分组为 0;CellRange.ColumnGroupLevel 返回该列所属层级;CellRange.IsGroupedByRow 判断该行是否参与分组;PageSetup.IsSummaryRowBelow 指定汇总行是否在明细下方。

枚举与常量:GroupByType.ByRows 按行方向操作;GroupByType.ByColumns 按列方向操作;ExpandCollapseFlags.ExpandParent 展开子组时一并展开外层。

八、小结与注意点

分组由两类参数决定:给哪一段行或列建组,以及建组时收不收。行号与列号都是工作表上的真实位置,从 1 起算;先建外层再建内层,RowGroupLevel 就逐级加深,层级按钮的数量随之增加。建组之后的状态可以用 CollapseGroup 与 ExpandGroup 按层级调整,IsSummaryRowBelow 决定折叠标记落在组的上沿还是下沿。

分组只改变显示层级,不删除也不移动单元格:折叠时行号跳过的位置仍是原来的数据,展开后回到原位。需要整表一次性收起或展开时,遍历各组对应的区域逐个调用即可。上述行为在保存为 ExcelVersion.Version2016 格式后,用 Excel 打开即可看到左侧或上方的分级条与层级按钮。
回复

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python对Excel工作表行分组与列分组:折叠展开、多级嵌套与汇总

这篇整理得挺系统的,尤其把对象模型的分工先讲清楚,再看后面的例子就不容易乱。我照着一、二两段试了下,建组和初始折叠都正常,RowGroupLevel 读回来和你说的一致,未参与分组的表头确实是 0。 有两点觉得特别实用:一是多级嵌套那里强调「先外层再内层」,顺序反了层级就会不对;二是汇总行位置那段,把 IsSummaryRowBelow 说成只影响折叠按钮朝向、不改数据顺序,这个提醒挺关键,很多人容易把它当成排序开关。 不过帖子到「六、列分组:把中间的列收起来」这里就断了,光看到「入」字,后面 GroupByColumns 的具体参数和示例还没贴出来。方便的话可以补一下列分组这段,特别是列号起止、CollapseGroup 里 GroupByType.ByColumns 的用法,以及列分组时汇总列方向有没有对应的设置。另外想顺带问一句:同一张表上行分组和列分组能不能混用,层级按钮会怎么显示?
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python对Excel工作表行分组与列分组:折叠展开、多级嵌套与汇总

这篇整理得挺清楚,先讲对象模型和各部分分工,再落到 GroupByRows 的行号从 1 起算、RowGroupLevel 读层级、第三个参数控制建组时是否折叠这些容易踩坑的点,很实用。基础行分组、多级嵌套以及 CollapseGroup / ExpandGroup 的示例也比较直观,IsSummaryRowBelow 只改变折叠标记朝向、不影响数据顺序这个提醒很到位。 看到第六部分“列分组”刚开头就断了,期待把 GroupByColumns 的示例、列层级读回以及行分组和列分组叠加时的表现补完。另外如果后续能说明一下建组保存后重新打开时折叠状态是否保留,就更完整了。
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python对Excel工作表行分组与列分组:折叠展开、多级嵌套与汇总

收藏了,行分组这块讲得挺清楚的。几个地方我印象比较深:一是 GroupByRows 的第三个参数是按组分别生效的,而不是全局开关,这样建组时就能把「这组收起、那组展开」一次定好,比建完再一个个调省事;二是明确提醒了行号是工作表真实行号、从 1 起算,这点和按区域偏移的参数容易混,写脚本时确实摔过跟头;三是 IsSummaryRowBelow 只改大纲按钮的朝向、不动数据顺序,这个区分说得很到位,很多人会误以为是把汇总行挪位置。 还有 CollapseGroup 和 ExpandGroup 用 GroupByType.ByRows 指定方向、作用于范围所在层级那段,配合「折叠内层时外层随之收起」的说明,理解起来比较顺。批量报表里建组时全收起、再按当期需要展开一两层的做法也很实用,回头可以试试。 不过帖子末尾好像截断了,「列分组:把中间的列收起来」刚起头就没了,列方向的 GroupByColumns 参数、和 CollapseGroup 配合的用法还想看看,方便的话补完这部分吧。另外顺带问一句,行分组和列分组同时存在时,左上角的层级按钮是分开显示还是合并的,这个在宽表场景下挺影响观感的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-9 04:51 , Processed in 0.021209 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部