阿里Excel工具的简单使用
记一次阿里Excel工具easyexcel的导入简单使用
maven的配置
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.2-beat1</version>
</dependency>
ExcelData类继承BaseRowModel类
public class XlsMonitorData extends BaseRowModel{
@ExcelProperty(value = "采样日期",index = 1)
private String time;
}
导入功能的使用
直接使用EasyExcel读取数据,注意的是这里的invoke和doAfterAllAnalysed需要重写,因为是观察者模式,这两个函数再取数据时候会被调用,
ZnfkHsjcMapper znfkHsjcMapper = SpringContextHolder.getBean(ZnfkHsjcMapper.class);
Integer BATCH_COUNT = 1000;
List<ZnfkHsjc> znfkHsjcList = new ArrayList<>();
try {
EasyExcelFactory.read(multipartFile.getInputStream(),
new AnalysisEventListener<Map<Integer,String>>() {
//一行一行的读取数据,每到1000个存一次数据,把list集合清空
@Override
public void invoke(Map<Integer,String> row, AnalysisContext analysisContext) {
if(znfkHsjcList.size() >= BATCH_COUNT) {
/**
* 保存到数据库
* @date 2022/5/30 16:21
*/
saveData(znfkHsjcMapper,znfkHsjcList);
znfkHsjcList.clear();
}
if(row != null && row.size() > 0) {
ZnfkHsjc znfkHsjc = toZnfkHsjc(row);
znfkHsjcList.add(znfkHsjc);
}
}
//最后读取完的逻辑,因为我们没每1000行存一次list,所以最后这里一定会剩余几行,所以这里可以把剩余的数据存到数据库,然后在清除
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
/**
* 保存到数据库
* @date 2022/5/30 16:21
*/
saveData(znfkHsjcMapper,znfkHsjcList);
znfkHsjcList.clear();
}
}
).sheet(0).headRowNumber(1).doRead();
} catch (Exception e) {
e.printStackTrace();
log.error("导入数据错误,error = {} \n",e.getMessage(),e);
}
上传文件的代码,这里使用多线程,先返回给用户结果,保存数据的逻辑操作,在后台慢慢处理。主要逻辑是,把MultipartFile的InputStream取出传入ExcelReader构造函数内,excelReader.read()函数执行会调用观察者的invoke函数。
public ResponseStatus importHsjcExcel(MultipartFile multipartFile) {
executor.execute(new ZnfkHsjcThread(multipartFile));
return ResponseUtil.createResponseStatus(ResponseEnum.OK,("导入成功"));
}
导出功能
实体类注解
@Data
@Builder
@HeadRowHeight(value = 20)//设置表头行高
@ColumnWidth(value = 15)//设置表头行宽
public class UserExcel {
@ColumnWidth(value = 15)//单独设置表头行宽
@ExcelProperty(value = "患者姓名", index = 0)//”0“表示excel中的第一列
private String Name;
}
创建Excel导出工具类
package com.lyt.business.app.data.v1.util;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import lombok.extern.log4j.Log4j2;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;
@Log4j2
public class ExcelUtil {
/**
* web中的读excel
* 简单读,读到的异常数据会返回;如果需要扩展,请重写EasyExcelReadEventListener监听器中的方法
* @param inputStream 需要读取的文件流
* @param list 接收读出的数据
* @param t 根据注解@ExcelProperty(index = ?)中的index值依次对应赋值
* @return java.lang.String 返回读取过程中的异常数据及其位置
*/
public static <T extends Object> String readExcel(InputStream inputStream, Class<T> t,List<T> list){
StringBuffer errorMsg = new StringBuffer();
List<T> finalList = list;
EasyExcel.read(inputStream,t, new EasyExcelReadEventListener(){
@Override
public void invoke(Object data, AnalysisContext context) {
finalList.add((T) data);
}
@Override
public void onException(Exception e, AnalysisContext analysisContext){
log.error("解析失败,但是继续解析下一行:{}", e.getMessage());
// 如果是某一个单元格的转换异常 能获取到具体行号
// 如果要获取头的信息 配合invokeHeadMap使用
if (e instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)e;
log.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex()+1,
excelDataConvertException.getColumnIndex()+1, excelDataConvertException.getCellData().getStringValue());
String msg = "第"+(excelDataConvertException.getRowIndex()+1)+"行,第"+(excelDataConvertException.getColumnIndex()+1)+"列解析异常,数据为:"
+excelDataConvertException.getCellData().getStringValue()+"<br/>";
errorMsg.append(msg);
}
}
}).sheet().headRowNumber(2).doRead();
return errorMsg.toString();
}
/**
* web中的读excel
* 扩展读,自己重写EasyExcelReadEventListener监听器中的方法
* @param inputStream 需要读取的文件流
* @param list 接收读出的数据
* @param t 根据注解@ExcelProperty(index = ?)中的index值依次对应赋值
* @param listener 自定义的监听器
* @return java.lang.String 返回读取过程中的异常数据及其位置
*/
public static <T extends Object> String readExcel(InputStream inputStream, Class<T> t,List<T> list,EasyExcelReadEventListener listener){
if (listener == null){
return readExcel(inputStream,t,list);
}
//自行处理数据
EasyExcel.read(inputStream,t,listener).sheet().headRowNumber(2).doRead();
return null;
}
/**
* web中的写Excel
* @param list 要写入的数据
* @param t Class 读的模板,列标题写成注解@ExcelProperty(value = "")中的value值
* @param fileName 文件名称
* @param response HttpServletResponse
*/
public static <T extends Object> void writeExcel(HttpServletResponse response,List<T> list, Class<T> t, String fileName) throws Exception {
// 这里注意 使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), t).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).sheet("sheet").doWrite(list);
}
}
serviceImpl层
public ResponseStatus keyPersonYjsOutput(Param param, HttpServletResponse response) {
List<UserExcel> list = mapper.queryList(param);
try {
ExcelUtil.writeExcel(response,list,UserExcel.class,"excel导出");
} catch (Exception e) {
log.error("导出出现错误{}",e);
}
return ResponseStatus.createOk();
}
参考链接:
https://blog.csdn.net/qq_41910048/article/details/108934354
https://blog.csdn.net/weixin_44774355/article/details/118967819
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具