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();//必须抛出}
标准化处理
- 定义一个读取错误的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;}
测试
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();//必须抛出} }
运行
@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、排除那些列导出
语法
- 直接在模型映射类的字段上面添加注解
//显示隐藏 @Excellgnore//在那个模型映射字段添加该注解,这个字段在导出的,就会忽略掉
在导出的时候设置那些是否导出
//设置那些模型字段导出EasyExcel.write(导出目标).head(映射模型.class)//根据集合设置,那些列不导出,Collection<String>:那些模型映射类的字段,如:userName,userGender,将这些封装成Lsit集合。.excludeColumnFiledNames(Collection<String>)//根据集合设置,那些列导出.includeColumnFiledNames(Collection<String>).doWrite(集合数据);
5、导出行高列宽
语法:
手动设置,通过在模型映射类的字段上面添加注解,或者在模型类上面添加,在模型类上面添加,所有导出的字段都生效。
//行高(内容):@ContentRowHeight(value=10) //行高(标题):@HeadRowHeight(value=20) //列宽:@ColumnWidth(value=25)
自动列宽,也可以参照
LongestMatchColumnWidthStyleStrategy
类重写一个EasyExcel.write(file)//自动列宽:根据内容长度自动匹配:默认按照标题匹配 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet() .doWrite(data);
6、合并单元格导出
语法
使用注解:
//firstRowIndex:开始第几行,lastRowindex结束是第几行,firstcolumnindex:第几列开始,lastColumnIndex:第几列结束 @OnceAbsoluteMerge(firstRowIndex =2,lastRowindex =3, firstcolumnindex=0,lastColumnIndex=0) public class 模型映射类{}@ContentLoopMerge(eachRow=2) private String fieldName;
- 自定义策略:
// 循环合并: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);}
自定义合并单元格
合并单元格,有两种方式:
- 是实现
RowWriteHandler
接口,这个是行合并,也是默认的- 是实现
CellWriteHandler
接口,这个是列合并实现
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()));}}} }
测试
- 模型类
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; }
- 测试类
@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);}
但是一般是合并指定列相同的数据
- 自定义合并单元格配置类
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()));}}} }
- 测试类
@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.显示隐藏 @Excellgnore//在那个模型映射字段添加该注解,这个字段在导出的,就会忽略掉 //2. 设置那些模型字段导出EasyExcel.write(导出目标).head(映射模型.class)//根据集合设置,那些列不导出,Collection<String>:那些模型映射类的字段,如:userName,userGender,将这些封装成Lsit集合。.excludeColumnFiledNames(Collection<String>)//根据集合设置,那些列导出.includeColumnFiledNames(Collection<String>).doWrite(集合数据);
指定表头集合
定义:根据需求动态构建表头集合。
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("账户积分"));
处理:使用动态表头导出相关数据。
EasyExcel.write(file).sheet().head(headList) doWrite(数据集合);
自定义导出动态表头
- 模型类
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;}
- 测试类
@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);
测试
- 定义模型类,设置超链接字段
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;}
- 测试
@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);
测试
- 定义模型类,设置批注字段
@ExcelProperty(value = "用户标识") private WriteCellData<Long> id;//设置批注
- 测试
@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);
测试
- 定义模型类,设置公式字段
//用户生日。@ExcelProperty(value = "用户生日")private WriteCellData<Void> userAge;
- 测试
@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、导出图片内容
导出图片内容语法
- 导出图片类型
@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;}
- 基本语法
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);}
基本语法对象填充
- 实体类
@Data public class UserModel {private String userNumber;private String userName;private BigDecimal userAccount;private Integer userScore; }
- 测试
@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);
相关文章:
EasyExcel使用总结
EasyExcel 文章目录 EasyExcel1、导入1.1、基本方式导入1.导入依赖2. 加载源文件基本语法 3. 读取数据行4. 读取结果 1.2、模型映射导入1.定义实体映射类2. 操作读取基本语法 3. 读取数据行4. 读取结果 1.3、导入类型转换器语法 1.4、导入监听器基本语法: 1.5、多行…...
【形式化验证】动态逻辑(DL)的定义解释与示例
动态逻辑(Dynamic Logic, DL)是一种用于描述和验证程序行为的逻辑系统。它结合了命题逻辑、谓词逻辑以及模态逻辑的特点,特别适用于表达程序执行前后的状态变化。以下将从语法、语义以及实际应用等方面详细介绍DL公式的相关内容。 1. 动态逻…...
OpenCv实战笔记(1)在win11搭建opencv4.11.1 + qt5.15.2 + vs2019_x64开发环境
一. 准备工作 Visual Studio 2019(安装时勾选 C 桌面开发 和 Windows 10 SDK) CMake 3.20(官网下载) Qt 5.15.2(下载 Qt Online Installer)安装时勾选 MSVC 2019 64-bit 组件。 opencv 4.11.1 源码下载 git…...
四年级数学知识边界总结思考-上册
目录 一、背景二、过程1.大数的认识**一、知识点梳理****二、知识点的由来****三、作用与意义****四、总结** 2. 公顷和平方千米**一、知识点梳理****二、知识点的由来****三、作用与意义** 3.角的度量**一、知识点梳理****二、知识点的由来****三、作用与意义** 4.平行四边形和…...
(undone) MIT6.S081 2023 学习笔记 (Day10: LAB9 fs file system)
url: https://pdos.csail.mit.edu/6.1810/2023/labs/fs.html 任务1:Large files (moderate) ----------------- 完成 本次作业中,你将扩大xv6文件的最大容量。当前xv6文件被限制为268个块(即268*BSIZE字节,xv6中BSIZE为1024&…...
SpringMVC详解
一:Maven 1.1 概述 (1)项目结构 所有IDE使用Maven创建的项目结构完全一样,maven项目可通用 (2)构建流程(编译、测试、打包、发布) (3)依赖管理 定义ÿ…...
【Python】一直没搞懂生成器是什么。。
生成器 上期我们讲解了迭代器:【Python】一直没搞懂迭代器是什么。。-CSDN博客 这期我们来讲讲它的好兄弟——生成器 生成器 (Generator)? 生成器是一种特殊的 迭代器 (Iterator)。 迭代器 是你可以逐个访问其元素的对象(比如在 for 循环中使用)。列表、元组、字典、字符…...
高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第四章 不定积分同步测试卷 B卷
第四章 不定积分同步测试卷 B卷 一、单项选择题(本大题共5小题,每小题3分,总计15分) 1. 2. 3. 4. 5. 二、填空题(本大题共5小题,每小题3分,总计15分) 6. 7. 8. 9. 10. 三、求解下列各题(本大题共5小题,每小题6分,总计30分) 11. 12. …...
只用Prettier进行格式化项目
1.下载Prettier插件,禁用ESlint 2.在项目根目录新建.prettierrc文件 {"singleQuote": true,"jsxSingleQuote": true,"printWidth": 100,"trailingComma": "none","tabWidth": 2,"semi": f…...
ARM寻址方式
寻址方式指的是确定操作数位置的方式。 寻址方式: 立即数寻址 直接寻址(绝对寻址),ARM不支持这种寻址方式,但所有CISC处理器都支持 寄存器间接寻址 3种寻址方式总结如下: 助记符 RTL格式 描述 ADD r0,r1…...
2025年- H25-Lc133- 104. 二叉树的最大深度(树)---java版
1.题目描述 2.思路 返回左右子树中,最高高度的子树,高度从0开始计数。 3.代码实现 class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;…...
深入理解 Spring MVC:DispatcherServlet 与视图解析机制
import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Locale; import java.util.Map;// 继承自 FrameworkServlet 的 DispatcherServlet 类…...
Python基本语法(lambda表达式)
lambda表达式 lambda的一般形式是在关键字lambda后面跟一个或多个参数,之后再紧跟一个 冒号,接下来是一个表达式。lambda是一个表达式,而不是一个语句,它能够出现 在Python语法不允许def出现的地方。作为表达式,lambd…...
嵌入式按键原理、中断过程与中断程序设计(键盘扫描程序)
按键去抖动 通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号波型如下图。由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。…...
C++负载均衡远程调用学习之实时监测与自动发布功能
目录 1.LarsDns-V0.3BackenThread后端实时监控线程流程 2.LarsDns-V0.3加载当前Route版本号方法实现 3.LarsDns-V0.3加载RouteChange修改表的信息 4.LarsDns-V0.3实现实时监控流程线程业务 5.LarsDnsV0.3编译bug修改和功能测试 6.Lars Web管理界面的集成 7.LarsDnsV0.3 D…...
VSCode常用插件推荐
文章目录 VSCode常用插件推荐1 Git相关插件2 代码格式3 AI工具4 语言插件通用工具参考 VSCode常用插件推荐 1 Git相关插件 2 代码格式 3 AI工具 4 语言插件 通用工具 参考 50 个 VSCode 必装插件推荐 https://mp.weixin.qq.com/s/b_OKvg3hdavtnv7pbWcKWg...
性能优化实践:内存优化技巧
性能优化实践:内存优化技巧 在Flutter应用开发中,内存优化是提升应用性能的关键环节之一。本文将从实战角度深入探讨Flutter内存优化的各种技巧,帮助你构建高性能的Flutter应用。 一、内存分析工具使用 1. DevTools内存分析器 启动DevTool…...
WPF中Behaviors
行为的好处 可以把复杂的界面逻辑抽象出去,让xaml的界面设计更简单,更清爽 1.安装包 Microsoft.Xaml.Behaviors.Wpf2.简单实现拖动效果 <Border Width"100"Height"100"Background"Red"><i:Interaction.Behav…...
FreeRTOS菜鸟入门(十)·消息队列
目录 1. 基本概念 2. 数据存储 3. 运作机制 4. 阻塞机制 4.1 出队阻塞 4.2 入队阻塞 5. 操作示意图 5.1 创建队列 5.2 向队列发送第一个消息 5.3 向队列发送第二个消息 5.4 从队列读取消息 6. 消息队列控制块 7. 消息队列常用函数 7.1 消息队列创建…...
Day3:设置页面全局渐变线性渐变背景色uniapp壁纸实战
效果: 页面全局渐变线性渐变背景色会让这个设计更加有质感 想给页面加背景的时候,就给最外部的布局容器添加一个pageBg这样一个类别 接下来,我们就可以在之前写的common的公共的style里的common-style.css里改变它就行了 线性渐变࿱…...
Ray开源程序 是用于扩展 AI 和 Python 应用程序的统一框架。Ray 由一个核心分布式运行时和一组用于简化 ML 计算的 AI 库组成
一、软件介绍 文末提供程序和源码下载 Ray开源程序 是用于扩展 AI 和 Python 应用程序的统一框架。Ray 由一个核心分布式运行时和一组用于简化 ML 计算的 AI 库组成 二、Ray AI 库的更多信息 数据:适用于 ML 的可扩展数据集训练:分布式训练Tune&…...
19、权限控制:分院帽系统——React 19 RBAC实现
一、分院帽的魔法本质 "RBAC是霍格沃茨城堡的智能分院帽,用角色编织的星轨矩阵阻隔黑魔法入侵!" 魔法部安全司官员挥舞魔杖,角色-权限的量子纠缠态在空中交织成防护结界。 ——基于《国际魔法联合会》第7号安全协议,RB…...
P1802 5 倍经验日
P1802 5 倍经验日 - 洛谷 题目背景 复制Markdown {展开 进入IDE模式 现在乐斗有活动了!每打一个人可以获得5倍经验!absi2011却无奈的看着那一些比他等级高的好友,想着能否把他们干掉。干掉能拿不少经验的。 题目描述 现在abs…...
赋予网页健壮的灵魂 —— TypeScript(下)
7 DOM 操作与类型定义:赋予网页真正的交互 回到最初的目标:让网页动起来。在 TypeScript 中,我们如何安全地操作 HTML 元素并响应用户的交互呢?TypeScript 提供了内置的类型定义来描述浏览器环境中的各种对象(如 docu…...
ARM Linux 设备树
Linux 设备驱动开发详解:基于最新的Linux 4.0内核, 机械工业出版社, 宋宝华, 2015 1. 设备树的起源 • 背景: ARM架构中大量板级代码冗余,硬编码在mach-xxx目录,设备树(Device Tree)引入结构化描述硬件。 • 目的: 减…...
35、C# 中的反射(Reflection)
反射是 C# 和 .NET 框架中的一个重要特性,它允许程序在运行时检查、访问和操作类型、对象、属性和方法等元数据信息。 反射的核心概念 运行时类型检查:反射允许你在程序运行时获取类型的详细信息,而不需要在编译时知道这些信息。动态操作&a…...
驱动中的 mmap() 函数和 file_operations 中的 mmap() 原型的区别
在 Linux 驱动开发中,mmap() 系统调用和 file_operations 结构中的 mmap() 方法虽然功能相关,但原型和用途有显著区别。以下是两者的详细对比: 1. 系统调用 mmap() 的原型 这是用户空间程序调用的系统调用接口,定义在 <sys/mma…...
Go语言八股文之Map详解
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…...
矿泉水瓶的绘制
1.制作中心矩形,大小为60,注意设置矩形的两条边相等 2.点击拉伸,高度为150mm 3.使用圆角命令,点击连接到开始面,同时选中4条边,进行圆角转化,圆角大小为10mm,点击多半径圆角…...
LeetCode 热题 100 54. 螺旋矩阵
LeetCode 热题 100 | 54. 螺旋矩阵 大家好,今天我们来解决一道经典的算法题——螺旋矩阵。这道题在LeetCode上被标记为中等难度,要求我们按照顺时针螺旋顺序返回矩阵中的所有元素。下面我将详细讲解解题思路,并附上Python代码实现。 问题描述…...
方案精读:业财融合转型路径和华为实践【附全文阅读】
在当今快速变化、竞争激烈的时代,业务面临不确定性,业财融合至关重要。以华为为例,其从财务到财经的转型,历经财务四统一变革、IFS 变革等,构建了包含财经能力中心(COE)、业务伙伴(BP)和财经共享中心(SSC)的财务组织架构 。通过实现财务四算拉通、提升预算预测、项目…...
AIDC智算中心建设:计算力核心技术解析
目录 一、智算中心发展概览 二、计算力核心技术解析 一、智算中心发展概览 智算中心是人工智能发展的关键基础设施,基于人工智能计算架构,提供人工智能应用所需算力服务、数据服务和算法服务的算力基础设施,融合高性能计算设备、高速网络以…...
Javase 基础加强 —— 02 泛型
本系列为笔者学习Javase的课堂笔记,视频资源为B站黑马程序员出品的《黑马程序员JavaAI智能辅助编程全套视频教程,java零基础入门到大牛一套通关》,章节分布参考视频教程,为同样学习Javase系列课程的同学们提供参考。 01 认识泛型…...
PowerShell 备份 Windows10/11 还原计算机驱动程序SOP
一、现在计算机C目录下创建一个新的文件夹名称为 driverbackup 二、打开cmd 以管理员身份执行 dism /online /export-driver /destination: C:\driverbackup 在正常情况下,Windows 10会自动检测您的设备所需的驱动程序,并将其安装到您的PC上。 但是&am…...
Python 中的 collections 库:高效数据结构的利器
Python 中的 collections 库:高效数据结构的利器 在 Python 编程中,数据结构的高效使用往往能极大地提升代码的性能和可读性。今天,就让我们来深入了解一下 Python 的 collections 库,它是一个非常实用且强大的工具库,…...
2025年- H24-Lc132-94. 二叉树的中序遍历(树)---java版。
1.题目描述 2.思路 递归遍历:返回值,中序遍历的节点值列表 List。 (1)首先是一个中序遍历的结果函数,传入root参数,定义一个节点值列表result,然后递归调用中序遍历的函数 (2&#…...
第十六届蓝桥杯单片机组省赛(第一套)
看到很多人在问第十六届蓝桥杯单片机难不难,以及实现多少功能可以获得省一。 先介绍下我的作答情况吧,选择题只对一题,程序题的求连续两次距离差值没有考虑负数的情况,其他功能都实现了,成绩是福建省省一第一页&#x…...
使用python写多文件#inlcude
使用下面的程序可以将当前文件夹下面的.c文件的写入main.h文件,我这里是将自己的基于标准库stm32初始化io文件为例。 import osbase ["#ifndef main_H","#define main_H\n","#endif" ]includes set() for file in os.listdir():if…...
深度学习中保存最优模型的实践与探索:以食物图像分类为例
深度学习中保存最优模型的实践与探索:以食物图像分类为例 在深度学习的模型训练过程中,训练一个性能良好的模型往往需要耗费大量的时间和计算资源。而保存最优模型不仅可以避免重复训练,还能方便后续使用和部署。本文将结合食物图像分类的代…...
OpenCv实战笔记(2)基于opencv和qt对图像进行灰度化 → 降噪 → 边缘检测预处理及显示
一、实现效果 二、应用场景 这三步是经典的 “灰度化 → 降噪 → 边缘检测” 预处理流程,常用于: 计算机视觉任务(如物体识别、特征提取)。 图像分析(如文档扫描、车牌识别)。 减少后续算法的计算复杂度&a…...
个人文章不设置vip
今天没登录打开自己文章,发现自己读自己文章还要充值。就感觉很扯。 继而去查看个人的历史文章,发现很多被标注为高质量的文章设置成了VIP文章。 如果仅有一两篇,还可能是本人手滑误设置,这么多就解释不通了。 (大概有…...
【聚类分析】基于copula的风光联合场景生成与缩减
目录 1 主要内容 风光出力场景生成方法 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序方法复现《融合风光出力场景生成的多能互补微网系统优化配置》风光出力场景生成部分,目前大多数研究的是不计风光出力之间的相关性影响,但是地理位置相近…...
CSDN积分详解(介绍、获取、用途)
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 积分**一、积分类型及用途****二、积分获取途…...
运维--计划任务
计划任务分为一次性和循环性的计划任务 1.date的用法 date 月日时分年 eg:date 100118222023 date:查看时间和日期、修改时间和日期 获取当前日期:date +%F F:日期 获取当前时间:date +%H:%M:%S H:时 M:分 S:秒 获取周几: date +%w w:周 …...
AVL树(2):
我们之前讲AVL树,我们讲到了旋转,然后讲了左单旋和右单旋。 但是我们这里的单旋产生的条件都是纯粹的一边比较高, 我们看上面这个图片,当我们插入新的结点导致一边的子树比较高的时候,我们必须是存粹的一边高…...
架构思维:异构数据的同步一致性方案
文章目录 一、引言二、全景架构回顾三、潜在问题问题1:Binlog 延迟——理想 vs 实际问题2:Binlog 格式解析问题3:高可靠消费1. 串行 ACK 消费2. 并行消费+乱序风险3. 解决方案 问题4:缓存数据结构设计1. Key–Value 冗…...
nginx 正反向代理和nginx正则
目录 一. 正向代理 1. 编译安装Nginx 2. 配置正向代理 二. 反向代理 1. 配置nginx七层代理 2. 配置nginx四层代理 三. Nginx 缓存 1. 缓存功能的核心原理和缓存类型 2. 代理缓存功能设置 四. Nginx rewrite和正则 1. Nginx正则 2. nginx location 3. Rewrite …...
SAM-Decoding_ 后缀自动机助力大模型推理加速!
SAM-Decoding: 后缀自动机助力大模型推理加速! 大语言模型(LLMs)的推理效率一直是研究热点。本文介绍的SAM-Decoding方法,借助后缀自动机(Suffix Automaton,SAM)实现推测解码,在提升…...
使用Scrapy构建高效网络爬虫:从入门到数据导出全流程
在数据驱动的时代,网络爬虫已成为获取公开信息的核心工具。本文将带您通过Scrapy框架完成一个实战项目,涵盖从零搭建爬虫到多格式数据导出的完整流程,并深入解析Scrapy的Feed Exports功能。 一、项目背景与目标 我们将爬取书籍网站ÿ…...
Docker安装Gitblit(图文教程)
本章教程,使用Docker安装部署Gitblit。 一、Gitblit简介 Gitblit 是一个基于 Java 的 Git 仓库管理工具,主要用于在局域网或小型团队环境中搭建私有 Git 服务器。它提供了一个简单易用的 Web 界面,用于浏览代码、管理仓库和用户权限等。 二、拉取镜像 sudo docker pull git…...