前言:在项目开发中,我们有时候会遇到自定义表头样式的需求。EasyExcel官方文档中关于表头样式的说明有两种(以设置表头颜色为例):

  • 方式1:通过使用注解来设置颜色(优点:使用非常方便,缺点:对于复杂表头就无能为力了,例如无法单独设置父表头和子表头的颜色)
  • 方式2:通过使用HorizontalCellStyleStrategy 策略的方式来设置表头颜色(优点:通过此策略可以对表头设置更多的样式,缺点:但此策略的应用对象是所有表头,这意味着无法单独对单个的表头进行个性化设置)。
  • 因此,本文想提供一种可行的且更加全面的表头样式设置方式,即自定义策略
1. 源码分析

通过类图我们不难发现,HorizontalCellStyleStrategy 类继承了AbstractCellStyleStrategy抽象类,而此抽象类中有三个抽象方法,其中与标题头部样式有关的是setHeadCellStyls这个抽象方法,那么这个方法又是何时调用的呢?我们进一步到AbstractCellStyleStrategy类中查看。

可以看到,在afterCellDispose方法中有对setHeadCellStyls的调用,当传入的是表头时,就会执行此方法来设置表头样式,否则就是对单元格的内容进行样式设置。

现在,我们再来看看HorizontalCellStyleStrategy 类是如何实现具体实现这些抽象方法的:

  • HorizontalCellStyleStrategy 类中的属性及构造方法


可以看到,HorizontalCellStyleStrategy 类定义了两种类型的属性方框1中的属性是属于EasyExcel的样式对象,方框2中的属性是属于POI的,从这里我们不难发现,HorizontalCellStyleStrategy 构造方法中传入的EasyExcel的样式对象,最终都要转换成POI的对象。那么在哪里进行转换呢?请看下面这段代码。

  • 抽象方法ininCellStyle的实现

上图中的initCellStyle方法,就是此策略进行对象转换的地方。通过StyleUtil工具类将EasyExcel对象转换成POI对象。值得注意的是,在代码调试的时我发现此方法只会执行一次,即在内容填充前进行样式的初始化,之后就不会执行了。 当然也可以在其父类AbstractCellStyleStrategy中发现此方法的调用时机。如下图所示:

  • 抽象方法setHeadCellStyle的实现

头部的具体样式都在这里进行设置,那么此方法又是何时调用的呢?

通过调用可以看到,当所有对Cell的操作都执行完之后,就会调用此方法,如果Cell是头,则执行头部样式方法,如果是内容则执行内容样式方法。至此,HorizontalCellStyleStrategy 类就分析完了。我们要想自定义策略就可以把HorizontalCellStyleStrategy 类当做参考对象

2. 自定义样式策略的实现
  • 基本思路:实现一个可以自定义表头样式的对象、实现一个可以处理此样式集合的策略、写Excel
  • 复杂表头样式对象【用于存储当表头的自定义样式信息】
/*** 复杂表头样式信息,包含需要自定义的表头坐标及样式** @Author: nxf* @Date: 2021/1/17 20:32*/
public class ComplexHeadStyles  {/***   表头横坐标 - 行* */private Integer x;/***   表头纵坐标 - 列* */private Integer y;/***   内置颜色* */private Short indexColor;public ComplexHeadStyles(Integer x, Integer y, Short indexColor){this.x=x;this.y=y;this.indexColor=indexColor;}private void setCroods(Integer x,Integer y){this.x=x;this.y=y;}public Integer getX() {return x;}public void setX(Integer x) {this.x = x;}public Integer getY() {return y;}public void setY(Integer y) {this.y = y;}public Short getIndexColor() {return indexColor;}public void setIndexColor(Short indexColor) {this.indexColor = indexColor;}
}
  • 自定义样式策略
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.util.StyleUtil;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import com.study.poi.utils.styles.ComplexHeadStyles;
import org.apache.poi.ss.usermodel.*;import java.util.concurrent.ArrayBlockingQueue;/*** 自定义样式拦截器-复杂表头样式的使用** @Author: nxf* @Date: 2021/1/17 14:31*/
public class HeadStyleWriteHandler extends AbstractCellStyleStrategy {/***   复杂表头自定义样式队列,先进先出,方便存储* */private ArrayBlockingQueue<ComplexHeadStyles> headStylesQueue;/***   WorkBoot* */private Workbook workbook;/***   构造方法,创建对象时传入需要定制的表头信息队列**/public HeadStyleWriteHandler(ArrayBlockingQueue<ComplexHeadStyles> headStylesQueue){this.headStylesQueue=headStylesQueue;}@Overrideprotected void initCellStyle(Workbook workbook) {// 初始化信息时,保存Workbook对象,转换时需要使用    this.workbook=workbook;}@Overrideprotected void setHeadCellStyle(Cell cell, Head head, Integer relativeRowIndex) {WriteCellStyle writeCellStyle=new WriteCellStyle();if(headStylesQueue !=null && ! headStylesQueue.isEmpty()){ComplexHeadStyles complexHeadStyle=headStylesQueue.peek();// 取出队列中的自定义表头信息,与当前坐标比较,判断是否相符if(cell.getColumnIndex() == complexHeadStyle.getY() && relativeRowIndex.equals(complexHeadStyle.getX())){// 设置自定义的表头样式writeCellStyle.setFillForegroundColor(complexHeadStyle.getIndexColor());// 样式出队headStylesQueue.poll();}}// WriteCellStyle转换为CellStyleCellStyle headCellStyle = StyleUtil.buildHeadCellStyle(workbook, writeCellStyle);// 设置表头样式cell.setCellStyle(headCellStyle);}@Overrideprotected void setContentCellStyle(Cell cell, Head head, Integer relativeRowIndex) {}}
  • Excel写对象类
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.study.poi.utils.SexConverterForStudentInfo;
import lombok.Data;import java.time.LocalDateTime;/*** 学生信息导出-复杂表头-特殊表头样式【单独设置表头样式】(Excel类)** @Author: nxf* @Date: 2021/1/12 23:07*/
@Data
@HeadRowHeight(20)
@ColumnWidth(25)
@ContentRowHeight(20)
public class StudyPoiComplexHeadStyleWriteExportDTO {/*** 学号ID,主键ID* note 复杂表头使用这样的方式即可* note 复杂表头无法使用注解【@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 14)】来达到满意的效果,其设定的样式会把学生基本信息和学号都设置为同样的颜色,无法单独设置,需另行处理*/@ExcelProperty({"学生基本信息", "学号"})private Long studentId;/*** 学生姓名*/@ExcelProperty({"学生基本信息", "姓名"})private String studentName;/*** 出生日期  */@ExcelProperty(value = "出生日期")private String studentBirthday;/*** 性别     */@ExcelProperty(value = "性别")private String studentSex;/*** 年级*/@ExcelProperty(value = "年级")private Integer studentGrade;/*** 班级*/@ExcelProperty(value = "班级")private Integer studentClass;
}
  • 写Excel
      /*** 复杂表头-自定义表头样式导出-学生信息表** @param response = 浏览器响应对象* @return: void* @Author: nxf* @Date: 2021/1/17 14:59*/@PostMapping("/complexHeadStyleExportStudentInfo")public void complexHeadStyleExportStudentInfo(HttpServletResponse response) throws IOException{try {// 查询导出的学生信息表数据List<StudyPioStudentDTO> studyPioStudents=studentInfoExportService.searchAllStudentInfo();// 字符编码String encode="utf-8";// 文件名String fileName=URLEncoder.encode("复杂表头-自定义表头样式导出",encode).replaceAll("\\+","%20");// response三部曲 1.设置响应文件类型 2.设置响应编码 3.设置响应文件拓展名response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding(encode);response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");// 设置表头样式队列【先进先出】ArrayBlockingQueue<ComplexHeadStyles> complexHeadStylesArrayBlockingQueue=new ArrayBlockingQueue<>(4);/***    (0,0)和(0,1)位置的单元格设置背景色为红色;(1,0)设置为绿色;(1,1)设置为蓝色*    写Excel是一行一行写的,因此入队顺序是这样*/complexHeadStylesArrayBlockingQueue.add(new ComplexHeadStyles(0,0,IndexedColors.RED1.getIndex()));complexHeadStylesArrayBlockingQueue.add(new ComplexHeadStyles(0,1,IndexedColors.RED1.getIndex()));complexHeadStylesArrayBlockingQueue.add(new ComplexHeadStyles(1,0,IndexedColors.LIGHT_GREEN.getIndex()));complexHeadStylesArrayBlockingQueue.add(new ComplexHeadStyles(1,1,IndexedColors.SKY_BLUE.getIndex()));// 自定义表头策略HeadStyleWriteHandler headStyleWriteHandler=new HeadStyleWriteHandler(complexHeadStylesArrayBlockingQueue);// 写ExcelEasyExcelFactory.write(response.getOutputStream(), StudyPoiComplexHeadStyleWriteExportDTO.class).registerWriteHandler(headStyleWriteHandler).autoCloseStream(true).sheet("自定义学生信息表头颜色").doWrite(studyPioStudents);}catch (Exception e){errorReturn(response);}}
3. 导出效果:

通过以上方式,我们就能够单独定义表头的样式啦!!!

EasyExcel--自定义表头(标题)样式策略相关推荐

  1. EasyExcel自定义表头导出模板并封装数据下拉选择

    EasyExcel自定义表头导出模板 首先查询可变数据 动态数据Controller 表头封装 定义导出模板时的下拉数据 最终结果 首先查询可变数据 动态数据Controller @ApiOperat ...

  2. easyExcel自定义表头导出

    当页面列表数据过多,而我们真实需要导出Excel表格的列没有那么多时,则需要支持,仅导出用户选定的列,老样子直接上图上代码. 如:页面全量数据如图,有9列 但实际上,业务有时只需要三列,每次下载后,还 ...

  3. EasyExcel自定义表头

    表头可以根据业务进行设置,然后后续赋值对应的值. @Testpublic void easyExcelTest() {List<List<String>> heads = Li ...

  4. element自定义el-dialog标题样式,实现在title部分放置按钮

    如图,需求是在title的右边有一个[编辑]按钮 此时需要自定义title部分的内容,而不是直接使用官方给的格式. <el-dialog :visible.sync="pr_dialo ...

  5. pandas输出excel文件添加表头标题,样式装饰器

    以下装饰器将输出带有样式的excel文件. import os import pandas as pd from xlsxwriter.utility import xl_rangedef decor ...

  6. EasyExcel复杂表头的导出样式自定义(字体,大小,主副标题不同底色,行高)

    效果预览 设置表头的行高有0.1的误差,按理说我设置的应该是17.7,但是实际出来excel中是17.8 准备工作 项目结构 导入easyExcel的依赖 <dependency>< ...

  7. Easy Excel生成压缩包文件,自定义表头样式

    Excel 文件内容形如下图! 需求场景 导出超10w左右的数据,涉及 源数据查. 组装业务数据 解析数据库中的json数据内容,并组装相应的信息 生成Excel文件内容到磁盘 将文件压缩,并写回到浏 ...

  8. EasyExcel自定义复杂的表头并在同sheet中实现分页

    文章目录 前言 一.EasyExcel导出 1.关键代码 2.测试 3.导出结果展示 总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 自定义表头导出excel,并在同sheet中进行分页 ...

  9. easyexcel 检查表头是否匹配_利用easyexcel生成excel文件-自定义表头与数据栏对应的处理方式...

    前面几篇文章测试过用easyexcel生成动态表头,动态样式.特别是动态表头以及下面数据列表与表头字段的对应是采用注解方式实现的.但在实际工作中,有些到处是灵活生成的,也就是说对于同一个类,在不同的场 ...

最新文章

  1. Vue.js框架简单读取数据库信息并渲染完成news新闻文章列表以及detail详情页功能(小试牛刀)
  2. Java垃圾回收(GC)机制详解
  3. 手工、工具分别实现cookie注入
  4. cs架构嵌入bs_车牌识别CS架构和BS架构详解
  5. 我来告诉你为什么中国民营企业管理失败的原因!
  6. 5位院士谈科研瓶颈:必须“逼着自己在精神上愿意吃苦”
  7. java socket 包头包体_使用JAVA上抓取Socket服务端和客户端通信TCP数据包
  8. FPGA异步复位设计代码
  9. 实用技巧:快速定位Zuul的性能瓶颈
  10. 东北老家有人在大连娶了媳妇
  11. docker启动nginx后挂了_使用docker启动nginx并挂载配置nginx
  12. 全国计算机考试一级在线模拟考试系统,全国计算机等级考试模拟系统全国计算机等级考试一级模拟试题和答案.doc...
  13. 使用广告终结者屏蔽页面的任意部分
  14. CRISC风险及信息系统监控认证
  15. 你想要的宏基因组-微生物组知识全在这(1905)
  16. CSS 实现面包屑导航
  17. VSCode插件之Beautify
  18. MATLAB神经网络43个案例分析
  19. 小程序源码:2022强大的修复版趣味心理测试小程序源码,趣味测试引流裂变神器-多玩法安装简单
  20. 计算机镜像怎么恢复,教你如何在win7系统创建系统恢复镜像

热门文章

  1. 爬虫进阶:反反爬虫技巧
  2. 有用的vscode快捷键大全+自定义快捷键
  3. CSMA/CA协议详解
  4. 2017计算机专业职称,2017年计算机职称考试题目及答案
  5. Redis(含Redis安装,CMD命令,使用Redis编程,缓存预热,计划任务)
  6. 【计算机组成原理】实验5:运算器实验
  7. 新加坡数字银行牌照争夺战:蚂蚁、小米、腾讯、头条等21家,谁能取胜?
  8. mikrotik基础功能配置
  9. 请教大侠如何用c语言编写搬家的简单程序
  10. 有人到农村收“废旧手机”,用手机换盆,收来做什么?