Skip to content

7 设置多行表头

guanquan.wang edited this page Jan 7, 2025 · 5 revisions

EEC从v0.5.3开始支持多表头导出,同样的可以使用注解或者手动指定两种方式,最多支持1024层。

使用注解

Java Bean可以使用多个ExcelColumn来实现,多个ExcelColumn的顺序与导出的最终表头完全一致,具体示例如下:

@ExcelColumn("订单号")
private String orderNo;

@ExcelColumn("收件人")
private String recipient;

@ExcelColumn("收件地址")
@ExcelColumn("省")
private String province;

@ExcelColumn("收件地址")
@ExcelColumn("市")
private String city;

@ExcelColumn("收件地址")
@ExcelColumn("区")
private String area;

@ExcelColumn("收件地址")
@ExcelColumn("详细地址")
private String detail;

定义如上Java实体,在‘省’,‘市’,‘区’,和‘详细地址‘4个属性上面加了一个共同的父表头‘收件地址’,效果如下

Repeat Columns Annotation

更为复杂的示例

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn
@ExcelColumn("订单号")
private String orderNo;

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn
@ExcelColumn("收件人")
private String recipient;

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn("收件地址")
@ExcelColumn("省")
private String province;

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn("收件地址")
@ExcelColumn("市")
private String city;

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn("收件地址")
@ExcelColumn("区")
private String area;

@ExcelColumn("TOP")
@ExcelColumn
@ExcelColumn("收件地址")
@ExcelColumn("详细地址")
private String detail;

我们在头顶再加一个共同的表头‘TOP’,展示效果如下

Repeat Columns Annotation2

手动添加

Column增加addSubColumn方法用于添加子表头,顺序与注解相似,第一个在最上面最后一个需要指定字段名。这种方式多用于ListMapSheet和ResultSetSheet

new Workbook().addSheet(new ListSheet<>(data
    , new Column("姓名", "name")
    , new Column("性别", "sex")
    , new Column("证书").addSubColumn(new Column("编号", "no"))
    , new Column("证书").addSubColumn(new Column("类型", "type"))
    , new Column("证书").addSubColumn(new Column("等级", "level"))
    , new Column("年龄", "age")
    , new Column("教育").addSubColumn(new Column("教育1", "jy1"))
    , new Column("教育").addSubColumn(new Column("教育2", "jy2"))))
    .writeTo(Paths.get("F:/excel"));

multi-header2

读取带多行表头的文件

v0.5.6开始EEC支持指定表头位置,你可以通过Sheet#header(fromRowNum, toRowNum)来指定表头,header方法支持fromRowNumtoRowNum两个参数,为了更加直观这两个参数均从1开始,和打开excel所看到的一样,同时from和to两端都是包含的,对于多行表头来说header将以A1:A2:A3这种格式进行纵向拼接

我们拿上面【手动添加】的文件为例子来展示如何使用header来支持多表头,我们只需要设置header(1, 2)指定两行表头即可reader.sheet(0).header(1, 2).dataRows().map(Row::toMap).forEach(System.out::println),通过这个命令可输入如下结果

{姓名=暗月月, 性别=男, 证书:编号=1, 证书:类型=数学, 证书:等级=3, 年龄=30, 教育:教育1=教育a, 教育:教育2=教育b}
{姓名=暗月月, 性别=男, 证书:编号=2, 证书:类型=语文, 证书:等级=1, 年龄=30, 教育:教育1=教育a, 教育:教育2=教育c}
{姓名=暗月月, 性别=男, 证书:编号=3, 证书:类型=历史, 证书:等级=1, 年龄=30, 教育:教育1=教育b, 教育:教育2=教育c}
{姓名=张三, 性别=女, 证书:编号=1, 证书:类型=英语, 证书:等级=1, 年龄=20, 教育:教育1=教育d, 教育:教育2=教育d}
{姓名=张三, 性别=女, 证书:编号=5, 证书:类型=物理, 证书:等级=7, 年龄=20, 教育:教育1=教育x, 教育:教育2=教育x}
{姓名=李四, 性别=男, 证书:编号=2, 证书:类型=语文, 证书:等级=1, 年龄=24, 教育:教育1=教育c, 教育:教育2=教育a}
{姓名=李四, 性别=男, 证书:编号=3, 证书:类型=历史, 证书:等级=1, 年龄=24, 教育:教育1=教育b, 教育:教育2=教育c}
{姓名=王五, 性别=男, 证书:编号=1, 证书:类型=高数, 证书:等级=2, 年龄=28, 教育:教育1=教育c, 教育:教育2=教育a}
{姓名=王五, 性别=男, 证书:编号=2, 证书:类型=JAvA, 证书:等级=3, 年龄=28, 教育:教育1=教育b, 教育:教育2=教育c}

我们可以看到中间合并的表头表现为证书:编号, 证书:类型, 证书:等级,如果Java bean使用EEC注解的话也可以直接转对象reader.sheet(0).header(1, 2).dataRows().map(row -> row.to(Order.class)).forEach(Print::println)和单行表头完全一样

自定义表头

v0.5.6同样也支持自定义表头,如果自动解析表头有问题则可以设置自定义表头

// 创建自定义表头
org.ttzero.excel.reader.Row headerRow2 = new org.ttzero.excel.reader.Row() {};
Cell[] cells2 = new Cell[8];
cells2[0] = new Cell((short) 1).setSv("姓名");
cells2[1] = new Cell((short) 2).setSv("性别");
cells2[2] = new Cell((short) 3).setSv("证书:编号");
cells2[3] = new Cell((short) 4).setSv("证书:类型");
cells2[4] = new Cell((short) 5).setSv("证书:等级");
cells2[5] = new Cell((short) 6).setSv("年龄");
cells2[6] = new Cell((short) 7).setSv("教育:教育1");
cells2[7] = new Cell((short) 8).setSv("教育:教育2");
headerRow2.setCells(cells2);
// 使用自定义表头
reader.sheet(0).reset().header(2).bind(Object.class, new HeaderRow().with(2, headerRow2))
        .rows().map(Row::toMap).forEach(System.out::println);