EasyExcel多层表头
EasyExcel实现多层表头:注解与列表两种方式详解
在复杂报表场景中,多层表头(如 “基础信息” 包含 “姓名”“手机号” 等子列)能更清晰地组织数据。EasyExcel 提供了简洁的 API 支持多层表头,本文将详细讲解两种实现方式(注解方式和列表方式),并对比其适用场景,帮助你快速实现类似 Excel 数据透视表的表头结构。
多层表头的核心原理
多层表头本质是多级列标题的合并与嵌套,例如 “基础信息” 作为一级标题,其下包含 “姓名”“手机号” 等二级标题。EasyExcel 通过以下方式实现:
- 层级定义:用数组或列表的嵌套结构表示表头层级(如
{"基础信息", "姓名"}表示两级表头); - 自动合并:相同的上级标题会自动合并单元格(如 “基础信息” 会跨列合并其所有子列)。
环境准备
引入 EasyExcel 依赖(兼容 2.x 和 3.x 版本):
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.0</version>
</dependency>
实现方式详解
注解方式(推荐用于固定表头)
通过 @ExcelProperty 注解的 value 属性定义多层表头,适用于表头结构固定的场景(如实体类与表头一一对应)。
定义实体类
在实体类的字段上使用 @ExcelProperty(value = {一级标题, 二级标题, ...}) 定义多层表头:
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
public class UserInfo {
// 二级表头:基础信息 -> 姓名
private String name;
// 二级表头:基础信息 -> 手机号
private String phone;
// 二级表头:基础信息 -> 年龄
private Integer age;
// 二级表头:其他信息 -> 教育经历
private String education;
// 二级表头:其他信息 -> 工作经历
private String workExperience;
}
value属性:数组元素依次表示从一级到 N 级的表头名称;index属性:指定列的顺序(0 开始),确保表头按预期排列。
生成 Excel
直接将实体类作为表头类传入 EasyExcel.write() 方法:
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
public class MultiLevelHeaderDemo {
public static void main(String[] args) {
String filePath = "多层表头_注解方式.xlsx";
// 准备测试数据(可选,此处为空列表仅生成表头)
List<UserInfo> dataList = new ArrayList<>();
// dataList.add(new UserInfo("张三", "13800138000", 25, "本科", "3年"));
// 写入 Excel,表头由 UserInfo 类的 @ExcelProperty 定义
EasyExcel.write(filePath, UserInfo.class)
.sheet("用户信息表") // Sheet 名称
.doWrite(dataList); // 写入数据(空列表则仅生成表头)
System.out.println("文件生成成功:" + filePath);
}
}
列表方式(推荐用于动态表头)
通过 List<List<String>> 手动定义表头层级,适用于表头结构动态生成的场景(如根据数据库配置动态调整表头)。
构建表头列表
外层 List 代表列的集合,内层 List 代表每列的多级表头:
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
public class DynamicHeaderDemo {
public static void main(String[] args) {
String filePath = "多层表头_列表方式.xlsx";
// 1. 构建多层表头(List<List<String>>)
List<List<String>> headers = new ArrayList<>();
// 第一列:基础信息 -> 姓名
List<String> col1 = new ArrayList<>();
col1.add("基础信息");
col1.add("姓名");
headers.add(col1);
// 第二列:基础信息 -> 手机号
List<String> col2 = new ArrayList<>();
col2.add("基础信息");
col2.add("手机号");
headers.add(col2);
// 第三列:基础信息 -> 年龄
List<String> col3 = new ArrayList<>();
col3.add("基础信息");
col3.add("年龄");
headers.add(col3);
// 第四列:其他信息 -> 教育经历
List<String> col4 = new ArrayList<>();
col4.add("其他信息");
col4.add("教育经历");
headers.add(col4);
// 第五列:其他信息 -> 工作经历
List<String> col5 = new ArrayList<>();
col5.add("其他信息");
col5.add("工作经历");
headers.add(col5);
// 2. 准备数据(数据结构需与表头列顺序对应)
List<List<Object>> dataList = new ArrayList<>();
// 示例数据行:[姓名, 手机号, 年龄, 教育经历, 工作经历]
List<Object> dataRow = new ArrayList<>();
dataRow.add("张三");
dataRow.add("13800138000");
dataRow.add(25);
dataRow.add("本科");
dataRow.add("3年");
dataList.add(dataRow);
// 3. 写入 Excel,表头由 headers 定义
EasyExcel.write(filePath)
.head(headers) // 设置动态表头
.sheet("用户信息表") // Sheet 名称
.doWrite(dataList); // 写入数据
System.out.println("文件生成成功:" + filePath);
}
}
- 数据结构:
List<List<Object>>中,内层List的元素顺序需与表头列顺序一致; - 灵活性:可根据业务需求动态增删表头列(如从数据库查询表头配置后构建
headers列表)。
扩展:三级及以上表头
EasyExcel 支持任意层级的表头,只需在注解数组或列表中增加层级即可。
示例:三级表头
注解方式
public class OrderInfo {
// 三级表头:订单信息 -> 基本信息 -> 订单号
private String orderNo;
// 三级表头:订单信息 -> 金额信息 -> 总金额
private BigDecimal totalAmount;
}
列表方式
List<List<String>> headers = new ArrayList<>();
// 三级表头:订单信息 -> 基本信息 -> 订单号
List<String> col1 = new ArrayList<>();
col1.add("订单信息");
col1.add("基本信息");
col1.add("订单号");
headers.add(col1);
// ... 其他列
两种方式的对比与适用场景
| 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 注解方式 | 代码简洁,与实体类绑定,可读性强 | 表头固定,无法动态修改 | 表头结构固定的报表(如固定模板) |
| 列表方式 | 支持动态生成表头,灵活性高 | 代码较繁琐,需手动维护列顺序 | 表头动态变化的场景(如配置化报表) |
常见问题与解决方案
1. 表头合并异常(上级标题未跨列合并)
- 原因:同级表头的上级标题名称不一致(如 “基础信息” 与 “基础信息 ”(含空格)被视为不同标题);
- 解决:确保同一组的上级标题字符串完全一致(无空格、大小写差异)。
2. 数据与表头列顺序不匹配
- 原因:注解方式中
index属性未按顺序设置,或列表方式中数据行元素顺序与表头列顺序不一致; - 解决:
- 注解方式:严格按列顺序设置
index = 0, 1, 2...; - 列表方式:数据行
List<Object>的元素顺序必须与headers列表的列顺序一一对应。
- 注解方式:严格按列顺序设置
3. 表头层级显示错乱
- 原因:表头层级深度不一致(如部分列是二级,部分列是三级);
- 解决:确保所有列的表头层级深度统一,或接受不同层级的显示效果(EasyExcel 会自动对齐空白单元格)。