前后端分离下EasyExcel的使用

  金牌会员 | 2023-3-17 14:35:57 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 994|帖子 994|积分 2982

前后端分离下EasyExcel的使用

项目环境:SpringBoot+Vue
依赖导入
  1. <dependency>
  2.     <groupId>com.alibaba</groupId>
  3.     <artifactId>easyexcel</artifactId>
  4.     <version>3.0.2</version>
  5. </dependency>
复制代码
tips
3.0.1版本 @ColumnWidth失效问题 用其他版本即可
实体类关联Excel

@ExcelProperty:value属性可用来设置表头名称
@ExcelPropertyvalue属性可用来设置表头名称
点击查看代码
  1. @TableName(value = "five_insurances")
  2. @Data
  3. public class FiveInsurances implements Serializable {
  4.     /**
  5.      *
  6.      */
  7.     @ExcelProperty("编号")
  8.     @ColumnWidth(10)
  9.     @TableId(value = "id", type = IdType.AUTO)
  10.     private Integer id;
  11.     /**
  12.      * 工号
  13.      */
  14.     @ExcelProperty("工号")
  15.     @ColumnWidth(15)
  16.     @TableField(value = "number")
  17.     private String number;
  18.     /**
  19.      * 姓名
  20.      */
  21.     @ExcelProperty("姓名")
  22.     @ColumnWidth(20)
  23.     @TableField(value = "name")
  24.     private String name;
  25.     /**
  26.      * 部门id
  27.      */
  28.     @ExcelProperty("部门")
  29.     @ColumnWidth(20)
  30.     @TableField(value = "dept_id")
  31.     private Integer deptId;
  32.     /**
  33.      * 电话
  34.      */
  35.     @ExcelProperty("电话")
  36.     @ColumnWidth(20)
  37.     @TableField(value = "phone")
  38.     private String phone;
  39.     /**
  40.      * 缴纳基数
  41.      */
  42.     @ExcelProperty({"社保", "缴纳基数"})
  43.     @ColumnWidth(20)
  44.     @TableField(value = "base_payment")
  45.     private String basePayment;
  46.     /**
  47.      * 个人缴纳
  48.      */
  49.     @ExcelProperty({"社保", "个人", "缴纳费用"})
  50.     @ColumnWidth(20)
  51.     @TableField(value = "self_payment")
  52.     private String selfPayment;
  53.     /**
  54.      * 工伤保险缴纳比例
  55.      */
  56.     @ExcelProperty({"社保", "企业", "工伤保险缴纳比例"})
  57.     @ColumnWidth(20)
  58.     @TableField(value = "ratio")
  59.     private String ratio;
  60.     /**
  61.      * 企业缴纳
  62.      */
  63.     @ExcelProperty({"社保", "企业", "缴纳费用"})
  64.     @ColumnWidth(20)
  65.     @TableField(value = "com_payment")
  66.     private String comPayment;
  67.     /**
  68.      * 备注
  69.      */
  70.     @ExcelProperty({"社保", "备注"})
  71.     @ColumnWidth(30)
  72.     @TableField(value = "remarks")
  73.     private String remarks;
  74.     @ExcelIgnore
  75.     @TableField(exist = false)
  76.     private Dept dept;
  77.     @ExcelIgnore
  78.     @TableField(exist = false)
  79.     private static final long serialVersionUID = 1L;
  80. }
复制代码
导出Excel

Controller
  1. @GetMapping("/fihf")
  2. @ApiOperation(value = "导出五险一金列表Excel")
  3. @ApiImplicitParams(
  4.             @ApiImplicitParam(dataType = "Interger",name = "page",value = "page==-1:查询所有;page==-2,返回空模板",required = false)
  5.     )
  6. public void exportList(HttpServletResponse response, @RequestParam(value = "page", defaultValue = "1") Integer page) throws Exception {
  7.         PageBean<List<FiveInsurances>> pageBean = fiveInsurancesService.selectFiveInsurancesList(page);
  8.         ExcelUtils.exportToWeb(response,"sheet1",FiveInsurances.class,pageBean.getData());
  9.     }
复制代码
前端Axios请求
  1. exportFile(page = this.pageBean.current) {
  2.     //复选框选中则设置page为-1,表示导出全部
  3.     if (this.checked) {
  4.         page = -1;
  5.     }
  6.     //关闭对话框
  7.     this.dialogVisible = false;
  8.     this.axios({
  9.         method: 'get',
  10.         url: baseURL + "fileExport/fihf",
  11.         params: {
  12.             page: page,
  13.         },
  14.         responseType: 'blob' //响应类型须设置为二进制文件流
  15.     }).then((res) => {
  16.         if (!res) {
  17.             return
  18.         }
  19.         const link = document.createElement("a");//创建a标签
  20.         let blob = new Blob([res.data], { type: "multipart/form-data" }); //设置文件类型
  21.         link.style.display = "none";
  22.         let url = URL.createObjectURL(blob);
  23.         link.href = url; //给a标签href属性赋值
  24.         link.setAttribute("download", decodeURI(Date.now() + '.xlsx'));
  25.         document.body.appendChild(link);//挂载a标签
  26.         link.click();//a标签click事件
  27.         document.body.removeChild(link); //移除a标签
  28.         window.URL.revokeObjectURL(url); //销毁下载链接
  29.         console.log(res);
  30.         this.checked = false;
  31.         return this.$message.success("导出报表数据成功!")
  32.     })
  33. },
复制代码
导入Excel

Controller
  1. @PostMapping("/fihf")
  2. @ApiOperation(value = "导入五险一金列表Excel")
  3. public ResultVO<FiveInsurances> FiveInsurances(@RequestPart("file") MultipartFile file) throws IOException {
  4.     if (file.getSize() < 0) {
  5.         return ResultVO.createFail(404, "导入数据失败");
  6.     }
  7.     List<FiveInsurances> list = ExcelUtils.importFile(file, FiveInsurances.class);
  8.     //持久化到数据库
  9.     int i = fiveInsurancesService.insertBatch(list);
  10.     if (i > 0) {
  11.         return ResultVO.createSuccess("读取excel成功", null);
  12.     } else {
  13.         return ResultVO.createFail();
  14.     }
  15. }
复制代码
前端Axios请求
  1. handleBeforUpload(file) {
  2.     console.log("beforeUpload", file);
  3.     //创建文件附件
  4.     let formData = new FormData();
  5.     //添加到formdata
  6.     formData.append("file", file);
  7.     this.axios({
  8.         method: 'post',
  9.         url: baseURL + "fileImport/fihf",
  10.         data: formData,
  11.         Headers: {
  12.             "Content-Type": "multipart/form-data",
  13.         }
  14.     }).then((res) => {
  15.         console.log("读取excel", res);
  16.         if (res.data.data == 10000) {
  17.             this.$message.success(res.data.msg)
  18.         }
  19.     })
  20. },
复制代码
Excel导入导出工具类

点击查看代码
  1. package com.self.salarymanagement.utils;
  2. import com.alibaba.excel.EasyExcel;
  3. import com.alibaba.excel.support.ExcelTypeEnum;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.poi.util.IOUtils;
  6. import org.springframework.web.multipart.MultipartFile;
  7. import javax.servlet.ServletOutputStream;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.File;
  10. import java.io.FileInputStream;
  11. import java.io.IOException;
  12. import java.io.UnsupportedEncodingException;
  13. import java.net.URLEncoder;
  14. import java.util.List;
  15. /**
  16. * Excel工具类
  17. */
  18. @Slf4j
  19. public class ExcelUtils {
  20.     /**
  21.      * 导出Excel到指定路径下
  22.      *
  23.      * @param path      路径
  24.      * @param excelName Excel名称
  25.      * @param sheetName sheet页名称
  26.      * @param clazz     Excel要转换的类型
  27.      * @param data      要导出的数据
  28.      */
  29.     public static void exportFileToLocal(String path, String excelName, String sheetName, Class clazz, List data) {
  30.         String fileName = path.concat(excelName).concat(ExcelTypeEnum.XLSX.getValue());
  31.         EasyExcel.write(fileName, clazz).sheet(sheetName).doWrite(data);
  32.     }
  33.     /**
  34.      * 导出Excel到web
  35.      *
  36.      * @param response  响应
  37.      * @param sheetName sheet页名称
  38.      * @param clazz     Excel要转换的类型
  39.      * @param data      要导出的数据
  40.      * @throws Exception
  41.      */
  42.     public static void exportToWeb(HttpServletResponse response, String sheetName, Class clazz, List data) throws Exception {
  43. //        response.setContentType("application/vnd.ms-excel");
  44.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  45.         response.setCharacterEncoding("utf-8");
  46.         // 这里URLEncoder .encode可以防止中文乱码
  47.         String excelName = URLEncoder.encode(String.valueOf(System.currentTimeMillis()), "UTF-8");
  48.         response.setHeader("Content-disposition", "attachment;filename=" + excelName + ExcelTypeEnum.XLSX.getValue());
  49.         EasyExcel.write(response.getOutputStream(), clazz).excelType(ExcelTypeEnum.XLSX).sheet(sheetName).doWrite(data);
  50.     }
  51.     /**
  52.      * 导出Excel到web
  53.      *
  54.      * @param response  响应
  55.      * @param excelName Excel名称
  56.      * @param sheetName sheet页名称
  57.      * @param clazz     Excel要转换的类型
  58.      * @param data      要导出的数据
  59.      * @throws Exception
  60.      */
  61.     public static void exportToWeb(HttpServletResponse response, String excelName, String sheetName, Class clazz, List data) throws Exception {
  62. //        response.setContentType("application/vnd.ms-excel");
  63.         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  64.         response.setCharacterEncoding("utf-8");
  65.         // 这里URLEncoder.encode可以防止中文乱码
  66.         excelName = URLEncoder.encode(excelName, "UTF-8");
  67.         response.setHeader("Content-disposition", "attachment;filename=" + excelName + ExcelTypeEnum.XLSX.getValue());
  68.         EasyExcel.write(response.getOutputStream(), clazz).sheet(sheetName).doWrite(data);
  69.     }
  70.     /**
  71.      * 将指定位置指定名称的Excel导出到web
  72.      *
  73.      * @param response  响应
  74.      * @param path      文件路径
  75.      * @param excelName 文件名称
  76.      * @throws UnsupportedEncodingException
  77.      */
  78.     public static String export2Web4File(HttpServletResponse response, String path, String excelName) throws UnsupportedEncodingException {
  79.         File file = new File(path.concat(excelName).concat(ExcelTypeEnum.XLSX.getValue()));
  80.         if (!file.exists()) {
  81.             return "文件不存在!";
  82.         }
  83.         response.setContentType("application/vnd.ms-excel");
  84.         response.setCharacterEncoding("utf-8");
  85.         // 这里URLEncoder.encode可以防止中文乱码
  86.         excelName = URLEncoder.encode(excelName, "UTF-8");
  87.         response.setHeader("Content-disposition", "attachment;filename=" + excelName + ExcelTypeEnum.XLSX.getValue());
  88.         try (
  89.                 FileInputStream in = new FileInputStream(file);
  90.                 ServletOutputStream out = response.getOutputStream();
  91.         ) {
  92.             IOUtils.copy(in, out);
  93.             return "导出成功!";
  94.         } catch (Exception e) {
  95.             log.error("导出文件异常:", e);
  96.         }
  97.         return "导出失败!";
  98.     }
  99.     public static <T> List<T> importFile(MultipartFile file, Class<T> clazz) throws IOException {
  100.         return EasyExcel.read(file.getInputStream())
  101.                 .head(clazz)
  102.                 .registerReadListener(new DefaultExcelListener<T>())
  103.                 .sheet()
  104.                 .doReadSync();
  105.     }
  106. }
复制代码
Excel导入监听器
  1. import com.alibaba.excel.context.AnalysisContext;
  2. import com.alibaba.excel.event.AnalysisEventListener;
  3. import com.alibaba.excel.exception.ExcelDataConvertException;
  4. import lombok.extern.slf4j.Slf4j;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. /**
  8. * @author Liu
  9. * @create 2023-03-08-11:44
  10. * @description:
  11. */
  12. @Slf4j
  13. public class DefaultExcelListener<T> extends AnalysisEventListener<T> {
  14.     private final List<T> rows = new ArrayList<>();
  15.     /**
  16.      * 读取excel操作
  17.      *
  18.      * @param obj             数据
  19.      * @param analysisContext 上下文
  20.      */
  21.     // 每读一样,会调用该invoke方法一次
  22.     @Override
  23.     public void invoke(T obj, AnalysisContext analysisContext) {
  24.         //添加到list
  25.         rows.add(obj);
  26.         log.info("list容量" + rows.size() + obj);
  27.         /** 数据量不是特别大,可以不需要打开
  28.          // 实际数据量比较大时,rows里的数据可以存到一定量之后进行批量处理(比如存到数据库),
  29.          // 然后清空列表,以防止内存占用过多造成OOM
  30.          if(rows.size() >= 500){
  31.          log.info("存入数据库ing");
  32.          try {
  33.          Thread.sleep(3000);
  34.          } catch (InterruptedException e) {
  35.          e.printStackTrace();
  36.          }
  37.          rows.clear();
  38.          }
  39.          */
  40.     }
  41.     /**
  42.      * 读取玩excel后的操作
  43.      */
  44.     @Override
  45.     public void doAfterAllAnalysed(AnalysisContext analysisContext) {
  46.         log.info("成功读取【" + rows.size() + "】条数据");
  47.         System.out.println("================================");
  48.         rows.forEach(System.out::println);
  49.         System.out.println("================================");
  50.     }
  51.     /**
  52.      * 在读取excel异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
  53.      */
  54.     @Override
  55.     public void onException(Exception exception, AnalysisContext context) {
  56.         log.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
  57.         if (exception instanceof ExcelDataConvertException) {
  58.             ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;
  59.             log.error("第{}行,第{}列解析异常,数据为:{}", excelDataConvertException.getRowIndex(),
  60.                     excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
  61.         }
  62.     }
  63.     /**
  64.      * @return 返回读取的总数据
  65.      */
  66.     public List<T> getRows() {
  67.         return rows;
  68.     }
  69. }
复制代码
多级表头设置

嵌套el-table-column即可
  1. <el-table-column label="社保" width="180">
  2.     <el-table-column label="缴纳基数" width="120">
  3.         <template slot-scope="scope">
  4.             {{ scope.row.basePayment }}
  5.         </template>
  6.     </el-table-column>
  7.     <el-table-column label="个人" width="120">
  8.         <el-table-column label="缴纳费用" width="120">
  9.             <template slot-scope="scope">
  10.                 {{ scope.row.selfPayment }}
  11.             </template>
  12.         </el-table-column>
  13.     </el-table-column>
  14.     <el-table-column label="企业" width="180">
  15.         <el-table-column label="工伤保险缴纳比例" width="180">
  16.             <template slot-scope="scope">
  17.                 {{ scope.row.ratio }}
  18.             </template>
  19.         </el-table-column>
  20.         <el-table-column label="缴纳费用" width="180">
  21.             <template slot-scope="scope">
  22.                 {{ scope.row.comPayment }}
  23.             </template>
  24.         </el-table-column>
  25.     </el-table-column>
  26.     <el-table-column label="备注" width="120">
  27.         <template slot-scope="scope">
  28.             {{ scope.row.remarks }}
  29.         </template>
  30.     </el-table-column>
  31. </el-table-column>
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表