二、阿里开源 EasyExcel
使用可以直接看(点击)官方文档
github地址:(https://github.com/alibaba/easyexcel

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便
**
pom中引入xml相关依赖

<dependencies><!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.3</version></dependency>
</dependencies>

写excel(导出)

**
通用数据生成 后面不会重复写

//封装好的数据private List<DemoData> data() {List<DemoData> list = new ArrayList<DemoData>();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}


对照excel写实体类

//  @ExcelProperty("字符串标题") 表头名
@Data
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;
}
 /*** 最简单的写* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 直接写即可*/@Testpublic void simpleWrite() {// 写法1String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03版本的excel 则 传入excelType参数即可xlsx改成xls// 参数一:写入excel文件路径// 参数二:写入的数据类型是TbDemo//data()方法是写入的数据,结果是List<DemoData>集合,查询全部数据的方法// 根据用户传入字段 假设我们要忽略 dateEasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());}
public static void uploadExcel(HttpServletResponse response, String name, Class cla, List<?> list) {//防止中文件名,在浏览器消失String fileName = new String(name.getBytes(), StandardCharsets.ISO_8859_1);response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");try {EasyExcel.write(response.getOutputStream(), cla).sheet(name).doWrite(list);} catch (IOException e) {e.printStackTrace();}}

读Excel(导入)

对象


@Data
public class DemoData {private String string;private Date date;private Double doubleData;
}

持久层

/*** 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。**/
public class DemoDAO {public void save(List<DemoData> list) {// 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入}
}

监听器

/ 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);/*** 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<DemoData> list = new ArrayList<DemoData>();/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private DemoDAO demoDAO;public DemoDataListener() {// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数demoDAO = new DemoDAO();}/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param demoDAO*/public DemoDataListener(DemoDAO demoDAO) {this.demoDAO = demoDAO;}/*** 这个每一条数据解析都会来调用** @param data*            one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param context* 该方法不会读取表头* 一行一行读取excel内容*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));//使用需要导入json依赖list.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 所有数据解析完成了 都会来调用*读取完毕后操作* @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();LOGGER.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {LOGGER.info("{}条数据,开始存储数据库!", list.size());demoDAO.save(list);LOGGER.info("存储数据库成功!");}
}

最简单的读


@Testpublic void simpleRead() {// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去// 写法1:String fileName = "D:\\IDEA_Project\\easy-excel\\src\\main\\resources\\excel\\demo.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭// 参数一:读取的excel文件路径// 参数二:读取sheet的一行,将参数封装在DemoData实体类中// 参数三:读取每一行的时候会执行DemoDataListener监听器EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}

案例:

1.Controller层

@RestController
@RequestMapping("/subject")
@CrossOrigin//跨域
public class SubjectController {@Autowiredprivate SubjectService subjectService;@PostMapping("upload/excel")public Result uploadExcel(MultipartFile file) {subjectService.batchImport(file, subjectService);return Result.success();}}

2.service接口层

public interface SubjectService  {/*** excel导入* @param file* @param subjectService*/void batchImport(MultipartFile file,SubjectService subjectService);}

3. SubjectServiceImpl 实现类

@Service
public class SubjectServiceImpl implements SubjectService {/*** excel 上传* @param file* @param subjectService*/@Overridepublic void batchImport(MultipartFile file ,SubjectService subjectService) {//1 获取文件输入流InputStream inputStream = null;try {inputStream = file.getInputStream();// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(inputStream, ExcelSubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();} catch (IOException e) {e.printStackTrace();}}}

4.监听器

package com.yzh.edu.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yzh.edu.entity.Subject;
import com.yzh.edu.excel.ExcelSubjectData;
import com.yzh.edu.service.SubjectService;
import java.util.Map;
/*** @author yzh*/
public  class SubjectExcelListener extends AnalysisEventListener<ExcelSubjectData> {public SubjectService subjectService;/*** 无参构造器*/public SubjectExcelListener() {}/*** 创建有参数构造,传递subjectService用于操作数据库* @param subjectService*/public SubjectExcelListener(SubjectService subjectService) {this.subjectService = subjectService;}/*** 一行一行去读取excle内容*/@Overridepublic void invoke(ExcelSubjectData excelSubjectData, AnalysisContext analysisContext) {if (null == excelSubjectData) {System.out.println("excel导入失败");}//添加一级分类Subject oneSubject = getOneSubject(excelSubjectData.getOneSubjectName());//没有相同的if (null == oneSubject) {oneSubject = new Subject();oneSubject.setTitle(excelSubjectData.getOneSubjectName());oneSubject.setParentId("0");subjectService.save(oneSubject);}//获取一级分类的idString pid = oneSubject.getId();//添加二级分类Subject twoSubject = getTwoSubject(excelSubjectData.getTwoSubjectName(), pid);if (null == twoSubject) {twoSubject = new Subject();twoSubject.setTitle(excelSubjectData.getTwoSubjectName());twoSubject.setParentId(pid);subjectService.save(twoSubject);}}//读取excel表头信息@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {System.out.println("表头信息:"+headMap);}//读取完成后执行@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}//判断一级分类是否重复private Subject getOneSubject(String name) {QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();queryWrapper.eq("parent_id", "0");queryWrapper.eq("title", name);Subject serviceOne = subjectService.getOne(queryWrapper);return serviceOne;}//判断二级分类是否重复private Subject getTwoSubject(String name, String pid) {QueryWrapper<Subject> queryWrapper = new QueryWrapper<>();queryWrapper.eq("title", "name");queryWrapper.eq("parent_id", "pid");Subject serviceOne = subjectService.getOne(queryWrapper);return serviceOne;}}

模板导出

/*** 根据模板,导出重点河流来水情况*/@Overridepublic void downLoadExcel(Map<String, Object> parameterSet) {// 塔城市List<WrRiverRVo> riverTCAll = wrRiverRMapper.getRiverTCAll(parameterSet);// 额敏县List<WrRiverRVo> emAll = wrRiverRMapper.getEMAll(parameterSet);// 乌苏市List<WrRiverRVo> wsAll = wrRiverRMapper.getWSAll(parameterSet);// 沙湾县List<WrRiverRVo> swAll = wrRiverRMapper.getSWAll(parameterSet);// 托里县List<WrRiverRVo> tlAll = wrRiverRMapper.getTLAll(parameterSet);// 裕民县List<WrRiverRVo> ymAll = wrRiverRMapper.getYMAll(parameterSet);// 和丰县List<WrRiverRVo> hfAll = wrRiverRMapper.getHFAll(parameterSet);// 模板String templateFileName = "D:\\work\\新需求20200603\\20200507徐洁整理新需求\\数据库建表\\河流\\河流监测信息表模板.xlsx";// 新的String newFileName = "D:\\work\\新需求20200603\\20200507徐洁整理新需求\\数据库建表\\河流\\河流监测信息表" + System.currentTimeMillis()+ ".xlsx";try {ExcelWriter excelWriter = EasyExcel.write(newFileName).withTemplate(templateFileName).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();// 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹excelWriter.fill(new FillWrapper("tc", riverTCAll), writeSheet);excelWriter.fill(new FillWrapper("em", emAll), writeSheet);excelWriter.fill(new FillWrapper("ws", wsAll), writeSheet);excelWriter.fill(new FillWrapper("sw", swAll), writeSheet);excelWriter.fill(new FillWrapper("tl", tlAll), writeSheet);excelWriter.fill(new FillWrapper("ym", ymAll), writeSheet);excelWriter.fill(new FillWrapper("hf", hfAll), writeSheet);// 千万别忘记关闭流excelWriter.finish();File file = new File(newFileName);Workbook wb = WorkbookFactory.create(new FileInputStream(file));// 刷新excel公式(否则公式不会重新计算)wb.setForceFormulaRecalculation(true);wb.write(new FileOutputStream(newFileName));} catch (Exception e1) {// TODO 自动生成的 catch 块e1.printStackTrace();}}

阿里开源 EasyExcel(Excel导入导出 推荐使用)相关推荐

  1. 二、使用阿里的easyExcel进行导入导出

    0.pom文件中使用的依赖 我用的是如下的版本,低版本的需要重写6个方法,新版的需要重写两个,新版本中其余4个转成了静态方法,不需要重写了. <dependency><groupId ...

  2. 一款Excel导入导出解决方案组成的轻量级开源组件

    Excel-Boot GitHub地址:gitee.com/nw1992/easy- 码云地址:github.com/programmere- Excel-Boot是一款Excel导入导出解决方案组成 ...

  3. easypoi导入校验跳过空行_Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件...

    Excel-Boot是一款Excel导入导出解决方案组成的轻量级开源组件. 如果喜欢或愿意使用, 请star本项目或者点击donate图标捐赠我们 如果是企业使用, 为了产品推广, 请通过评论.Iss ...

  4. easypoi 多sheet导入_easy-poi: Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件。...

    Easy-POI Easy-POI是一款Excel导入导出解决方案组成的轻量级开源组件. 如果喜欢或愿意使用, 请star并且Watch本项目或者移步码云捐赠我们 https://gitee.com/ ...

  5. easyexcel 设置标题_EasyExcel,让 excel 导入导出更加简单

    做积极的人,而不是积极废人! 来源:jianshu.com/p/8f3defdc76d4EasyExcelGitHub上的官方说明快速开始maven仓库地址导入导出总结 EasyExcel 在做exc ...

  6. SpringBoot中使用Easyexcel实现Excel导入导出功能(三)

    导出的数据包含有图片 导出excel表格的数据包含有图片,这种场景比较少.通Easyexcel实现这样的需求,我认为最简便的方法就是使用前面提到的自定义转换器(com.alibaba.excel.co ...

  7. easyexcel 在 设置标题_EasyExcel,让excel导入导出更加简单

    EasyExcel 在做excel导入导出的时候,发现项目中封装的工具类及其难用,于是去gitHub上找了一些相关的框架,最终选定了EasyExcel.之前早有听闻该框架,但是一直没有去了解,这次借此 ...

  8. SpringBoot中使用Easyexcel实现Excel导入导出功能(一)

    目录 前言 1.常规导入 2.读取到指定的列 3.读取全部的sheet页 4.日期.数字及其他自定义格式的转换 5.表头有多行的表格读取 6.表头数据的读取 7.单元格内的备注内容读取 前言 exce ...

  9. EasyExcel(二) 导入导出excel的数据格式转换

    EasyExcel(二) 导入导出excel的数据格式转换 关于easyExcel的基本用法我就不在多说了,有需要的可以自己点击该链接去学习基本的使用,主要对这里面经常用到的一些监听器和拦截器讲一下, ...

最新文章

  1. Android APP测试的日志文件抓取
  2. SpringBoot 搭建基于 minio 的高性能存储服务
  3. ASP.NET MVC应用程序实现下载功能
  4. python支持list类型吗_Python-不支持的操作数类型为%:“list”和“int”
  5. OpenShift 4 之通过命令创建Service Mesh环境
  6. 在Azure Data StudioSQL笔记本中使用Python脚本加密密码
  7. 更开放的分布式事务 | 蚂蚁金服共建 Seata 社区
  8. python 字符串_Python中常用的8种字符串操作方法
  9. 加锁解锁PHP实现 -转载
  10. 按键精灵手机助手连接不上mumu模拟器问题解决办法
  11. 新能源汽车前景广袤但痛点多多,大圆柱电池能否提供最优解?
  12. 动态规划——01背包——精卫填海
  13. IEEE协会首次在京举办研讨会,王飞跃称不存在AI芯片
  14. python使用神器_python 神器
  15. (VQA)LRTA: A Transparent Neural-Symbolic Reasoning Framework with Modular Supervision for Visual Que
  16. 41-C++自动存储、静态存储和动态存储
  17. 一文让你读懂什么是智慧数字经营
  18. 【iOS】设置背景渐变色
  19. java中singleton_java中singleton的几种实现方式
  20. 访客模式 无痕模式 区别_访客设计模式示例

热门文章

  1. 利用shell脚本批量提交网站404死链给百度
  2. android应用市场点击下载APK安装详解
  3. 【学员心得】我的HCIE-DC学习成长旅程
  4. 【百炼】二分法求函数的零点(c语言)
  5. 基于智能合约的状态机设计
  6. 盘点多边形战士Polygon有哪些扩容解决方案|Tokenview
  7. C# ComboBox禁用滚轮滑动事件
  8. MySQL基础(四)运算符
  9. 欢乐家上市后连跌两日:规模增速有所放缓,产能利用率较低
  10. ubuntu 20.04 安装 keepass【解决中文乱码】