EasyExcel导出自定义表格

谈到新技术,每个人都会有点恐惧,怕处理不好。确实,第一次使用新技术会遇到很多坑,这次使用 EasyExcel 这个新技术去做 excel 导出,还要给表格加样式,遇到不同的版本问题,遇到颜色加错了地方,反正各种效果都打不到自己想要的那种,幸好最终看文档解决了,特此写下这篇博客。

EasyExcel导出自定义表格

  • 一、导入依赖
  • 二、原理分析
  • 三、上代码

一、导入依赖

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version>
</dependency>

二、原理分析

  1. 对于 read 函数主要通过流操作获取
    在这里插入图片描述
    对于 EasyExcel.read 方法中常用的一个 read 函数:

    java">EasyExcel.read(fileName, head, readListener).sheet().doRead();
    

    三个参数如下:

    • fileName:Excel 文件的路径或输入流。
    • head:Excel 表头对应的实体类,定义了 Excel 表的结构。
    • readListener:数据读取的监听器,定义了读取数据的逻辑。
  2. Excel 表头的实体类

    在读取 Excel 文件时,需要定义一个实体类来映射 Excel 表头,每个字段对应一个表头列。这个实体类用于指定数据在 Java 对象中的存储结构。

    java">public class ExcelData {private String name;private Integer age;// 其他字段...// 省略 getter 和 setter 方法
    }
    
  3. 数据读取监听器

    EasyExcel 提供了 AnalysisEventListener 类来处理 Excel 数据的读取。

    需要集成该类,并实现 invoke 方法来处理每一行数据的读取逻辑,以及 doAfterAllAnalysed 方法来处理所有数据解析完成后的逻辑。

    public class ExcelDataListener extends AnalysisEventListener<ExcelData> {@Overridepublic void invoke(ExcelData data, AnalysisContext context) {// 处理每一行数据的逻辑System.out.println("Read data: " + data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 所有数据解析完成后的逻辑}
    }
    
  4. Excel 写入

    EasyExcel 也提供了写入 Excel 文件的功能。可以使用 EasyExcel.write 方法来配置写入参数,然后调用 sheet 方法指定写入的 sheet,最后调用 doWrite 方法执行写入操作。

    EasyExcel.write(fileName, head).sheet("Sheet1").doWrite(dataList);
    

    三个参数如下:

    • fileName:写入的 Excel 文件路径。
    • head:Excel 表头对应的实体类。
    • dataList:要写入的数据列表。dataList 是一个 List 集合,其中的元素是实体类的对象。
  5. Excel 写入监听器

    写入 Excel 文件时进行一些额外的处理,可以使用写入的监听器 WritHandler。

    public class ExcelWriteHandler implements WriteHandler {@Overridepublic void sheet(int sheetNo, Sheet sheet) {// 对每个 sheet 进行处理的逻辑}@Overridepublic void row(int rowNum, Row row) {// 对每一行进行处理的逻辑}@Overridepublic void cell(int cellNum, Cell cell) {// 对每个单元格进行处理的逻辑}
    }
    

在写入 Excel 文件时,通过 excelWriter.registerWriterHandler( new ExcelWriterHandler() ) 注册写入监听器即可。

三、上代码

先看要求
在这里插入图片描述
其实这里的大部分样式,都可以参考 EasyExcel API 文档

导出

@Overridepublic void importUserSign(ImportUserSignReq req, HttpServletResponse response) {String projectName = req.getProjectName();String time = req.getTime();// 查询第一页数据List<SignTemplate1> data1 = new ArrayList<>();data1.add(new SignTemplate1().setE1("序号").setE2("成员姓名").setE3("签到次数").setE4("补签次数").setE5("签到总工时").setE6("最后签到时间"));data1.addAll(getData1(req));// 查询第二页数据List<SignTemplate2> data2 = getData2(req, getData1(req));Integer maxRow = data2.stream().map(SignTemplate2::getE2).max(Integer::compare).orElse(0); //获取最大行try {// 指定文件名
//            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//            response.setCharacterEncoding("utf-8");
//            String fileName = URLEncoder.encode("签到模板导出.xlsx", "UTF-8");
//            response.setHeader("Content-disposition", "attachment;filename*=" + fileName);String fileName = "E:\\excel\\" + "签到模板导出" + System.currentTimeMillis() + ".xlsx";ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();// 第一页// 自定义头部样式WriteCellStyle headWriteCellStyle1 = new WriteCellStyle();headWriteCellStyle1.setFillForegroundColor(IndexedColors.GOLD.getIndex()); //背景颜色-黄色headWriteCellStyle1.setHorizontalAlignment(HorizontalAlignment.LEFT); //左对齐// 自定义内容样式WriteCellStyle contentWriteCellStyle1 = new WriteCellStyle();// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现HorizontalCellStyleStrategy style1 = new HorizontalCellStyleStrategy(headWriteCellStyle1, contentWriteCellStyle1);// sheet命名WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "项目名称").registerWriteHandler(style1) //自定义策略.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) //自动列宽.head(getHead("【"+projectName+"】", time, 6)) //动态表头.head(SignTemplate1.class).build();// 写入第一页excelWriter.write(data1, writeSheet1);// 第二页// 自定义头部样式WriteCellStyle headWriteCellStyle2 = new WriteCellStyle();headWriteCellStyle2.setFillForegroundColor(IndexedColors.GOLD.getIndex()); //背景颜色-黄色headWriteCellStyle2.setHorizontalAlignment(HorizontalAlignment.LEFT); //左对齐// 自定义内容样式WriteCellStyle contentWriteCellStyle2 = new WriteCellStyle();contentWriteCellStyle2.setHorizontalAlignment(HorizontalAlignment.RIGHT); //右对齐// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现HorizontalCellStyleStrategy style2 = new HorizontalCellStyleStrategy(headWriteCellStyle2, contentWriteCellStyle2);// sheet命名WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "签到明细").registerWriteHandler(style2) //自定义策略.registerWriteHandler(new CustomCellWriteHandler(maxRow, (data2.size()+1))) //自定义动态行/列背景颜色.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) //自动列宽.head(getHead("【"+projectName+"】", time, (data2.size()+1))) //动态表头.build();// 写入第二页excelWriter.write(dataList(data2, maxRow), writeSheet2).close();}catch (Exception e){e.printStackTrace();throw new CustomException("导出失败");}}

动态标题头

private List<List<String>> getHead(String projectName, String time, Integer num) {List<List<String>> list = new ArrayList<List<String>>();for (int i = 0; i < num; i++) {list.add(Arrays.asList(projectName, time));}return list;
}

动态填充数据

private List<List<Object>> dataList(List<SignTemplate2> data2, Integer maxRow) {List<List<Object>> list = new ArrayList<>();List<Object> row1 = ListUtils.newArrayList(); //第一行List<Object> row2 = ListUtils.newArrayList(); //第二行row1.add("成员名称");row2.add("签到次数");for (int i = 0; i <data2.size(); i++) { //行内每一列数据row1.add(data2.get(i).getE1());row2.add(data2.get(i).getE2());}list.add(row1);list.add(row2);for (int i = 0; i < maxRow; i++) {List<Object> row3 = ListUtils.newArrayList(); //第三行-多条List<Object> row4 = ListUtils.newArrayList(); //第四行-多条row3.add(null);row4.add(null);for (int j = 0; j <data2.size(); j++) { //行内每一列数据List<SignTemplate3> eList = data2.get(j).getEList();//当前列的签到集合if (i < eList.size()) {row3.add(eList.get(i).getE2()+"  "+eList.get(i).getE1());row4.add(ObjectUtil.isNotNull(eList.get(i).getE3())?eList.get(i).getE3():"暂无");}else {row3.add(null);row4.add(null);}}list.add(row3);list.add(row4);}return list;
}

自定义动态行/列背景颜色

package com.glbTech.business.dto.req.stat;import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import lombok.Data;
import org.apache.commons.lang.BooleanUtils;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@Data
public class CustomCellWriteHandler extends AbstractCellWriteHandler {private Integer maxRow;private Integer maxCol;private final short colorL = IndexedColors.LIME.getIndex(); //绿色private final short colorH = IndexedColors.GREY_25_PERCENT.getIndex(); //灰色public CustomCellWriteHandler(Integer maxRow, Integer maxCol) {this.maxRow = maxRow;this.maxCol = maxCol;}@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {// 自定义样式处理// 当前事件会在 数据设置到poi的cell里面才会回调int x = 1;for (int i = 4; i < (maxRow+2)*2; i=(x*2)) {Cell cell = context.getCell();int rowIndex = cell.getRowIndex(); //行int cellIndex = cell.getColumnIndex(); //行的列// 判断不是头的情况 如果是fill 的情况 这里会==null 所以用not trueif (BooleanUtils.isNotTrue(context.getHead())) {if (cellIndex > 0 && (rowIndex==i || rowIndex==i+1)) {// 拿到poi的workbookWorkbook workbook = context.getWriteWorkbookHolder().getWorkbook();// 这里千万记住 想办法能复用的地方把他缓存起来 一个表格最多创建6W个样式// 不同单元格尽量传同一个 cellStyleCellStyle cellStyle = workbook.createCellStyle();//设置颜色if (x%2==0) {cellStyle.setFillForegroundColor(colorL); //绿色}else {cellStyle.setFillForegroundColor(colorH); //灰色}cellStyle.setAlignment(HorizontalAlignment.RIGHT); //右对齐// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUNDcellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);cell.setCellStyle(cellStyle);// 由于这里没有指定dataformat 最后展示的数据 格式可能会不太正确// 这里要把 WriteCellData的样式清空, 不然后面还有一个拦截器 FillStyleCellWriteHandler 默认会将 WriteCellStyle 设置到// cell里面去 会导致自己设置的不一样(很关键)context.getFirstCellData().setWriteCellStyle(null);}}x++;}}
}

好事定律:每件事最后都会是好事,如果不是好事,说明还没到最后。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/739269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web开发——前端html、css、JavaScript学习总结(持续更新中.......)

目录模版 1 html:结构标签/属性文本标记: mark文本设置:删除线del / 下划线ins/ 加粗b / 强调的文本em / 重要的文本 strong超链接: a联系信息: addressdiv 定义文档中的分区或节: div行元素:spanhtml结构: main / section / articlenav表格:table html中各种标签/属性的英文扩…

记一次寻找js来文件上传

edu教育证书站之路 0x01 信息收集 通过fofa&#xff0c;子域名收集等相关工具搜索域名 定位到站点&#xff1a;htps://xx..edu.cn/x/xx/ 0x02 寻找接口 通过f12寻找相关的js&#xff0c;发现有其他的页面 0x03 拼接路径 https://xx.xx.edu.cn/xx/xx/repairResgister 之后未授权…

主流接口测试框架对比

公司计划系统的开展接口自动化测试&#xff0c;需要我这边调研一下主流的接口测试框架给后端测试&#xff08;主要测试接口&#xff09;的同事介绍一下每个框架的特定和使用方式。后端同事根据他们接口的特点提出一下需求&#xff0c;看哪个框架更适合我们。 需求 1、接口编写…

亿道三防手持机丨安卓加固手持终端丨手持机PDA丨货物出入库

出入库管理是现代物流系统中的重要环节&#xff0c;涉及到货物的接收、分发、存储和追踪等方面。然而&#xff0c;在复杂的仓库环境中&#xff0c;传统的管理方法面临着很多困难和挑战&#xff0c;如手写记录容易出错、数据处理繁琐等。为了提高出入库管理的效率和准确性&#…

【新手适用】手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN一: 创建model模块和加载数据集

教程&#xff1a;j从零开始实现一个基于Pytorch的卷积神经网络 - 知乎 目录 网络结构 1 初始化 2 前向传播forward函数 2.1 forward函数定义 2.2 view函数和size函数 如何获取channels&#xff1f; 如何获取batchsize&#xff1f; 2.3 forward实现 2.4 main方法调用 模…

企业微信变更主体对用户有影响吗?

企业微信变更主体有什么作用&#xff1f;现在很多公司都用企业微信来加客户&#xff0c;有时候辛辛苦苦积累了很多客户&#xff0c;但是公司却因为各种各样的原因需要注销&#xff0c;那么就需要通过企业微信变更主体的方法&#xff0c;把企业微信绑定的公司更改为最新的。企业…

Java后端八股------消息中间件篇

自动确认没收到&#xff0c;实现重复消费问题&#xff0c;可以用业务唯一标识来确定业务是否被消费。 TTL也就是超时时间&#xff0c;一般去dead letter的时间为min(消息的ttl,queue的ttl)。 acksall设置是最安全的&#xff0c;但是效率太低了&#xff0c;实际的生…

鲜花销售小程序|基于微信小程序的鲜花销售系统设计与实现(源码+数据库+文档)

鲜花销售小程序目录 目录 基于微信小程序的鲜花销售系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1前台功能模块 2、后台功能模块 1、管理员功能模块 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、…

【io.net】问题汇总

【io.net】问题汇总 大家最近挖挖的如火如荼&#xff0c;可是不论是社区活动积分和参与挖矿积分&#xff0c;大家遇到了很多类似问题&#xff0c;重复解决。 因此我这里整理了一下常见的相关问题&#xff0c;大家可以一站式找到解决方案。解决方案主要分为运营和挖矿两个两面…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的障碍物检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发障碍物检测系统对于道路安全性具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个障碍物检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同模型间的性能…

如何解决由触发器导致 MySQL 内存溢出?

由触发器导致得 OOM 案例分析过程和解决方式。 作者&#xff1a;龚唐杰&#xff0c;爱可生 DBA 团队成员&#xff0c;主要负责 MySQL 技术支持&#xff0c;擅长 MySQL、PG、国产数据库。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编…

苹果cms模板保护设置,防止被扒

苹果cms模板保护设置&#xff0c;防止被扒 如今互联网时代&#xff0c;网站模板前端被扒是常有的事&#xff0c;如何防止模板数据被扒&#xff1f; 保护设置方法&#xff1a; 登录宝塔 找到安装模板的网站 设置禁止访问文件 方法参考截图后缀填&#xff1a;php|html 目录填&a…

OA系统中的九大常用审批场景,你都晓得吗?

Hi&#xff0c;我是贝格前端工场&#xff0c;今天继续来剖析OA的功能&#xff0c;这次重点分析审批功能&#xff0c;欢迎老铁们点赞评论转发。 一、OA的审批功能和流程 OA的审批功能是指在办公自动化系统中&#xff0c;通过电子化的方式实现对各种申请、请求或业务流程的审批管…

项目管理工具及模板(甘特图、OKR周报、任务管理、头脑风暴等)

项目管理常用模板大全&#xff1a; 1. 项目组OKR周报 2. 项目组传统周报工作法 3. 项目甘特图 4. 团队名单 5. 招聘跟进表 6. 出勤统计 7. 年度工作日历 8. 项目工作年计划 9. 版本排期 10. 项目组任务管理 11. 项目规划模板 12. 产品分析报告 13. 头脑风暴 信息化项目建设全套…

阻塞队列学习

1、什么是阻塞队列&#xff1f; 顾名思义&#xff0c;就是支持阻塞的队列&#xff0c;相比于其他的队列&#xff0c;阻塞队列支持以下特性&#xff1a; 队列为空的时候&#xff0c;获取元素的线程会等待队列变为非空。队列为满的时候&#xff0c;存储元素的线程会等待队列可以…

Python 单元测试

本篇为Python的单元测试的方法及示例 目录 概念 结果 示例 对函数进行测试 创建函数文件 创建测试文件 测试结果 对类进行测试 创建待测试类 创建测试文件 文档测试 创建函数 进行测试 总结 概念 用来对一个函数、一个类或者一个模块来进行正确性校验工作 结果 …

提取B站视频教程详情

提取B站视频教程详情 背景 B站这个视频列表是真的体验感太差了,有时候想把章节复制下来,再对应的章节下面做笔记,实在是太难搞了,于是就有了这篇文文章 根据关键字获取视频id Test public void list() {String url "https://api.bilibili.com/x/web-interface/wbi/sea…

虚拟机(KVM)克隆

当需要批量部署虚拟机时&#xff0c;可以使用克隆虚拟机的方式来进行。 使用图形界面来克隆虚拟机。 [rootzhoujunru_node1 zhou]# virsh list --allId Name State ------------------------------ vm01 shut off- vm01-clone shut off克隆完成。

Django入门 整体流程跑通

Django学习笔记 一、Django整体流程跑通 1.1安装 pip install django //安装 import django //在python环境中导入django django.get_version() //获取版本号&#xff0c;如果能获取到&#xff0c;说明安装成功Django目录结构 Python310-Scripts\django-admi…

Centos7 安装mongodb 7.0

官方手册参考&#xff1a; https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-red-hat/ Mongodb支持的版本 安装 MongoDB 社区版 按照以下步骤使用包管理器安装 MongoDB Community Edition yum。 配置包管理系统 ( yum) 创建一个/etc/yum.repos.d/mongodb-o…