阿里出品 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
解决方案
但这意味着没有要解压缩的字节。因此,
MinInflateRatio
of0.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()&