核心是用循环嵌套构造动态表头结构并分段写入多个table,easyexcel的table机制天然支持每子表独立表头与数据源,无需手动计算行号或合并单元格。

用循环嵌套动态生成多级表头的Excel报表,核心不是“写循环”,而是用循环构造表头结构、组织数据块,并按顺序写入多个逻辑独立的子表。EasyExcel 的 Table 机制天然适配这种场景——每个子表可拥有自己的动态表头和数据源,无需手动计算行号或合并单元格。
一、明确多级表头的层级逻辑
多级表头本质是二维结构:行数代表层级深度,每行的列数决定该层字段宽度。例如“部门 → 小组 → 姓名”是三级表头,对应三行;若“华东”下有3个小组,“华北”下有2个,则第二行需体现分组跨度,第三行才填具体姓名列。循环嵌套的作用,就是按业务规则逐层展开这些分支。
- 外层循环遍历一级维度(如区域、时间周期、产品大类)
- 中层循环处理二级结构(如各区域下的部门或时间段内的子周期)
- 内层循环生成叶子列(如每个部门下的具体指标:“销售额”、“完成率”、“同比”)
二、用 List> 构建动态表头
EasyExcel 接收表头的方式是 List<list>></list>,每一层 list 对应表头的一行。循环嵌套在此处直接映射为代码结构:
- 初始化空的
header = new ArrayList() - 第一行(顶层标题):添加固定内容,如
Arrays.asList("2026年Q2销售汇总"),并用CellRangeAddress后续合并(需自定义 WriteHandler) - 第二行(主分组):遍历区域列表,每个区域重复 N 次(N=其下属子项数),构成横向分组栏
- 第三行(明细指标):对每个子项,添加其全部指标列名,如 "订单量"、"GMV"、"退货率"
关键点:同一行中相邻相同内容需保持列数一致,否则 EasyExcel 无法自动合并;如需跨列合并,必须配合 HorizontalCellStyleStrategy 或自定义 WriteHandler 处理单元格样式与合并逻辑。
三、单 Sheet 内分段写入多个 Table
不要试图在一个 write() 中塞入全部数据。正确做法是:一个 Sheet 写多次,每次写一个 Table,每个 Table 携带自己生成的表头和对应数据块。
- 调用
EasyExcel.write(outputStream).sheet().doWrite(data)只适用于单表头+单数据集 - 多子表必须用
ExcelWriter+ 多次write(..., writerTable) - 每个
writerTable需指定起始行号(.tableNo(0).needHead(true).head(header)),避免覆盖 - 示例:第一个 Table 从第0行开始,第二个 Table 从第 header.size() + data1.size() + 2 行开始(预留空行分隔)
四、动态数据匹配与填充控制
表头动态了,数据也得对齐。不能直接传 List<yourentity></yourentity>,而应构造与表头列顺序严格对应的 List<list>></list>。
- 外层循环确定当前处理哪一组数据(如“华东区”)
- 中层循环取出该组所有子维度(如“上海仓”、“杭州仓”)
- 内层循环为每个子维度生成一行数据,按第三行表头顺序依次填值(可用 Map.get(key) 或反射取值)
- 若某列无数据,填
null或空字符串,EasyExcel 会正常渲染空白单元格
不复杂但容易忽略:列顺序必须与表头 list 的顺序完全一致,错一位整行就偏移。建议封装一个 buildRow(List<string> headerRow, Map<string object> dataMap)</string></string> 工具方法统一处理。











