阿里出品 easyExcel[基于poi] 入门小结及优化
着急可直接看最下面java代码
常用maven依赖
<!-- Excel 工具 开始 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
<!-- Excel 工具 结束 -->
<!-- 其他依赖 -->
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<!--<scope>provided</scope>-->
</dependency>
<!-- JSON 工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
常见问题
1. com.alibaba.excel.exception.ExcelCommonException: Convert excel format exception.You can try specifying the ‘excelType’ yourself
此情况先看是否能找到指定路径下的文件
注意:获取根目录功能 可能在Junit 中不生效
java.io.IOException: Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data.
zip 炸弹检测!
在解压缩时,它会检查比率compressedBytes/uncompressedBytes,如果低于特定数量 ( MinInflateRatio),则检测到炸弹。

源码中默认最小比例为 0.01D. 这意味着压缩文件比未压缩文件小 100 倍,而不会丢失信息。换言之,压缩后的文件仅以未压缩文件大小的 1% 存储相同的信息。
Uncompressed size[未压缩大小]: 875067, Raw/compressed size[压缩大小]: 8704, ratio[比例]: 0.009947
解决方案
但这意味着没有要解压缩的字节。因此,
MinInflateRatioof0.0d永远无法达到,也无法被低估。因此MinInflateRatio,0.0d所有可能的比率都将被接受。当然
MinInflateRatio,-1.0d也永远无法达到或被低估。所以使用这个也将接受所有可能的比率。
常用注解
@ColumnWidth 用于设置列宽度的注解。
参数:
注解中只有一个参数value,value的单位是字符长度,最大可以设置255个字符,因为一个excel单元格最大可以写入的字符个数就是255个字符。
@HeadFontStyle 用于定制标题字体格式
参数:
fontName 字体名称
fontHeightInPoints 字体高度
italic 是否斜体
strikeout 是否设置删除水平线
color 字体颜色
typeOffset 偏移量
underline 下划线
bold 是否加粗
charset 编码格式
@ContentLoopMerge 用于设置合并单元格的注解
标注在属性上
参数:
eachRow 合并行
columnExtend 合并列
@ContentRowHeight 用于设置行高
参数:
value 行高,-1代表自动行高
@ContentStyle 设置内容格式注解
参数:
dataFormat 日期格式
hidden 设置单元格使用此样式隐藏
locked 设置单元格使用此样式锁定
quotePrefix 在单元格前面增加'`'符号,数字或公式将以字符串形式展示
horizontalAlignment 设置是否水平居中
wrapped 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment 设置是否垂直居中
rotation 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°~90°,07版本的Excel旋转角度区间为0°~180°
indent 设置单元格中缩进文本的空格数
borderLeft 设置左边框的样式
borderRight 设置右边框样式
borderTop 设置上边框样式
borderBottom 设置下边框样式
leftBorderColor 设置左边框颜色
rightBorderColor 设置右边框颜色
topBorderColor 设置上边框颜色
bottomBorderColor 设置下边框颜色
fillPatternType 设置填充类型
fillBackgroundColor 设置背景色
fillForegroundColor 设置前景色
shrinkToFit 设置自动单元格自动大小
@HeadRowHeight设置标题行行高
参数:
value 设置行高,-1代表自动行高
@HeadStyle 设置标题样式
参数:
dataFormat 日期格式
hidden 设置单元格使用此样式隐藏
locked 设置单元格使用此样式锁定
quotePrefix 在单元格前面增加`符号,数字或公式将以字符串形式展示
horizontalAlignment 设置是否水平居中
wrapped 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment 设置是否垂直居中
rotation 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°~90°,07版本的Excel旋转角度区间为0°~180°
indent 设置单元格中缩进文本的空格数
borderLeft 设置左边框的样式
borderRight 设置右边框样式
borderTop 设置上边框样式
borderBottom 设置下边框样式
leftBorderColor 设置左边框颜色
rightBorderColor 设置右边框颜色
topBorderColor 设置上边框颜色
bottomBorderColor 设置下边框颜色
fillPatternType 设置填充类型
fillBackgroundColor 设置背景色
fillForegroundColor 设置前景色
shrinkToFit 设置自动单元格自动大小
@ExcelIgnore 不将该字段转换成Excel
@ExcelIgnoreUnannotated 没有@ExcelProperty注解的字段都不转换
@ExcelProperty 可以理解为标题列与实体对应的注解
@ExcelProperty("姓名") # 根据标题[列名]匹配
@ExcelProperty(index = 1) # 根据列数 0 代表第一列,以此类推
@ExcelProperty(value = "婚姻状态",converter = CustomStringToBooleanConverter.class)
# 注意事项:
# 1、不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
# 2、如果用名字去匹配,名字重复,会导致只有一个字段读取到数据
# 根据Excel 结构变化频率去选择 index/name。
参数:
value 标题名
index 列序号
converter 数据转换方式
@DateTimeFormat 日期转换
用String去接收excel日期格式的数据会调用这个注解。里面的value参照 java.text.SimpleDateFormat
例:yyyy-MM-dd HH:mm:ss
@NumberFormat 数字转换
用String去接收excel数字格式的数据会调用这个注解。里面的value参照 java.text.DecimalFormat
例:
“0”——表示一位数值,如没有,显示0。如“0000.0000”,整数位或小数位>4,按实际输出,<4整数位前面补0小数位后面补0,凑足4位。
“#”:无小数,小数部分四舍五入。
“.#”:整数部分不变,一位小数,四舍五入。
“.##”:整数部分不变,二位小数,四舍五入。
“.”——表示小数点。
常用监听器
PageReadListener
# 功能简介:读取Excel数据,默认100条返回一次
# 注意事项: 此处如果调用写入数据库操作,建议用批量插入,最好别一条一条插入。
Java 代码
easyExcel 工具类
package com.husky.easyexcle.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.fastjson.JSON;
import com.husky.easyexcle.entity.ExcelDateEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author husky
* @Date 2022/3/14 16:13
* @Description: easyExcel 工具类
**/
@Slf4j
public class ExcleUtil {
/**
* 读取Excel文件数据
* @param fileName excel 文件名
*/
public <T> void readExcel(String fileName, Class<T> tclass) {
//获取根目录
ApplicationHome ah = new ApplicationHome(this.getClass());
String excelPath = ah.getSource().getParentFile().toString()+"/excel/";
log.info("excelPath={}",excelPath);
ExcelReader excelReader = null;
AtomicInteger count = new AtomicInteger();
try {
EasyExcel.read(excelPath+fileName, ExcelDateEntity.class, new PageReadListener<T>(
dataList -> {
for (T demoData : dataList) {
}
log.info("Excel内容{}", JSON.toJSONString(dataList));
count.set(dataList.size());
log.info("Excel内容数量:{}",count);
}
)).sheet(0).doRead();
}catch (Exception e){
log.error("Excel PageReadListener 读取出错。Exception={}",e);
}finally {
if (excelReader != null) {
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
}
}
}
/**
* 将数据写入Excel
* @param fileName 文件名
* @param sheetName 工作簿名称
* @param dataList 带写入数据
*/
public <T> void exportExcle(String fileName,String sheetName,List<T> dataList, Class headClass){
//获取根目录
ApplicationHome ah = new ApplicationHome(this.getClass());
//excle 导出文件夹
String excelPath = ah.getSource().getParentFile().toString()+"/excel/";
//根据年月日创建文件夹
String timePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")).replace("-","/")+"/";
log.info("excelPath={}",excelPath);
//如果没有文件夹则新建
File filePath = new File(excelPath + timePath);
if (!filePath.exists()) {
filePath.mkdirs();
}
EasyExcel.write(excelPath+timePath+fileName, headClass)
.sheet(sheetName)
.doWrite(() -> {
log.info("待导出数据={}",dataList);
return dataList;
});
}
public static void main(String[] args) {
List<ExcelDateEntity> list = new CopyOnWriteArrayList<>();
ExcelDateEntity excelDateEntity = new ExcelDateEntity();
excelDateEntity.setAge(19);
excelDateEntity.setBirthday(LocalDateTime.now());
excelDateEntity.setMarriedFlag(true);
excelDateEntity.setName("林婉儿");
excelDateEntity.setPartyMemberFlag(1);
excelDateEntity.setShowFlag("不展示");
excelDateEntity.setSalary("300.2345");
excelDateEntity.setStature("173");
list.add(excelDateEntity);
// new ExcleUtil().exportExcle("aaa.xlsx","我是工作簿",list,ExcelDateEntity.class);
new ExcleUtil().readExcel("test.xlsx",excelDateEntity.getClass());
}
public static <T> List<T> readWebExcelData(MultipartFile file, Class<T> tclass) {
List<T> resultList = new CopyOnWriteArrayList<>();
ExcelReader excelReader = null;
AtomicInteger count = new AtomicInteger();
try {
EasyExcel.read(file.getInputStream(), tclass, new PageReadListener<T>(
dataList -> {
for (T demoData : dataList) {
resultList.add(demoData);
}
log.info("Excel内容{}", JSON.toJSONString(dataList));
count.set(dataList.size());
log.info("Excel内容数量:{}",count);
}
)).sheet(0).doRead();
return resultList;
}catch (Exception e){
log.error("Excel PageReadListener 读取出错。Exception={}",e);
}finally {
if (excelReader != null) {
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
excelReader.finish();
}
}
return resultList;
}
}
Excel 数据封装实体
package com.husky.easyexcle.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.husky.easyexcle.annotation.ExportAppendStringAnnotation;
import com.husky.easyexcle.annotation.StringToBooleanConverterAnnotation;
import com.husky.easyexcle.annotation.StringToIntegerConverterAnnotation;
import com.husky.easyexcle.converter.CustomExportAppendStringConverter;
import com.husky.easyexcle.converter.CustomStringToBooleanConverter;
import com.husky.easyexcle.converter.CustomStringToIntegerConverter;
import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
/**
* @Author husky
* @Date 2022/3/14 16:18
* @Description: Excel 数据封装实体
**/
@ColumnWidth(15) //列宽
@HeadRowHeight(20) //标题行高
@HeadFontStyle(fontHeightInPoints = 12, color = 9) //文件头的字体大小和颜色
@Data // lombok注解
@Slf4j
public class ExcelDateEntity {
@ExcelProperty(value = "姓名")
private String name;
@ExcelProperty(value = "年龄")
private Integer age;
/**
* 指定字符转转为布尔值
*/
@StringToBooleanConverterAnnotation(trueStr = "已婚",falseStr = "未婚")
@ExcelProperty(value = "婚姻状态",converter = CustomStringToBooleanConverter.class)
private boolean marriedFlag;
@ExportAppendStringAnnotation(endPositionContent = "万元/月")
@ExcelProperty(value = "薪资",converter = CustomExportAppendStringConverter.class)
private String salary;
@ColumnWidth(20) //列宽
@ExcelProperty(value = "生日")
@DateTimeFormat(value = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthday;
/**
* 指定字符串转为指定数字
*/
@StringToIntegerConverterAnnotation(converterEnums = {StringToIntegerConverterEnum.CHINESE_NO,StringToIntegerConverterEnum.CHINESE_YES})
@ExcelProperty(value = "是否党员",converter = CustomStringToIntegerConverter.class)
private Integer partyMemberFlag;
/**
* NumberFormat 常用
* “0”——表示一位数值,如没有,显示0。如“0000.0000”,整数位或小数位>4,按实际输出,<4整数位前面补0小数位后面补0,凑足4位。
* “#”:无小数,小数部分四舍五入。
* “.#”:整数部分不变,一位小数,四舍五入。
* “.##”:整数部分不变,二位小数,四舍五入。
* “.”——表示小数点。
*/
@ExportAppendStringAnnotation(beginPositionContent = "TA", endPositionContent = "CM")
@ExcelProperty(value = "身高",converter = CustomExportAppendStringConverter.class)
@NumberFormat(value = ".#########")
private String stature;
/**
* excel 匹配时忽略该字段
*/
@ExcelIgnore
@ExcelProperty(value = "爱好")
private String showFlag;
}
指定字符串转指定数字枚举类
package com.husky.easyexcle.enums;
/**
* @Author husky
* @Date 2022/3/15 13:23
* @Description: 指定字符串转指定数字枚举类
**/
public enum StringToIntegerConverterEnum {
/**
* 中文是
*/
CHINESE_YES("是",1,"中文是"),
/**
* 中文否
*/
CHINESE_NO("否",2,"中文否"),
/**
* 小写英文是
*/
LOWERCASE_ENGLISH_YES("yes",2,"小写英文是"),
/**
* 小写英文否
*/
LOWERCASE_ENGLISH_NO("no",2,"小写英文否"),
;
/**
* 带转换的字符串
*/
private String key;
/**
* 带转换的字符串
*/
private Integer value;
/**
* 备注,便于阅读
*/
private String remark;
/**
* 私有构造,防止被外部调用
* @param key 带转换的字符串
* @param value 字符串转换的数字
* @param remark 备注,便于阅读
*/
private StringToIntegerConverterEnum(String key, int value,String remark){
this.key=key;
this.value=value;
this.remark = remark;
}
/**
* 获取键[带转换的字符串]
* @return
*/
public String getKey(){
return this.key;
}
/**
* 获取值[字符串转换的数字]
* @return
*/
public int getValue(){
return this.value;
}
}
字符串转布尔注解
字符串 转布尔 注解,用于easyExcel。与 CustomStringToBooleanConverter 连用
package com.husky.easyexcle.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author husky
* @Date 2022/3/15 11:25
* @Description: 字符串 转布尔 注解,用于easyExcel。与 CustomStringToBooleanConverter 连用
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface StringToBooleanConverterAnnotation {
/**
* 为true时的字符串
* @return
*/
public String trueStr();
/**
* 为false时的字符串
* @return
*/
public String falseStr();
}
指定字符串转指定数字注解
指定字符串转指定数字注解,用于easyExcel。与 CustomStringToIntegerConverter 连用
package com.husky.easyexcle.annotation;
import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author husky
* @Date 2022/3/15 13:34
* @Description: 指定字符串转指定数字注解,用于easyExcel。与 CustomStringToIntegerConverter 连用
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface StringToIntegerConverterAnnotation {
/**
* 带转换枚举
* @return
*/
public StringToIntegerConverterEnum[] converterEnums();
}
导出时追加指定字符串注解
package com.husky.easyexcle.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author husky
* @Date 2022/3/16 16:43
* @Description: 导出时追加指定字符串
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExportAppendStringAnnotation {
/**
* 开始位置追加内容
* @return
*/
public String beginPositionContent() default "";
/**
* 结束位置追加内容
* @return
*/
public String endPositionContent() default "";
}
自定义字符串转布尔值转换器
package com.husky.easyexcle.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
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;
import com.husky.easyexcle.annotation.StringToBooleanConverterAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
/**
* @Author husky
* @Date 2022/3/15 10:52
* @Description: 自定义字符串转布尔值转换器
**/
@Slf4j
public class CustomStringToBooleanConverter implements Converter<Boolean> {
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里是读的时候会调用
*
* @return
*/
@Override
public Boolean convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
// 默认返回false
boolean result = false;
try{
//获取属性上 StringToBooleanConverterAnnotation 注解
StringToBooleanConverterAnnotation annotation = contentProperty.getField().getAnnotation(StringToBooleanConverterAnnotation.class);
//判断该注解是否存在
if(annotation != null){
//获取Excle读取到的字符串类型的值
String stringValue = cellData.getStringValue();
//Excle读取到值真实有效
if(!ObjectUtils.isEmpty(stringValue)){
//判断注解为true时的字符串 是否与 Excle读取到值相同
boolean srtFlag = annotation.trueStr().equals(stringValue);
if(srtFlag){
//相同返回true
result = true;
}
}
}else{
log.error("使用自定义字符串转布尔值转换器,缺少配套注解@StringToBooleanConverterAnnotation");
}
}catch (Exception e){
log.error("使用自定义字符串转布尔值转换器,获取属性反射异常。Exception={}",e);
}
return result;
}
/**
* 这里是写的时候会调用
* @return
*/
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<Boolean> context) {
// 默认返回空字符串
String result = "";
try {
//获取属性上 StringToBooleanConverterAnnotation 注解
StringToBooleanConverterAnnotation annotation = context.getContentProperty().getField().getAnnotation(StringToBooleanConverterAnnotation.class);
//判断该注解是否存在
if(annotation != null){
//读取待写入的布尔值
boolean booleanValue = context.getValue();
if(booleanValue){
// 将为true时的字符串反写到Excel
result = annotation.trueStr();
}else{
// 将为false时的字符串反写到Excel
result = annotation.falseStr();
}
}else{
log.error("写入时使用自定义字符串转布尔值转换器,缺少配套注解@StringToBooleanConverterAnnotation");
}
}catch (Exception e){
log.error("将数据写入Excle出现异常。Exception={}",e);
}
return new WriteCellData<>(result);
}
}
自定义指定字符串转指定数字转换器
package com.husky.easyexcle.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
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;
import com.husky.easyexcle.annotation.StringToIntegerConverterAnnotation;
import com.husky.easyexcle.enums.StringToIntegerConverterEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
/**
* @Author husky
* @Date 2022/3/15 10:52
* @Description: 自定义指定字符串转指定数字转换器
**/
@Slf4j
public class CustomStringToIntegerConverter implements Converter<Integer> {
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里是读的时候会调用
*
* @return
*/
@Override
public Integer convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
// 默认返回 0
Integer result = 0;
try{
StringToIntegerConverterAnnotation annotation = contentProperty.getField().getAnnotation(StringToIntegerConverterAnnotation.class);
if(annotation != null){
//获取Excel中读取的数据
String stringValue = cellData.getStringValue();
//获取的String类型数据不为空
if(!ObjectUtils.isEmpty(stringValue)){
//获取属性上的注解中传递的枚举值
StringToIntegerConverterEnum[] stringToIntegerConverterEnums = annotation.converterEnums();
//判断注解中枚举值真实存在
if(stringToIntegerConverterEnums != null){
//遍历注解中传递的枚举值
for(StringToIntegerConverterEnum stice:stringToIntegerConverterEnums){
//如果 Excel中读取的数据 与 传递的枚举中数据匹配
boolean intFlag = stice.getKey().equals(stringValue);
if(intFlag){
//返回值为枚举值配置的返回数字
result = stice.getValue();
}
}
}
}
}else{
log.error("使用自定义字符串转数字转换器,缺少配套注解@StringToIntegerConverterAnnotation");
}
}catch (Exception e){
log.error("使用自定义字符串转数字转换器,获取属性反射异常。Exception={}",e);
}
return result;
}
/**
* 这里是写的时候会调用
* @return
*/
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) {
String result = "";
try{
StringToIntegerConverterAnnotation annotation = context.getContentProperty().getField().getAnnotation(StringToIntegerConverterAnnotation.class);
if(annotation != null){
//获取带写入Excel中数据
int intValue = context.getValue();
//获取的String类型数据不为空
if(!ObjectUtils.isEmpty(intValue)){
//获取属性上的注解中传递的枚举值
StringToIntegerConverterEnum[] stringToIntegerConverterEnums = annotation.converterEnums();
//判断注解中枚举值真实存在
if(stringToIntegerConverterEnums != null){
//强烈建议!!!枚举值不要重复,如果重复则取最后一个
//遍历注解中传递的枚举值
for(StringToIntegerConverterEnum stice:stringToIntegerConverterEnums){
//如果 Excel中读取的数据 与 传递的枚举中数据匹配
boolean intFlag = stice.getValue() == intValue;
if(intFlag){
//返回值为枚举中配置的key
result = stice.getKey();
}
}
}
}
}else{
log.error("使用自定义字符串转数字转换器,缺少配套注解@StringToIntegerConverterAnnotation");
}
}catch (Exception e){
log.error("使用自定义字符串转数字转换器,获取属性反射异常。Exception={}",e);
}
return new WriteCellData<>(result);
}
}
自定义导出时追加字符串转换器
package com.husky.easyexcle.converter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
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;
import com.husky.easyexcle.annotation.ExportAppendStringAnnotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* @Author husky
* @Date 2022/3/16 16:36
* @Description: 自定义导出时追加字符串转换器
* 注意: 此注解不可以写在 BigDecimal 类型的属性上
**/
@Slf4j
public class CustomExportAppendStringConverter implements Converter<String> {
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
/**
* 这里是读的时候会调用
*
* @return
*/
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
return cellData.getStringValue();
}
/**
* 这里是写的时候会调用
* @return
*/
@Override
public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
String result = "";
try{
ExportAppendStringAnnotation annotation = context.getContentProperty().getField().getAnnotation(ExportAppendStringAnnotation.class);
if(annotation != null){
//获取带写入Excel中数据 并且将格式强转为字符串
// String value = context.getValue();
String value = context.getValue()+"";
//获取的String类型数据不为空
if(StringUtils.hasLength(value)){
result = value;
// 如果开始位置追加内容不为空
if(!ObjectUtils.isEmpty(annotation.beginPositionContent())){
result = annotation.beginPositionContent()+result;
}
// 如果结束位置追加内容不为空
if(!ObjectUtils.isEmpty(annotation.endPositionContent())){
result = result+annotation.endPositionContent();
}
}
}else{
log.error("导出时追加指定字符串,缺少配套注解@ExportAppendStringAnnotation");
}
}catch (Exception e){
log.error("自定义导出时追加字符串转换器,获取属性反射异常。Exception={}",e);
}
return new WriteCellData<>(result);
}
}
导入文件读取Excel
Excel相关控制层
package com.husky.easyexcle;
import com.husky.easyexcle.entity.ExcelDateEntity;
import com.husky.easyexcle.service.ExcelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
* @Author husky
* @Date 2022/3/22 15:58
* @Description: Excel相关控制层
**/
@RestController
@Slf4j
public class ExcelController {
@Autowired
private ExcelService excelServiceImpl;
/**
* 读取上传Excel数据
* @param file
* @return
* @throws IOException
*/
@PostMapping("read/excel/data")
public String readExcelData(MultipartFile file) throws IOException {
log.info("读取上传Excel开始。file={}",file);
try {
List<ExcelDateEntity> list = excelServiceImpl.readExcelData(file);
log.info("list={}",list);
return "SUCCESS";
}catch (Exception e){
log.error("读取上传Excel异常。Exception={}",e);
return "FAIL";
}
}
}
Excelweb相关业务接口
package com.husky.easyexcle.service;
import com.husky.easyexcle.entity.ExcelDateEntity;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author husky
* @Date 2022/3/22 16:08
* @Description: Excelweb相关业务接口
**/
public interface ExcelService {
/**
* 读取上传Excel数据
* @param file
* @return
*/
List<ExcelDateEntity> readExcelData(MultipartFile file);
}
Excelweb相关业务接口实现类
package com.husky.easyexcle.service.impl;
import com.husky.easyexcle.entity.ExcelDateEntity;
import com.husky.easyexcle.service.ExcelService;
import com.husky.easyexcle.utils.ExcleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @Author husky
* @Date 2022/3/22 16:09
* @Description: Excelweb相关业务实现类
**/
@Slf4j
@Service
public class ExcelSerivceImpl implements ExcelService {
/**
* 读取上传Excel数据
* @param file
* @return
*/
@Override
public List<ExcelDateEntity> readExcelData(MultipartFile file) {
return ExcleUtil.readWebExcelData(file, ExcelDateEntity.class);
}
}
本文总结了阿里出品的easyExcel的入门要点,包括常见问题的解决,如Zip bomb异常,以及各种注解和监听器的使用。通过示例代码展示了如何进行日期和数字转换,自定义转换器,以及在导入导出Excel时的操作。
1万+

被折叠的 条评论
为什么被折叠?



