当前位置:   article > 正文

教您如何三分钟搞定EasyExcel导入与导出功能_easyexcel 导出

easyexcel 导出

文章目录


前言

该文章主要是介绍如何快速实现导入与导出功能

一、EasyExcel是什么?

引用官方的说明:EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

二、使用步骤

1.引入库

pom.xml引入jar依赖包:

  1. <!-- EasyExcel -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>easyexcel</artifactId>
  5. <version>2.2.6</version>
  6. </dependency>

2.导入

2.1创建对应excel表格的实体类

@ExcelProperty该注解的value是对应excle表格的列名称,index对应的是excel列的下标

  1. @Data
  2. public class ImportModel {
  3. /**
  4. * 树根
  5. */
  6. @ExcelProperty(value = "名称", index = 0)
  7. private String ;
  8. /**
  9. * 树根标题
  10. */
  11. @ExcelProperty(value = "编码", index = 1)
  12. private String code;
  13. }

2.2后端接收请求入口

  1. /**
  2. * 导入
  3. */
  4. @ApiOperation("导入")
  5. @PostMapping("/importTree")
  6. public R importTree(@RequestParam("file") MultipartFile file) {
  7. /** 根据自己的业务自行选择在哪处理 */
  8. /** 直接在controllerr处理 */
  9. // EasyExcel.read(file.getInputStream(), BigTreeImportCommand.class, new ExcelListener(urbanFacilityManageService)).sheet().doRead();
  10. /** 在service实现类处理 */
  11. Boolean flag = treeService.importTree(file, tenantId);
  12. return R.ok("导入成功");
  13. }

2.3业务处理

  1. @Override
  2. public Boolean importTree(MultipartFile file) {
  3. try {
  4. /** 处理数据的监听器,有参构造,根据自己的业务决定 */
  5. TreeExcelListener excelListener = new TreeExcelListener(importService,tenantId);
  6. // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
  7. //EasyExcel.read(文件流,对应的Model实体类,监听器).sheet(那张sheet表,可以使用下标或者使用sheet名字).head(表头对应的实体类).headRowNumber(表头占几行).registerReadListener(处理数据的监听器类).doRead()
  8. EasyExcel.read(file.getInputStream(), ImportModel.class, excelListener).sheet(0).head(ImportModel.class).headRowNumber(1).doRead();
  9. return true;
  10. } catch (Exception e) {
  11. throw new RuntimeException(e);
  12. }
  13. }

2.4监听器处理数据

  1. import com.alibaba.excel.context.AnalysisContext;
  2. import com.alibaba.excel.event.AnalysisEventListener;
  3. import com.ieds.back.interfaces.sys.web.command.BigTreeImportModel;
  4. /**
  5. * @Author: ChenFB
  6. * @CreateTime: 2023-04-23 17:18
  7. * @Description: 导入监听器
  8. */
  9. public class ImportListener extends AnalysisEventListener<BigTreeImportModel> {
  10. private ImportService importService;
  11. private String tenantId;
  12. /** 有参构造,建议将serverjie接口以参数的方式参进来,方便数据入库处理,这个参数自行界定 */
  13. public ImportListener(ImportService importService, String tenantId) {
  14. this.importService = importService;
  15. this.tenantId = tenantId;
  16. }
  17. /** 读取每一行数据都会进入该方法,数据处理与校验可以在该方法进行处理 */
  18. @Override
  19. public void invoke(BigTreeImportModel data, AnalysisContext context) {
  20. }
  21. /** 所有数据读取完毕后,最终会执行这个方法,所以建议数据处理完后,批量在该方法进行入库处理 */
  22. @Override
  23. public void doAfterAllAnalysed(AnalysisContext context) {
  24. }
  25. }

3.导出

3.1创建导出格式生成对应的excel表格的实体类,这个可以看2.1

3.2后端接收请求入口

  1. /**
  2. * 导出
  3. */
  4. @ApiOperation("导出")
  5. @GetMapping("/exportTree")
  6. public void exportTree(HttpServletResponse response, @RequestParam("tenantId") String tenantId) {
  7. treeService.exportTree(response,tenantId);
  8. }

3.3业务处理

  1. @Override
  2. public void exportTree(HttpServletResponse response, String tenantId) {
  3. ExcelWriter writer = null;
  4. try {
  5. response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); //设置响应内容类型
  6. response.setCharacterEncoding("utf-8");//编码
  7. // 设置文件名, ps:把字符串中所有的'+'替换成'%20',在URL中%20代表空格
  8. String fileName = URLEncoder.encode("文件名,根据业务决定", "UTF-8").replaceAll("\\+", "%20");
  9. response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");//设置响应头
  10. response.setHeader("fileName", fileName + ".xlsx");//设置响应头
  11. /** 导出的数据集合 */
  12. List<ExportModel> modelList = new ArrayList<>();
  13. /** registerWriteHandler(合并行数,那些列需要合并) */
  14. writer = EasyExcel.write(response.getOutputStream(), BigTreeImportModel.class).registerWriteHandler(new MergeStrategy(modelList.size(), 0, 1, 2, 7, 8, 10, 11)).build();//获取写出流
  15. WriteSheet sheet = EasyExcel.writerSheet("sheet名称,自行决定").build();//创建表格,设置表格页名称
  16. writer.write(modelList, sheet);//读出
  17. } catch (Exception e) {
  18. throw new RuntimeException(e);
  19. } finally {
  20. if (null != writer) {
  21. writer.finish();//关闭流
  22. }
  23. }
  24. }

4.合并工具类

  1. import com.alibaba.excel.metadata.Head;
  2. import com.alibaba.excel.write.merge.AbstractMergeStrategy;
  3. import org.apache.commons.collections.map.HashedMap;
  4. import org.apache.poi.ss.usermodel.Cell;
  5. import org.apache.poi.ss.usermodel.Sheet;
  6. import org.apache.poi.ss.util.CellRangeAddress;
  7. import java.util.*;
  8. /**
  9. * @Author: ChenFB
  10. * @CreateTime: 2023-04-20 10:56
  11. * @Description: Excel单元格合并工具类
  12. */
  13. public class MergeStrategy extends AbstractMergeStrategy {
  14. // 合并的列编号,从0开始,指定的index或自己按字段顺序数
  15. private Set<Integer> mergeCellIndex = new HashSet<>();
  16. // 数据集大小,用于区别结束行位置
  17. private Integer maxRow = 0;
  18. // 禁止无参声明
  19. private MergeStrategy() {
  20. }
  21. public MergeStrategy(Integer maxRow, int... mergeCellIndex) {
  22. Arrays.stream(mergeCellIndex).forEach(item -> {
  23. this.mergeCellIndex.add(item);
  24. });
  25. this.maxRow = maxRow;
  26. }
  27. // 记录上一次合并的信息
  28. private Map<Integer, MergeRange> lastRow = new HashedMap();
  29. // 每行每列都会进入,绝对不要在这写循环
  30. @Override
  31. protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
  32. int currentCellIndex = cell.getColumnIndex();
  33. // 判断该行是否需要合并
  34. if (mergeCellIndex.contains(currentCellIndex)) {
  35. String currentCellValue = cell.getStringCellValue();
  36. int currentRowIndex = cell.getRowIndex();
  37. if (!lastRow.containsKey(currentCellIndex)) {
  38. // 记录首行起始位置
  39. lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
  40. return;
  41. }
  42. //有上行这列的值了,拿来对比.
  43. MergeRange mergeRange = lastRow.get(currentCellIndex);
  44. if (!(mergeRange.lastValue != null && mergeRange.lastValue.equals(currentCellValue))) {
  45. // 结束的位置触发下合并.
  46. // 同行同列不能合并,会抛异常
  47. if (mergeRange.startRow != mergeRange.endRow || mergeRange.startCell != mergeRange.endCell) {
  48. sheet.addMergedRegionUnsafe(new CellRangeAddress(mergeRange.startRow, mergeRange.endRow, mergeRange.startCell, mergeRange.endCell));
  49. }
  50. // 更新当前列起始位置
  51. lastRow.put(currentCellIndex, new MergeRange(currentCellValue, currentRowIndex, currentRowIndex, currentCellIndex, currentCellIndex));
  52. }
  53. // 合并行 + 1
  54. mergeRange.endRow += 1;
  55. // 结束的位置触发下最后一次没完成的合并
  56. if (relativeRowIndex.equals(maxRow - 1)) {
  57. MergeRange lastMergeRange = lastRow.get(currentCellIndex);
  58. // 同行同列不能合并,会抛异常
  59. if (lastMergeRange.startRow != lastMergeRange.endRow || lastMergeRange.startCell != lastMergeRange.endCell) {
  60. sheet.addMergedRegionUnsafe(new CellRangeAddress(lastMergeRange.startRow-1, lastMergeRange.endRow, lastMergeRange.startCell, lastMergeRange.endCell));
  61. }
  62. }
  63. }
  64. }
  65. }
  66. class MergeRange {
  67. public int startRow;
  68. public int endRow;
  69. public int startCell;
  70. public int endCell;
  71. public String lastValue;
  72. public MergeRange(String lastValue, int startRow, int endRow, int startCell, int endCell) {
  73. this.startRow = startRow;
  74. this.endRow = endRow;
  75. this.startCell = startCell;
  76. this.endCell = endCell;
  77. this.lastValue = lastValue;
  78. }
  79. }

总结

以上就是使用EasyExcel时限导入与导出功能的实现步骤,鄙人才疏学浅,本文章仅供参考,有不对之处,还望各位大佬提醒与指教.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/528781
推荐阅读
相关标签
  

闽ICP备14008679号