当前位置: 首页 > news >正文

EasyExcel使用总结

EasyExcel

文章目录

  • EasyExcel
    • 1、导入
      • 1.1、基本方式导入
        • 1.导入依赖
        • 2. 加载源文件
          • 基本语法
        • 3. 读取数据行
        • 4. 读取结果
      • 1.2、模型映射导入
        • 1.定义实体映射类
        • 2. 操作读取
          • 基本语法
        • 3. 读取数据行
        • 4. 读取结果
      • 1.3、导入类型转换器
        • 语法
      • 1.4、导入监听器
        • 基本语法:
      • 1.5、多行表头导入
        • 基本语法:
      • 1.6、导入异常处理
      • 1.7、文件上传导入
    • 2、导出
      • 1、基本方式导出
        • 基本语法
      • 2、模型映射导出
        • 基本语法
      • 3、自定义导出格式转换
        • 语法
      • 4、排除那些列导出
        • 语法
      • 5、导出行高列宽
        • 语法:
      • 6、合并单元格导出
        • 语法
        • 自定义合并单元格
      • 7、导出动态表头
        • 语法
        • 自定义导出动态表头
      • 8、导出超链接、批注、公式
        • 导出超链接语法
        • 导出批注语法
        • 导出公式语法
      • 9、导出图片内容
        • 导出图片内容语法
    • 3、模版填充
      • 1、模版填充对象
        • 基本语法Map填充
        • 基本语法对象填充
      • 2、模版填充列表
        • 语法
      • 3、模版填充组合
        • 基本语法
      • 4、导出文件下载
        • 语法

1、导入

1.1、基本方式导入

1.导入依赖

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.js</groupId><artifactId>EasyExcel-Test</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--easy-excel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.4</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency><!--Junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><!--slf4j接口--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.6</version></dependency><!--slf4j实现--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>2.0.6</version></dependency><!--fast-josn--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.22</version></dependency></dependencies></project>
2. 加载源文件

使用File 或 InputStream 的方式加载Excel 源文件

基本语法
//示例:从本地File文件导入。
File file = new File("Excel本地文件路径.xlsx");
List<Object>list = EasyExcel.read(file).sheet(0).doReadsync();//示例:从InputStream输入流中导入。
InputStream inputStream = TestSample.class.getClassLoader(),aetResourceAsstream("Excel资源路径,xlsx");
List<Object>list = EasyExcel.read(inputStream).sheet(0).doReadsync();
3. 读取数据行

使用 EasyExcel 载入并读取源文件数据行内容

实例

在这里插入图片描述

package cn.js;import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.io.File;
import java.util.List;/*** Description:** @Author Js* @Create 2025-05-03 20:05* @Version 1.0*/
@Slf4j
public class EasyExcelTest {@Testpublic void testFile(){File file = new File("C:\\Users\\lenovo\\Desktop\\123\\Easy-test.xlsx");List<Object> list = EasyExcel.read(file).sheet(0).doReadSync();for (Object item : list) {log.info("item:{}",item);}}
}

在这里插入图片描述


实例2

package cn.js;import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.io.File;
import java.io.InputStream;
import java.util.List;/*** Description:** @Author Js* @Create 2025-05-03 20:05* @Version 1.0*/
@Slf4j
public class EasyExcelTest {/*** 我们将:Easy-test.xlsx 文件放到 resource 目录下面*/@Testpublic void testInputStream(){InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test.xlsx");List<Object> list = EasyExcel.read(inputStream).sheet(0).doReadSync();for (Object item : list) {log.info("item:{}",item);}}}

在这里插入图片描述

4. 读取结果

获取数据行条目及各行数据内容

在这里插入图片描述

在这里插入图片描述


1.2、模型映射导入

我们第一种导出结果,可以看出,是一个Map 的结构,我们在获取数据的时候,如果通过角标 Key获取值的话,很不方便的,而且每一个key 对应的Value 的类型也不一样。如果我们定义好一个类,将类中的属性和Excel 列进行一 一 绑定,这样既能知道value的类型,也更加明确的好获取每个数据。

1.定义实体映射类
package cn.js;import lombok.Data;import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-03 20:34* @Version 1.0*/
@Data
public class UserInfoModel {/*** 昵称*/private String userName;/*** 性别*/private String userGender;/*** 生日*/@DateTimeFormat(value="yyyy年MM月dd日 HH时mm分ss秒")private Date userBirth;/*** 邮箱*/private String userEmail;/*** 积分*/private Integer userScore;/*** 排名*/// private Double userRank;@NumberFormat(value="#.##%")private String userRank;}
2. 操作读取
基本语法
关联映射 @ExcelProperty:将类的属性,和excel的单元格进行绑定,默认是按照顺序进行解析的,注意类的字段类型,要符合excel中的字段,否则会报错;建议使用“列名” 进行绑定@ExcelProperty(index=0)@ExcelProperty(value ="列名")格式转换@DateTimeFormat(value="yyyy年MM月dd日 HH时mm分ss秒")@NumberFormat(value="#.##%")@ExcelProperty(converter=自定义格式转换.class)相关方法EasyExcel.read(inputStream).head(映射模型.class).doReadSync();
3. 读取数据行
@Testpublic void testInputStreamWithModel() {InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test.xlsx");List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).head(UserInfoModel.class).doReadSync();for (UserInfoModel item : list) {log.info("昵称:{},性别{},生日{},邮箱{},积分{},排名{}", item.getUserName(),item.getUserGender(),item.getUserBirth(),item.getUserEmail(),item.getUserScore(),item.getUserRank());}}
4. 读取结果

在这里插入图片描述

1.3、导入类型转换器

语法

实现 implements Converter<就是实际导进来需要转换成java中啥类型> 接口中convertToJavaData 方法

在需要转换的映射模型字段上面加上如下注解

@ExcelProperty(converter = 类型转换器.class)

类型转换器

package cn.js;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;/*** Description:** @Author Js* @Create 2025-05-03 21:04* @Version 1.0*/// Converter<Integer>:就是实际导进来需要转换成啥类型
public class UserInfoGenderConverter implements Converter<Integer> {/*** 导入时: 把excel中的数据转成java类型*/@Overridepublic Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {String value = cellData.getStringValue();switch (value) {case "男":return 1;case "女":return 2;default:return 0;}}/*** 导出时: 把java中的数据转成符合excel类型*/@Overridepublic WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {return Converter.super.convertToExcelData(value, contentProperty, globalConfiguration);}
}

使用类型转换器: @ExcelProperty(converter = 类型转换器所在的类.class),将这个注解贴在要转换的模型映射类中对应的Excel字段上面,即可。

​ 如:将excel中的男,女转换成:1,0

/*** 性别 */
@ExcelProperty(converter = UserInfoGenderConverter.class)//类型转换器
private Integer userGender;
//private String userGender;
package cn.js;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import lombok.Data;import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-03 20:34* @Version 1.0*/
@Data
public class UserInfoModel {/*** 昵称*/private String userName;/*** 性别*/@ExcelProperty(converter = UserInfoGenderConverter.class)//类型转换器private Integer userGender;//private String userGender;/*** 生日*/@DateTimeFormat(value="yyyy年MM月dd日 HH时mm分ss秒")private Date userBirth;/*** 邮箱*/private String userEmail;/*** 积分*/private Integer userScore;/*** 排名*/@NumberFormat(value="#.##%")private String userRank;//private Double userRank;}

测试

	 @Testpublic void testInputStreamWithModel() {InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test.xlsx");List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).head(UserInfoModel.class).doReadSync();for (UserInfoModel item : list) {log.info("昵称:{}, 性别:{}, 生日:{}, 邮箱:{}, 积分:{}, 排名:{}", item.getUserName(),item.getUserGender(),item.getUserBirth(),item.getUserEmail(),item.getUserScore(),item.getUserRank());}}

在这里插入图片描述


1.4、导入监听器

为啥需要监听器?我们在读取excel 文件时候,不管是File 还是InputStream 流,都是直接使用.doReadSync() 方法直接读取,但是我们在实际当中,可能还得需要对Excel中数据进行:

1.数据格式校验

2.自动适配内容

3.解析异常处理

4.分批入库

5.节约内存 ……操作

基本语法:
//1.示例:使用匿名内部类。
EasyExcel.read(inputStream)
.head(UserInfoModel.class)
.registerReadListener(new ReadListener<映射模型>(){})
.sheet(0);//2.示例:使用监听实现类。
public class 监听实现类 implements ReadListender<映射模型>{}EasyExcel.read(inputStream)
.head(UserInfoModel.class)
.registerReadListener(new监听实现类())
.sheet(0);//3.示例:简写方式。
EasyExcel.read(inputStream, UserinfoModel.class, new 监听实现类()).sheet(0);

使用步骤

package cn.js.listener;import cn.js.model.UserInfoModel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;/*** Description:** @Author Js* @Create 2025-05-03 21:52* @Version 1.0*/
@Slf4j
public class UserInfoReadListener implements ReadListener<UserInfoModel> {/***  解析excel中每一条数据时,会执行的方法* @param userInfoModel* @param analysisContext*/@Overridepublic void invoke(UserInfoModel userInfoModel, AnalysisContext analysisContext) {log.info("解析每一行excel的 invoke 方法:{}" ,userInfoModel);}/*** 解析完 excel中所有数据时,会执行的方法* @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info("解析完excel的 doAfterAllAnalysed 方法:" );}
}

使用

	@Testpublic void testInputStreamWithListener() {InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test.xlsx");List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).registerReadListener(new UserInfoReadListener())//监听器.head(UserInfoModel.class).doReadSync();}

在这里插入图片描述


1.5、多行表头导入

应用场景

一般在导入数据的时候我们会给用户一个模版,让用户按照模版要求进行导入。

比方说下图,前五行,是我们提供给用户的注意事项,从第六行开始,才是我们的excel数据的表头,此时我们应该指定,数据真正的表头,是第几行。

在这里插入图片描述

基本语法:
EasyExcel.read(inputStream)
.sheet(0)
.head(映射模型.class)
//关键代码:设置表头行数。
.headRowNumber(6)
.registerReadListener(new监听器实现类())
.""””..

在这里插入图片描述

测试

@Testpublic void testInputStreamWithModel1() {InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test1.xlsx");List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).head(UserInfoModel.class).headRowNumber(6)//关键代码:设置表头行数。.doReadSync();for (UserInfoModel item : list) {log.info("昵称:{}, 性别:{}, 生日:{}, 邮箱:{}, 积分:{}, 排名:{}", item.getUserName(),item.getUserGender(),item.getUserBirth(),item.getUserEmail(),item.getUserScore(),item.getUserRank());}}

在这里插入图片描述


1.6、导入异常处理

处理方式也是实现监听器,并重写其中的 onException 方法,里面的异常封装着数据错误信息。

public void onException(Exception exception, AnalysisContext context) throws Exception

基本语法:

/*** 解析异常时,会执行的方法* @param exception* @param context* @throws Exception*/@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {//  ReadListener.super.onException(exception, context);ExcelDataConvertException dataConvertException = (ExcelDataConvertException) exception;//获取行的下标Integer rowIndex = dataConvertException.getRowIndex();//获取列的下标Integer columnIndex = dataConvertException.getColumnIndex();//数据String content = dataConvertException.getCellData().getStringValue();//原因String message = dataConvertException.getMessage();log.error("解析失败,请检查输入的第{}行第{}列数据是否正确:{}",rowIndex,columnIndex,message);log.warn("Excel data conversion error at row {}, column {}, content: {}", rowIndex, columnIndex, content);throw new ExcelAnalysisStopException();//必须抛出}

标准化处理

  1. 定义一个读取错误的Moder类
package cn.js.model;import lombok.AllArgsConstructor;
import lombok.Data;import java.io.Serializable;/**
* Description:
*
* @Author Js
* @Create 2025-05-03 22:57
* @Version 1.0
*/
@Data
@AllArgsConstructor
public class ReadErrorModel implements Serializable {private static final long serialVersionUID = 1L;/*** 错误信息*/private String message;/*** 行号*/private Integer rowIndex;/*** 列号*/private Integer columnIndex;/*** 单元格数据*/private String cellData;}
  1. 测试

    package cn.js.listener;import cn.js.model.UserInfoModel;
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.exception.ExcelDataConvertException;
    import com.alibaba.excel.read.listener.ReadListener;
    import lombok.extern.slf4j.Slf4j;/*** Description:** @Author Js* @Create 2025-05-03 21:52* @Version 1.0*/
    @Slf4j
    public class UserInfoReadListener implements ReadListener<UserInfoModel> {/***  解析excel中每一条数据时,会执行的方法* @param userInfoModel* @param analysisContext*/@Overridepublic void invoke(UserInfoModel userInfoModel, AnalysisContext analysisContext) {log.info("解析每一行excel的 invoke 方法:{}" ,userInfoModel);}/*** 解析完 excel中所有数据时,会执行的方法* @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {log.info("解析完excel的 doAfterAllAnalysed 方法:" );}/*** 解析异常时,会执行的方法** @param exception* @param context* @throws Exception*/@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {//  ReadListener.super.onException(exception, context);ExcelDataConvertException dataConvertException = (ExcelDataConvertException) exception;//获取行的下标Integer rowIndex = dataConvertException.getRowIndex();//获取列的下标Integer columnIndex = dataConvertException.getColumnIndex();//数据String content = dataConvertException.getCellData().getStringValue();//原因String message = dataConvertException.getMessage();this.readErrorModel = new ReadErrorModel(rowIndex, columnIndex, content, message);throw new ExcelAnalysisStopException();//必须抛出}
    }
  2. 运行

    @Testpublic void testInputStreamWithListener2() {InputStream inputStream = EasyExcelTest.class.getClassLoader().getResourceAsStream("Easy-test.xlsx");UserInfoReadListener listener = new UserInfoReadListener();List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).registerReadListener(listener)//监听器.head(UserInfoModel.class).doReadSync();if(listener.getReadErrorModel()!=null){log.info("读取失败:{}",listener.getReadErrorModel());}else {log.info("读取成功:{}",list);}}
    

在这里插入图片描述

在这里插入图片描述


1.7、文件上传导入

导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.js</groupId><artifactId>EasyExcel-Test</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--easy-excel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.1</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion><exclusion><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId></exclusion></exclusions></dependency><!--commons--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.23.0</version></dependency><!--Junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.24</version></dependency><!--slf4j接口--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.6</version></dependency><!--slf4j实现--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>2.0.6</version></dependency><!--fast-josn--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.22</version></dependency><!--springBoot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.11</version><exclusions><exclusion><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>2.0</version></dependency></dependencies></project>
package cn.js.controller;import cn.js.model.UserInfoModel;
import com.alibaba.excel.EasyExcel;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** Description:** @Author Js* @Create 2025-05-03 23:18* @Version 1.0*/
@RestController
@RequestMapping("/hom")
public class HomController {@RequestMapping("/test")public String test(){return "hello";}@PostMapping("/test2")public List<UserInfoModel> update(MultipartFile file) throws IOException {//获取:文件输入流InputStream inputStream = file.getInputStream();List<UserInfoModel> list = EasyExcel.read(inputStream).sheet(0).head(UserInfoModel.class).registerReadListener(new UserInfoReadListener())//监听器doReadSync();return list;}}

在这里插入图片描述


2、导出

1、基本方式导出

基本语法
 EasyExcel.write("导出目标").sheet().doWrite("集合数据");
//导出目标:1.string 文件路径2.File 文件对象3.OutStream 输出流//集合数据:1.List<List<Object>>2.List<Map<Integer,Object>>3.List<Object>

使用List集合导出

package cn.js;import cn.js.model.UserInfoModel;
import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;import java.util.Arrays;
import java.util.List;/*** Description:** @Author Js* @Create 2025-05-04 13:04* @Version 1.0*/
@Slf4j
public class EasyWiteTest {private static final String FILE_NAME = "C:\\Users\\lenovo\\Desktop\\123\\test.xlsx";@Testpublic void  witeList(){List<Object> list1 = Arrays.asList(1, 2, 3);List<Object> list2 = Arrays.asList("郭德纲", "王德纲", "张德纲");List<List<Object>> list = Arrays.asList(list1, list2);EasyExcel.write(FILE_NAME).sheet("测试").doWrite(list);}
}

在这里插入图片描述


使用Map集合导出


    @Testpublic void  witeMap() throws ParseException {Map<Integer, Object> map1 = new HashMap<>();map1.put(0, "张三");map1.put(1, "男");map1.put(2, DateUtils.parseDate("2025-05-04"));map1.put(3, "zhangsan@163.com");HashMap<Integer, Object> map2 = new HashMap<>();map2.put(0, "李四");map2.put(1, "女");map2.put(2, DateUtils.parseDate("2025-05-04"));map2.put(3, "lisi@163.com");List<Map<Integer, Object>> list = Arrays.asList(map1, map2);EasyExcel.write(FILE_NAME).sheet("测试").doWrite(list);}

在这里插入图片描述


使用List对象集合导出

package cn.js.model;import cn.js.converter.UserInfoGenderConverter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-04 13:20* @Version 1.0*/
@Data
@AllArgsConstructor
public class UserWriteModel {/*** 昵称*/private String userName;/*** 性别*/private String userGender;/*** 生日*/@DateTimeFormat(value="yyyy年MM月dd日 HH时mm分ss秒")private Date userBirth;/*** 邮箱*/private String userEmail;
}
@Testpublic void objectList() throws ParseException {UserWriteModel model1 = new UserWriteModel("张三", "男", DateUtils.parseDate("2025-05-04"), "zhangsan@163.com");UserWriteModel model2 = new UserWriteModel("李四", "女", DateUtils.parseDate("2025-05-04"), "lisi@163.com");List<UserWriteModel> list = Arrays.asList(model1, model2);EasyExcel.write(FILE_NAME).sheet("测试").doWrite(list);}

在这里插入图片描述


2、模型映射导出

其一步实我们,在上一步中ListObject 使用过程当中就已经使用过了,但是可以发现导出的时候Excel 中是没有表头的,而且数据没有格式化……等操作

基本语法
// 关联映射&设置标题@ExcelProperty(index=0)//表示:数据放在excel中那一列@ExcelProperty(value ="列名")@ExcelProperty(value ={"主标题""副标题"})//显示隐藏@Excellgnore//在那个模型映射字段添加该注解,这个字段在导出的,就会忽略掉//设置那些模型字段导出EasyExcel.write(导出目标).head(映射模型.class).excludeColumnFiledNames(Collection<String>)//根据集合设置,那些列不导出,Collection<String>:那些模型映射类的字段,:userName,userGender,将这些封装成Lsit集合。.includeColumnFiledNames(Collection<String>)//根据集合设置,那些列导出.doWrite(集合数据);     //格式转换@DateTimeFormat(value="yyyy年MM月dd日")@NumberFormat(value="#.##%")@ExcelProperty(converter=自定义转换.class)// 相关方法EasyExcel.write(导出目标).head(映射模型.class).doWrite(集合数据);

关联映射&设置标题

package cn.js.model;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;import java.math.BigDecimal;
import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-04 13:20* @Version 1.0*/
@Data
@AllArgsConstructor
public class UserWriteModel {/*** 昵称*/@ExcelProperty(value = {"基本信息", "姓名"})private String userName;/*** 性别*/@ExcelProperty(value = {"基本信息", "性别"})private Integer userGender;/*** 生日*/@ExcelProperty(value = {"基本信息", "生日"})@DateTimeFormat(value = "yyyy年MM月dd日 HH时mm分ss秒")private Date userBirth;/*** 邮箱*/@ExcelProperty(value = {"基本信息", "邮箱"})private String userEmail;/*** 积分*/@ExcelProperty(value = {"账户信息", "积分"})private Integer userScore;@ExcelProperty(value = {"账户信息", "奖励"})private BigDecimal userReward;
}
@Testpublic void objectList2() throws ParseException {UserWriteModel model1 = new UserWriteModel("张三疯", 1, DateUtils.parseDate("2025-05-04"), "zhangsan@163.com", 123, BigDecimal.valueOf(123.456));UserWriteModel model2 = new UserWriteModel("李四军", 0, DateUtils.parseDate("2025-05-04"), "lisi@163.com", 789, BigDecimal.valueOf(789.258));List<UserWriteModel> list = Arrays.asList(model1, model2);EasyExcel.write(FILE_NAME).sheet("测试").head(UserWriteModel.class).doWrite(list);}

在这里插入图片描述

3、自定义导出格式转换

语法

实现 implements Converter<就是实际导进来需要转换成java中啥类型> 接口中convertToExcelData方法

在需要转换的映射模型字段上面加上如下注解:

@ExcelProperty(converter = 类型转换器.class)

类型转换器

package cn.js;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;/*** Description:** @Author Js* @Create 2025-05-03 21:04* @Version 1.0*/// Converter<Integer>:就是实际导进来需要转换成啥类型
public class UserInfoGenderConverter implements Converter<Integer> {/*** 导入时: 把excel中的数据转成java类型*/@Overridepublic Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {String value = cellData.getStringValue();switch (value) {case "男":return 1;case "女":return 2;default:return 0;}}/*** 导出时: 把java中的数据转成符合excel类型*/@Overridepublic WriteCellData<?> convertToExcelData(Integer value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {switch (value) {case 1:return new WriteCellData<>("男");case 2:return new WriteCellData<>("女");default:return new WriteCellData<>("未知");}}
}

测试

模型映射类添加类型转换器

/**
* 性别
*/
@ExcelProperty(value = {"基本信息", "性别"},converter = UserInfoGenderConverter.class)
private Integer userGender;

1

@Testpublic void objectList2() throws ParseException {UserWriteModel model1 = new UserWriteModel("张三疯", 1, DateUtils.parseDate("2025-05-04"), "zhangsan@163.com", 123, BigDecimal.valueOf(123.456));UserWriteModel model2 = new UserWriteModel("李四军", 0, DateUtils.parseDate("2025-05-04"), "lisi@163.com", 789, BigDecimal.valueOf(789.258));List<UserWriteModel> list = Arrays.asList(model1, model2);EasyExcel.write(FILE_NAME).sheet("测试").head(UserWriteModel.class).doWrite(list);}

在这里插入图片描述

4、排除那些列导出

语法
  1. 直接在模型映射类的字段上面添加注解
//显示隐藏
@Excellgnore//在那个模型映射字段添加该注解,这个字段在导出的,就会忽略掉
  1. 在导出的时候设置那些是否导出

      //设置那些模型字段导出EasyExcel.write(导出目标).head(映射模型.class)//根据集合设置,那些列不导出,Collection<String>:那些模型映射类的字段,如:userName,userGender,将这些封装成Lsit集合。.excludeColumnFiledNames(Collection<String>)//根据集合设置,那些列导出.includeColumnFiledNames(Collection<String>).doWrite(集合数据);     
    

5、导出行高列宽

语法:
  1. 手动设置,通过在模型映射类的字段上面添加注解,或者在模型类上面添加,在模型类上面添加,所有导出的字段都生效。

    //行高(内容):@ContentRowHeight(value=10)
    //行高(标题):@HeadRowHeight(value=20)
    //列宽:@ColumnWidth(value=25)
    
  2. 自动列宽,也可以参照 LongestMatchColumnWidthStyleStrategy 类重写一个

    EasyExcel.write(file)//自动列宽:根据内容长度自动匹配:默认按照标题匹配
    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet()
    .doWrite(data);
    

6、合并单元格导出

语法
  1. 使用注解:

    //firstRowIndex:开始第几行,lastRowindex结束是第几行,firstcolumnindex:第几列开始,lastColumnIndex:第几列结束
    @OnceAbsoluteMerge(firstRowIndex =2,lastRowindex =3, firstcolumnindex=0,lastColumnIndex=0)
    public class 模型映射类{}@ContentLoopMerge(eachRow=2)
    private String fieldName;
    
    1. 自定义策略:
    // 循环合并:new LoopMergeStrategy(eachRow:2,columnIndex:0);// 合并一次: new OnceAbsoluteMergestrategy(firstRowindex: 0, lastRowindex: 1, firstcolumnindex: 4, lastcolumnindex: 4);// 使用策略:
    EasyExcel.write(file).head(映射模型.class).sheet().registerWriteHandler(合并策略).doWrite(数据);
    

测试

  @Testpublic void objectList3() throws ParseException {UserWriteModel model1 = new UserWriteModel("第一团队","张三疯", 1, DateUtils.parseDate("2025-05-04"), "zhangsan@163.com", 123, BigDecimal.valueOf(123.456));UserWriteModel model2 = new UserWriteModel("第一团队","李四军", 0, DateUtils.parseDate("2025-05-05"), "lisi@163.com", 789, BigDecimal.valueOf(789.258));UserWriteModel model3 = new UserWriteModel("第二团队", "王五", 1, DateUtils.parseDate("2025-05-06"), "zhangsxxn@163.com", 124, BigDecimal.valueOf(123.056));UserWriteModel model4 = new UserWriteModel("第二团队", "赵六", 1, DateUtils.parseDate("2025-05-07"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(435.010));UserWriteModel model5 = new UserWriteModel("第三团队", "孙七", 0, DateUtils.parseDate("2025-05-08"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(405.231));List<UserWriteModel> list = Arrays.asList(model1, model2, model3, model4, model5);EasyExcel.write(FILE_NAME).sheet("测试").head(UserWriteModel.class)// .registerWriteHandler(new OnceAbsoluteMergeStrategy(2,3,0,0)).registerWriteHandler(new LoopMergeStrategy(2,0)).doWrite(list);}

在这里插入图片描述

自定义合并单元格
  1. 合并单元格,有两种方式:

    1. 是实现RowWriteHandler接口,这个是行合并,也是默认的
    2. 是实现CellWriteHandler接口,这个是列合并
  2. 实现 CellWriteHandler 接口

    package cn.js.converter;import com.alibaba.excel.metadata.Head;
    import com.alibaba.excel.metadata.data.WriteCellData;
    import com.alibaba.excel.write.handler.CellWriteHandler;
    import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
    import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.CellType;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;import java.io.Serializable;
    import java.util.List;/*** Description:** @Author Js* @Create 2025-05-04 14:54* @Version 1.0*/
    public class CustomMergeStrategy implements CellWriteHandler {@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {// 如果是表头,不做处理if(isHead) {return;}//relativeRowIndex: 当前行号,如果当前是第一行,则不做处理if(relativeRowIndex== 0) {return;}//获取当前表格,当前行下标,上一行下标,上一行对象,上一列对象Sheet sheet = cell.getSheet();int rowIndexCurrent = cell.getRowIndex();int lastRowIndex = rowIndexCurrent - 1;Row rowPrev = sheet.getRow(lastRowIndex);Cell cellPrev = rowPrev.getCell(cell.getColumnIndex());//获取当前单元格的值Object cellValueCurrent = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();//获取上一单元格的值Object cellValuePrev = cellPrev.getCellType() == CellType.STRING ? cellPrev.getStringCellValue() : cellPrev.getNumericCellValue();//如果当前单元格的值和上一单元格的值相同,则合并单元格if(cellValueCurrent.equals(cellValuePrev)) {Boolean isMerged = false;//获取已有的合并区域for(int i = 0;i<sheet.getNumMergedRegions();i++) {org.apache.poi.ss.util.CellRangeAddress range = sheet.getMergedRegion(i);if(range.isInRange(rowIndexCurrent, cell.getColumnIndex())){//如果当前单元格已经在合并区域中,则先移除合并区域sheet.removeMergedRegion(i);//重新合并单元格的结束行range.setLastRow(rowIndexCurrent);//重新添加合并区域sheet.addMergedRegion(range);isMerged = true;break;}}if(!isMerged) {//如果当前单元格不在合并区域中,则直接添加新的合并区域sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(lastRowIndex, rowIndexCurrent, cellPrev.getColumnIndex(), cellPrev.getColumnIndex()));}}}
    }

测试

  1. 模型类
package cn.js.model;import cn.js.converter.UserInfoGenderConverter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.AllArgsConstructor;
import lombok.Data;import java.math.BigDecimal;
import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-04 13:20* @Version 1.0*/
@Data
@AllArgsConstructor
public class UserWriteModel {/*** 团队名称*/@ExcelProperty(value =  "团队名称")private String teamName;/*** 昵称*/@ExcelProperty(value = {"基本信息", "姓名"})private String userName;/*** 性别*/@ExcelProperty(value = {"基本信息", "性别"},converter = UserInfoGenderConverter.class)private Integer userGender;/*** 生日*/@ExcelProperty(value = {"基本信息", "生日"})@DateTimeFormat(value = "yyyy年MM月dd日 HH时mm分ss秒")private Date userBirth;/*** 邮箱*/@ExcelProperty(value = {"基本信息", "邮箱"})private String userEmail;/*** 积分*/@ExcelProperty(value = {"账户信息", "积分"})private Integer userScore;@ExcelProperty(value = {"账户信息", "奖励"})private BigDecimal userReward;
}
  1. 测试类
 @Testpublic void objectList3() throws ParseException {UserWriteModel model1 = new UserWriteModel("第一团队","张三疯", 1, DateUtils.parseDate("2025-05-04"), "zhangsan@163.com", 123, BigDecimal.valueOf(123.456));UserWriteModel model2 = new UserWriteModel("第一团队","李四军", 0, DateUtils.parseDate("2025-05-05"), "lisi@163.com", 789, BigDecimal.valueOf(789.258));UserWriteModel model3 = new UserWriteModel("第二团队", "王五", 1, DateUtils.parseDate("2025-05-06"), "zhangsxxn@163.com", 124, BigDecimal.valueOf(123.056));UserWriteModel model4 = new UserWriteModel("第二团队", "赵六", 1, DateUtils.parseDate("2025-05-07"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(435.010));UserWriteModel model5 = new UserWriteModel("第三团队", "孙七", 0, DateUtils.parseDate("2025-05-08"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(405.231));List<UserWriteModel> list = Arrays.asList(model1, model2, model3, model4, model5);EasyExcel.write(FILE_NAME).sheet("测试").head(UserWriteModel.class)// .registerWriteHandler(new OnceAbsoluteMergeStrategy(2,3,0,0))
//                .registerWriteHandler(new LoopMergeStrategy(2,0)).registerWriteHandler(new CustomMergeStrategy()).doWrite(list);}

在这里插入图片描述

但是一般是合并指定列相同的数据

  1. 自定义合并单元格配置类
package cn.js.converter;import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;import java.util.List;/*** Description:** @Author Js* @Create 2025-05-04 14:54* @Version 1.0*/
public class CustomMergeStrategy implements CellWriteHandler {//合并列名集合private final List<String> mergeColumnNames;public CustomMergeStrategy(List<String> mergeColumnNames) {this.mergeColumnNames = mergeColumnNames;}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {// 如果是表头,不做处理if (isHead) {return;}//relativeRowIndex: 当前行号,如果当前是第一行,则不做处理if (relativeRowIndex == 0) {return;}//如果不是合并列,不做处理if (!mergeColumnNames.contains(head.getFieldName())) {return;}//获取当前表格,当前行下标,上一行下标,上一行对象,上一列对象Sheet sheet = cell.getSheet();int rowIndexCurrent = cell.getRowIndex();int lastRowIndex = rowIndexCurrent - 1;Row rowPrev = sheet.getRow(lastRowIndex);Cell cellPrev = rowPrev.getCell(cell.getColumnIndex());//获取当前单元格的值Object cellValueCurrent = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();//获取上一单元格的值Object cellValuePrev = cellPrev.getCellType() == CellType.STRING ? cellPrev.getStringCellValue() : cellPrev.getNumericCellValue();//如果当前单元格的值和上一单元格的值相同,则合并单元格if (cellValueCurrent.equals(cellValuePrev)) {Boolean isMerged = false;//获取已有的合并区域for (int i = 0; i < sheet.getNumMergedRegions(); i++) {org.apache.poi.ss.util.CellRangeAddress range = sheet.getMergedRegion(i);if (range.isInRange(rowIndexCurrent, cell.getColumnIndex())) {//如果当前单元格已经在合并区域中,则先移除合并区域sheet.removeMergedRegion(i);//重新合并单元格的结束行range.setLastRow(rowIndexCurrent);//重新添加合并区域sheet.addMergedRegion(range);isMerged = true;break;}}if (!isMerged) {//如果当前单元格不在合并区域中,则直接添加新的合并区域sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(lastRowIndex, rowIndexCurrent, cellPrev.getColumnIndex(), cellPrev.getColumnIndex()));}}}
}
  1. 测试类
@Testpublic void objectList3() throws ParseException {UserWriteModel model1 = new UserWriteModel("第一团队", "张三", 1, DateUtils.parseDate("2025-05-04"), "zhangsan@163.com", 123, BigDecimal.valueOf(123.456));UserWriteModel model2 = new UserWriteModel("第一团队", "张三", 0, DateUtils.parseDate("2025-05-05"), "lisi@163.com", 789, BigDecimal.valueOf(789.258));UserWriteModel model3 = new UserWriteModel("第二团队", "王五", 1, DateUtils.parseDate("2025-05-06"), "zhangsxxn@163.com", 124, BigDecimal.valueOf(123.056));UserWriteModel model4 = new UserWriteModel("第二团队", "赵六", 1, DateUtils.parseDate("2025-05-07"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(435.010));UserWriteModel model5 = new UserWriteModel("第三团队", "孙七", 0, DateUtils.parseDate("2025-05-08"), "zhdsfgxxn@163.com", 604, BigDecimal.valueOf(405.231));List<UserWriteModel> list = Arrays.asList(model1, model2, model3, model4, model5);EasyExcel.write(FILE_NAME).sheet("测试").head(UserWriteModel.class)// .registerWriteHandler(new OnceAbsoluteMergeStrategy(2,3,0,0))
//                .registerWriteHandler(new LoopMergeStrategy(2,0)).registerWriteHandler(new CustomMergeStrategy(Arrays.asList("teamName", "userGender")))//设置那些列合并.doWrite(list);}

可以看到只合并我们设置的列

在这里插入图片描述

7、导出动态表头

在这里插入图片描述

语法
  1. 可以通过之前学习的 设置排除那些列导出.

    //1.显示隐藏
    @Excellgnore//在那个模型映射字段添加该注解,这个字段在导出的,就会忽略掉 //2. 设置那些模型字段导出EasyExcel.write(导出目标).head(映射模型.class)//根据集合设置,那些列不导出,Collection<String>:那些模型映射类的字段,如:userName,userGender,将这些封装成Lsit集合。.excludeColumnFiledNames(Collection<String>)//根据集合设置,那些列导出.includeColumnFiledNames(Collection<String>).doWrite(集合数据);  
    
  2. 指定表头集合

    1. 定义:根据需求动态构建表头集合。

      List<List<String>> headList = new ArrayList<>());
      headList.add(collections.singletonList("用户昵称"));
      headList.add(collections.singleonList("用户性别"));
      headList.add(collections.singletonList("用户年龄"));
      headList.add(Collections.singletonList("账户佣金"));
      headList.add(collections.singletonList("账户积分"));
      
    2. 处理:使用动态表头导出相关数据。

      EasyExcel.write(file).sheet().head(headList)
      doWrite(数据集合);
      

自定义导出动态表头
  1. 模型类
package cn.js.model;import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-04 15:49* @Version 1.0*/
@Data
@TableName("tb_user_info")
public class UserInfoEntity implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.ASSIGN_ID)@ExcelProperty(value = {"用户信息", "用户ID"})private Long id;@TableField(value = "user_nickname")@ExcelProperty(value = {"用户信息", "用户昵称"})private String userNickname;@TableField(value = "user_phone")@ExcelProperty(value = {"账号信息", "用户手机"})private String userPhone;@TableField(value = "user_email")@ExcelProperty(value = {"账号信息", "用户邮箱"})private String userEmail;@TableField(value = "user_gender")@ExcelProperty(value = {"其他信息", "用户性别"})private Integer userGender;@TableField(value = "user_birth")@ExcelProperty(value = {"其他信息", "用户生日"})private Date userBirth;@TableField(value = "user_score")@ExcelProperty(value = {"其他信息", "用户积分"})private Integer userScore;@TableField(value = "user_reward")@ExcelProperty(value = {"其他信息", "用户奖励"})private BigDecimal userReward;}
  1. 测试类
@Testpublic void test4() {// 导出字段名称。List<String> exportFieldNames = Arrays.asList("id", "userNickname", "userPhone", "userEmail", "userScore");//解析字段名称 -> 数据表列名称。Map<String, String[]> map = this.resolveFieldNameMap(UserInfoEntity.class, exportFieldNames);//动态查询。List<String> columnNames = new ArrayList<>(map.keySet());QueryWrapper<UserInfoEntity> queryWrapper = Wrappers.<UserInfoEntity>query().select(columnNames);List<UserInfoEntity> list = this.userInfoService.list(queryWrapper);//动态表头。List<List<String>> headlist = map.values().stream().map(Arrays::asList).collect(Collectors.toList());EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export456.xlsx").sheet("用户信息").head(headlist).doWrite(list);}/*** 解析字段名称 -> 数据表列名称。** @param clz              实体类* @param exportFieldNames 导出字段名称。* @param <T>* @return 返回数据表列名,表头名称*/@SneakyThrowsprivate <T> Map<String, String[]> resolveFieldNameMap(Class<T> clz, List<String> exportFieldNames) {Map<String, String[]> map = new LinkedHashMap<>(exportFieldNames.size());for (String fieldName : exportFieldNames) {Field field = clz.getDeclaredField(fieldName);String columnName = field.isAnnotationPresent(TableId.class) ? field.getAnnotation(TableId.class).value() : field.getAnnotation(TableField.class).value();String[] headNames = field.getAnnotation(ExcelProperty.class).value();map.put(columnName, headNames);}return map;}

8、导出超链接、批注、公式

导出超链接语法
1.属性类型
@ExcelProperty(value="用户编号")
@ColumnWidth(value=15)
private WriteCellData<String>userNumber;2. 导出处理
//声明:超链接数据。
HyperlinkData hyperlinkData = new HyperlinkData();
hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
hyperlinkData.setAddress("https://www.example.com/u/1001")//处理:使用超链接数据初始化用户编号。
WriteCellData<String> userNumber = new WriteCellData<>("1001");
userNumber.setHyperlinkData(hyperlinkData);//封装:模型对象。
UserInfoModel userInfoModel = new UserInfoModel();
userInfoModel.setUserNumber(userNumber);

测试

  1. 定义模型类,设置超链接字段
package cn.js.model;import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;/*** Description:** @Author Js* @Create 2025-05-04 15:49* @Version 1.0*/
@Data
@TableName("tb_user_info")
public class UserInfoEntity implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.ASSIGN_ID)@ExcelProperty(value = {"用户信息", "用户ID"})private Long id;@TableField(value = "user_nickname")@ExcelProperty(value = {"用户信息", "用户昵称"})private String userNickname;@TableField(value = "user_phone")@ExcelProperty(value = {"账号信息", "用户手机"})private String userPhone;@TableField(value = "user_email")@ExcelProperty(value = {"账号信息", "用户邮箱"})private String userEmail;@TableField(value = "user_gender")@ExcelProperty(value = {"其他信息", "用户性别"})private Integer userGender;@TableField(value = "user_birth")@ExcelProperty(value = {"其他信息", "用户生日"})private Date userBirth;@TableField(value = "user_score")@ExcelProperty(value = {"其他信息", "用户积分"})private Integer userScore;@TableField(value = "user_reward")@ExcelProperty(value = {"其他信息", "用户奖励"})private BigDecimal userReward;}
  1. 测试
@Testpublic void test3() {// 查询:用户信息实体。List<UserInfoEntity> entityList = this.userInfoService.list();//转换:entity -> modelList<UserInfoEntityModel> modelList = entityList.stream().map(item -> {UserInfoEntityModel model = new UserInfoEntityModel();//用户标识。model.setId(item.getId());// 用户昵称。HyperlinkData hyperlinkData = new HyperlinkData();hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);hyperlinkData.setAddress("http://www.xxx.com/usen/" + item.getId());WriteCellData<String> userNickname = new WriteCellData<>(item.getUserNickname());userNickname.setHyperlinkData(hyperlinkData);model.setUserNickname(userNickname);//用户性别。model.setUserGender(item.getUserGender());//用户生日。model.setUserBirth(item.getUserBirth());return model;}).collect(Collectors.toList());EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export156.xlsx").sheet("用户信息").head(UserInfoEntityModel.class).doWrite(modelList);}

在这里插入图片描述

在这里插入图片描述


导出批注语法
//属性类型:
@ExcelProperty(value = "用户昵称")
@ColumnWidth(value = 15)
private WriteCellData<String> userName;//设置批注//2.导出处理:
//声明:批注数据。
CommentData commentData = new CommentData();
commentData.setRichTextStringData(new RichTextStringData("此用户一天不学习就浑身难受。"));//处理:使用批注数据初始化用户昵称。
WriteCellData<String> userName = new WriteCellData<>("Jshuai ");
userName.setCommentData(commentData);
// 封装:用户信息模型。
UserinfoModel userInfoModel = new UserlnfoModel();
userInfoModel.setUserName(userName);

测试

  1. 定义模型类,设置批注字段
@ExcelProperty(value = "用户标识")
private WriteCellData<Long> id;//设置批注
  1. 测试
 @Testpublic void test4() {// 查询:用户信息实体。List<UserInfoEntity> entityList = this.userInfoService.list();//转换:entity -> modelList<UserInfoEntityModel> modelList = entityList.stream().map(item -> {UserInfoEntityModel model = new UserInfoEntityModel();//添加批注CommentData commentData = new CommentData();//创建批注对象commentData.setAuthor("作者:Jshuai");//设置批注的作者commentData.setRichTextStringData(new RichTextStringData("备注:这是一个备注信息"));WriteCellData<Long> id = new WriteCellData<>(BigDecimal.valueOf(item.getId()));//设置在那个字段上面添加批注id.setCommentData(commentData);//设置批注信息model.setId(id);//将设置批注信息与字段绑定//添加超链接HyperlinkData hyperlinkData = new HyperlinkData();//创建超链接对象hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);//设置超链接类型hyperlinkData.setAddress("http://www.xxx.com/usen/" + item.getId());//设置超链接地址WriteCellData<String> userNickname = new WriteCellData<>(item.getUserNickname());//设置在那个字段上面添加超链接userNickname.setHyperlinkData(hyperlinkData);//设置超链接信息model.setUserNickname(userNickname);//将超链接信息与字段绑定//用户性别。model.setUserGender(item.getUserGender());//用户生日。model.setUserBirth(item.getUserBirth());return model;}).collect(Collectors.toList());EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export156.xlsx").sheet("用户信息").head(UserInfoEntityModel.class).doWrite(modelList);}

在这里插入图片描述


导出公式语法
	属性类型@ExcelProperty(value = "用户年龄")@ColumnWidth(value = 15)private WriteCellData<Void> userAge;导出处理://声明:公式数据。FormulaData formulaData = new FormulaData();formulaData.setFormulaValue("CONCAT(DATEDIF(C2,NOW(),\"Y\"),\"岁\")");//处理:使用公式数据初始化用户年龄。WriteCellData<Void> userAge = new WriteCellData<>();userAge.setFormulaData(formulaData);
// 封装:用户信息模型。UserinfoModel userInfoModel=new UserinfoModel();userInfoModel.setUserBirth(DateUtils.parseDate("2000-01-01"));userInfoModel.setUserAge(userAge);

测试

  1. 定义模型类,设置公式字段
	//用户生日。@ExcelProperty(value = "用户生日")private WriteCellData<Void> userAge;
  1. 测试
@Testpublic void test6(){
// 查询:用户信息实体。List<UserInfoEntity> entityList = this.userInfoService.list();// 转换:entity -> model.List<UserInfoEntityModel> modelList = IntStream.range(0, entityList.size()).mapToObj(index -> {// 提取:当前用户信息实体。UserInfoEntity entity = entityList.get(index);// 封装:用户信息模型。UserInfoEntityModel model = new UserInfoEntityModel();// 行号。model.setRowNum(index + 1);//添加批注CommentData commentData = new CommentData();//创建批注对象commentData.setAuthor("作者:Jshuai");//设置批注的作者commentData.setRichTextStringData(new RichTextStringData("备注:这是一个备注信息"));WriteCellData<Long> id = new WriteCellData<>(BigDecimal.valueOf(entity.getId()));//设置在那个字段上面添加批注id.setCommentData(commentData);//设置批注信息model.setId(id);//将设置批注信息与字段绑定// 用户昵称。HyperlinkData hyperlinkData = new HyperlinkData();hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);hyperlinkData.setAddress("http://www.xxx.com/user/" + entity.getId());WriteCellData<String> userNickname = new WriteCellData<>(entity.getUserNickname());userNickname.setHyperlinkData(hyperlinkData);model.setUserNickname(userNickname);// 用户性别。model.setUserGender(entity.getUserGender());// 用户生日。model.setUserBirth(entity.getUserBirth());// 用户年龄。FormulaData formulaData = new FormulaData();formulaData.setFormulaValue("CONCAT(DATEDIF(E" + (index + 2) + ", NOW(), \"Y\"), \"岁\")");WriteCellData<Void> userAge = new WriteCellData<>();userAge.setFormulaData(formulaData);model.setUserAge(userAge);return model;}).collect(Collectors.toList());EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export156.xlsx").sheet("用户信息").head(UserInfoEntityModel.class).doWrite(modelList);}

9、导出图片内容

在这里插入图片描述

导出图片内容语法
  1. 导出图片类型
@ContentRowHeight(value=50)@ColumnWidth(value=30)public class ExportModel {@ExcelProperty(value = "File类型")private File fileImage;@ExcelProperty(value = "byte[]类型")private byte[] byteImage;@ExcelProperty(value = "Inputstream类型")private InputStream inputStreamImage;@ExcelProperty(value = "URL类型")private URL urlImage;@ExcelProperty(value = "string类型", converter = StringImageConverter.class)//不设置转换器的话,导出时是一个字符串private String stringImage;}
  1. 基本语法
File file = new File("E:\\export.xlsx");// 封装:模型对象。ExportModel exportModel = new ExportModel();exportModel.setFileImage(图片的File对象);exportModel.setByteImage(图片的byte[] 对象);exportModel.setInputStreamImage(图片的InputStream对象);exportModel.setUrlImage(图片的URL对象);exportModel.setStringImage(图片文件路径);
//处理:导出操作。
EasyExcel.write(file).sheet().head(ExportModel .class).doWrite(Collections.singletonList(exportModel));

3、模版填充

1、模版填充对象

在这里插入图片描述

基本语法Map填充
//封装:Map对象:
Map<String,Object> fillData = new HashMap<>();fillData.put("userNumber","1001");fillData.put("userName","Jshuai");fillData.put("userAccount",BigDecimal.valueOf(666.66));fillData.put("userscore",888);//处理:导出操作。
EasyExcel.write(导出目标)
.withTemplate(模板文件)
.sheet()
.doFill(fillData))//数据填充

测试

@Testpublic void test7(){InputStream resourceAsStream = EasyExcelWiteTest.class.getClassLoader().getResourceAsStream("export-template.xlsx");//封装:Map对象:Map<String,Object> fillData = new HashMap<>();fillData.put("userNumber","1001");fillData.put("userName","Jshuai");fillData.put("userAccount",BigDecimal.valueOf(666.66));fillData.put("userscore",888);//处理:导出操作。EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export-template.xlsx").withTemplate(resourceAsStream).sheet().doFill(fillData);}

在这里插入图片描述


基本语法对象填充
  1. 实体类
@Data
public class UserModel {private String userNumber;private String userName;private BigDecimal userAccount;private Integer userScore;
}
  1. 测试
@Testpublic void test8(){InputStream resourceAsStream = EasyExcelWiteTest.class.getClassLoader().getResourceAsStream("export-template.xlsx");//封装:Map对象:UserModel userModel=new UserModel();userModel.setUserNumber("1001");userModel.setUserName("JshuaiBoss");userModel.setUserAccount(BigDecimal.valueOf(666.66));userModel.setUserScore(888);//处理:导出操作。EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export-template.xlsx").withTemplate(resourceAsStream).sheet().doFill(userModel);}

在这里插入图片描述

2、模版填充列表

批量填充时,模版设置时,在在占位符前面加一个点

在这里插入图片描述

语法
//封装:List对象:
List<Object> fillData = new ArrayList<>();//处理:导出操作。
EasyExcel.write(导出目标)
.withTemplate(模板文件)
.sheet()
.doFill(list))//数据填充

测试

@Testpublic void test9(){InputStream resourceAsStream = EasyExcelWiteTest.class.getClassLoader().getResourceAsStream("export-template.xlsx");//封装:Map对象:UserModel userModel=new UserModel();userModel.setUserNumber("1001");userModel.setUserName("JshuaiBoss");userModel.setUserAccount(BigDecimal.valueOf(666.66));userModel.setUserScore(888);UserModel userModel2=new UserModel();userModel2.setUserNumber("1002");userModel2.setUserName("JshuaiBoss2");userModel2.setUserAccount(BigDecimal.valueOf(666.77));userModel2.setUserScore(999);List<UserModel> list = Arrays.asList(userModel, userModel2);//处理:导出操作。EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export-template.xlsx").withTemplate(resourceAsStream).sheet().doFill(list);}

在这里插入图片描述

3、模版填充组合

在这里插入图片描述

基本语法
try (ExcelWriter excelWriter = EasyExcel.write(..).withTemplate(..)...){WriteSheet writeSheet = EasyExcel.writerSheet().build();//处理:填充公司信息对象。excelWriter.fill(<公司信息对象 >,writeSheet);//处理:填充部门集合列表。FillConfig fillconfig = Fillconfig.builder().direction(WriteDirectionEnum.HORIZONTAL)//横向,默认纵向.build();excelWriter.fill(new FillWrapper("dept", <部门集合>), fillconfig, writeSheet);//处理:填充员工集合列表。excelWriter.fill(new FillWrapper("employee", <员工集合>),writeSheet);}

在这里插入图片描述

测试

@Testpublic void test10() {InputStream exportTemplate = EasyExcelWiteTest.class.getClassLoader().getResourceAsStream("export-templates.xlsx");try (ExcelWriter excelWriter = EasyExcel.write("C:\\Users\\lenovo\\Desktop\\123\\export12026.xlsx").withTemplate(exportTemplate).build()) {WriteSheet writeSheet = EasyExcel.writerSheet().build();// 公司信息。Map<String, Object> companyInfo = new HashMap<>();companyInfo.put("companyName", "大明帝国信息技术有限公司");excelWriter.fill(companyInfo, writeSheet);// 部门信息。Map<String, Object> deptInfo1 = new HashMap<>();deptInfo1.put("deptName", "研发部");deptInfo1.put("deptMaster", "张先生");deptInfo1.put("deptContact", "186****7420");Map<String, Object> deptInfo2 = new HashMap<>();deptInfo2.put("deptName", "设计部");deptInfo2.put("deptMaster", "李女士");deptInfo2.put("deptContact", "185****7420");List<Map<String, Object>> deptList = Arrays.asList(deptInfo1, deptInfo2);FillConfig fillconfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); // 填充配置excelWriter.fill(new FillWrapper("dept", deptList), fillconfig, writeSheet);// 填充部门信息// 员工信息。Map<String, Object> empInfo1 = new HashMap<>();empInfo1.put("userNumber", "A001002");empInfo1.put("userName", "张三");empInfo1.put("userAccount", 12);empInfo1.put("userscore", BigDecimal.valueOf(120));Map<String, Object> empInfo2 = new HashMap<>();empInfo2.put("userNumber", "A001005");empInfo2.put("userName", "李四");empInfo2.put("userAccount", 16);empInfo2.put("userscore", BigDecimal.valueOf(24));List<Map<String, Object>> empList = Arrays.asList(empInfo1, empInfo2);excelWriter.fill(new FillWrapper("user", empList), writeSheet);// 填充员工信息}}

在这里插入图片描述


4、导出文件下载

语法
 //1.处理:设置响应参数(内容类型、字符集编码)。
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());//2.处理:设置文件名。
String fileName = URLEncoder.encode("用户列表","UTF-8").replaceAll("\\+","%20");
response.setHeader("content-Disposition", "attachment;filename*=UTF-8’" + fileName + ".xlsx");//3.处理:导出文件到输出流。
InputStream inputStream = Application.class.getclassloader().getResourceAsStream("user-export-template.xlsx");
OutputStream outputStream=response.getOutputStream();EasyExcel.write(outputStream);
EasyExcel.write(outputStream).withTemplate(inputStream).sheet("用户列表").doFill(list);

相关文章:

  • 【Linux系统】第二节—基础指令(2)
  • 【ArcGIS微课1000例】0144:沿线或多边形要素添加折点,将曲线线段(贝塞尔、圆弧和椭圆弧)替换为线段。
  • Spring MVC设计与实现
  • 【Java JUnit单元测试框架-60】深入理解JUnit:Java单元测试的艺术与实践
  • 架构思维:利用全量缓存架构构建毫秒级的读服务
  • 【C++ Qt】输入类控件(上) LineEdit、QTextEdit
  • 仓颉编程语言快速入门:从零构建全场景开发能力
  • 主成分分析(PCA)与逻辑回归在鸢尾花数据集上的实践与效果对比
  • PyTorch_张量索引操作
  • 【C++】 —— 笔试刷题day_25
  • [硬件电路-12]:LD激光器与DFB激光器功能概述、管脚定义、功能比较
  • Qwen2.5模型性能测评 - 速度指标
  • 【Linux】命令行参数与环境变量
  • LeetCode 热题 100 54. 螺旋矩阵
  • ES6入门---第三单元 模块四:Set和WeakSet
  • LLama-v2 权重下载
  • Webug4.0靶场通关笔记14- 第18关 文件上传之Nginx解析缺陷
  • Python-Django系列—视图
  • 【ArcGIS微课1000例】0145:如何按照自定义形状裁剪数据框?
  • Rust与C/C++互操作实战指南
  • 五一假期旅游大市党政领导靠前调度,重视解决游客反映的问题
  • 准80后遵义市自然资源局局长陈清松任仁怀市委副书记、代市长
  • 北部艳阳高照、南部下冰雹,五一长假首日上海天气很“热闹”
  • 海警巡航时海豚围舰艇嬉戏,专家:证明海域生态环境持续向好
  • 扬州市中医院“药膳面包”走红,内含党参、黄芪等中药材
  • 宁波市纪委监委通报4起违反中央八项规定精神典型问题