VUE项目中使用EasyExcel下载复杂表格


前言

目前刚做完一个VUE的项目,前台菜单中有一个下载统计报表的功能,该表的结构比较复杂,没有采用传统的导出表头的那种方式,而是自己定义了一套表格模板,通过EasyExcel的方式去填充内容;现在项目已经上线,抽空在此记录一下实现过程,以后有类似的功能可以作为参考。


一、定义要下载的表格模板

业务需求提供的表格模板:
在这里插入图片描述

技术定义完字段后的表格模板:

二、代码实现

1.控制类

1.查询会商诊断表全部字段信息,这一步就是从数据库中遍历出所需要的字段值;
2.数据字典转码,这一步根据自身需要来定,我这里是从数据库查询到的值是code值,需要转成中文展示才进行转码;
3.把会商诊断表组装成Map,这一步基本上是需要的,因为表格模板中的定义字段是Map类型的,所以需要封装一下,不过这一步也可以直接在步骤1中实现,看个人选择了。
代码如下(示例):

package com.icbc.tech.ccrm.custlib.primary.controller;

import com.icbc.tech.ccrm.common.auth.utils.ExcelUtils;
import com.icbc.tech.ccrm.common.util.ExcelExportUtils;
import com.icbc.tech.ccrm.custlib.primary.entity.dto.CustlibPrimaryConDiaOutDTO;
import com.icbc.tech.ccrm.custlib.primary.entity.dto.CustlibPrimaryConDiaVO;
import com.icbc.tech.ccrm.custlib.primary.service.ICrmCCustlibPrimaryService;
import com.icbc.tech.ccrm.system.scommoncode.service.ICrmSCommonCodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 会商诊断表导出控制器
 * @Date 2022/9/23
 */
@RestController
@Slf4j
@Validated
@RequestMapping("/c/primary/consultation-diagnosis")
public class CrmCCustlibPrimaryConDiaController {

    @Autowired
    private ICrmCCustlibPrimaryService iCrmCCustlibPrimaryService;
    @Autowired
    private ExcelUtils excelUtils;
    @Autowired
    private ExcelExportUtils excelExportUtils;

    @GetMapping("/download/v1")
    public void downloadOperational(@Valid CustlibPrimaryConDiaVO custlibPrimaryConDiaVO, HttpServletResponse response) throws IOException {
        try {
            List<CustlibPrimaryConDiaOutDTO> dictList1 = new ArrayList<>();
            List<CustlibPrimaryConDiaOutDTO> dictList2 = new ArrayList<>();
            //查询会商诊断表全部字段信息
            CustlibPrimaryConDiaOutDTO custlibPrimaryConDiaOutDTO = iCrmCCustlibPrimaryService.findPrimaryConDiaInfo(custlibPrimaryConDiaVO);
            dictList1.add(custlibPrimaryConDiaOutDTO);
            //数据字典转码
            dictList2 = excelExportUtils.convertDictCode(dictList1, CustlibPrimaryConDiaOutDTO.class, ICrmSCommonCodeService.class);
            custlibPrimaryConDiaOutDTO = dictList2.get(0);
            //把会商诊断表组装成Map
            HashMap<String, Object> map = iCrmCCustlibPrimaryService.createConDiaInfoMap(custlibPrimaryConDiaOutDTO);
            //excel模板路径
            InputStream templateFileName = this.getClass().getClassLoader().getResourceAsStream("template/consultationDiagnosis.xlsx");
            //调用Excel工具类导出功能
            excelUtils.exportExcel(response, map, "ConDiaExcel", templateFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

2.Excel工具类导出

在网上找到的Excel Util工具类跟我的情况有点区别,所以自己写了一个工具类,这里可以适当参考;另外如果对表格的字体或者格式有特殊要求可以在前端处理,比如给导出的表格命名。
代码如下(示例):

package com.icbc.tech.ccrm.common.auth.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * Excel工具类,用于导出复杂xlsx文件
 * 2022-9-22
 */
@Component
@Scope("prototype")
@Slf4j
public class ExcelUtils {

    /**
     * 导出复杂表头的Excel
     * @param response
     * @param map 单组数据Map
     * @param outFileName 导出的Excel名称
     * @param templateFileName Excel模板的路径名称
     * @throws Exception
     */

    public static void exportExcel(HttpServletResponse response, Map<String,Object> map,
                                   String outFileName, InputStream templateFileName ) throws Exception{



        //告诉response下载的是excel文件
        response.setContentType("application/vnd.ms-excel");

        //告诉response使用utf-8编码格式
        response.setCharacterEncoding("utf-8");

        //.withTemplate(templateFileName)就是读取模板
        //.write(ExcelUtil.getOutputStream(outFileName, response))是将数据写入文件,并交给response
        ExcelWriter excelWriter = EasyExcel.write(ExcelUtils.getOutputStream(outFileName, response)).withTemplate(templateFileName).build();

        //创建Sheet
        //设置excel Sheet为第几张并设置名称
        //.writerSheet(0,"第一个")中前面的参数为sheetNo,就是第几张sheet
        //第二参数为sheet名称
        //不写就是默认
        WriteSheet writeSheet  = EasyExcel.writerSheet().build();

        //这里是将一些普通数据放到map中,方便填入,可以看getStringObjectMap()。
        //map的String是对应的名称,Object就是数据了。
        //将数据填入
        excelWriter.fill(map, writeSheet);

        //关闭
        excelWriter.finish();
    }
    /**
     * 这是ExcelUtil.getOutputStream
     * 这里就是将文件下载交给了浏览器
     * @return
     */
    public static OutputStream getOutputStream(String Name, HttpServletResponse response) throws Exception {
        //这里是对文件的重命名
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
        String date = sdf.format(new Date());
        String fileName = new String(Name.getBytes(), StandardCharsets.UTF_8.toString()) + date + ".xlsx";
        // 这里文件名如果涉及中文一定要使用URL编码,否则会乱码
        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        return response.getOutputStream();
    }

}

3.实现效果

后端从数据库查询到的结果经过封装和Excel Util类的处理后,导出的表格即可实现内容的填充,我的测试结果如下:
在这里插入图片描述


总结

前端的代码比较简单,不用过多展示了,后端的实现类也是基本的代码编写,上面的实现难点在于数据库查询,由于我的项目涉及到的字段较多,关联的表和遇到值多对一的情况,最终写了几百行的查询语句,当然这些都是跟项目相关的东西,最重要的是参考实现思路。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以按照以下步骤使用 Vue、Spring Boot 和 EasyExcel 把 Excel 表格导入数据库: 1. 创建一个 Vue 页面,使用 Element UI 的 Upload 组件上传 Excel 文件,并在上传成功后调用后端接口。 2. 在 Spring Boot 后端使用 EasyExcel 将上传的 Excel 文件转换为 Java 对象。 3. 将 Java 对象保存到数据库,可以使用 Spring Data JPA 或 Mybatis 等框架进行操作。 下面是一个示例代码: Vue 页面代码: ```html <template> <div> <el-upload class="upload-demo" ref="upload" :action="uploadUrl" :on-success="handleUploadSuccess" :file-list="fileList" :auto-upload="false" > <el-button slot="trigger" size="small" type="primary">选取文件</el-button> <el-button size="small" type="success" @click="submitUpload">上传到服务器</el-button> <div slot="tip" class="el-upload__tip">只能上传 xlsx 文件</div> </el-upload> </div> </template> <script> import axios from 'axios'; export default { data() { return { fileList: [], uploadUrl: '/api/upload', }; }, methods: { handleUploadSuccess(response) { this.fileList.push(response.data.file); }, submitUpload() { const formData = new FormData(); formData.append('file', this.fileList[0].raw); axios.post(this.uploadUrl, formData, { headers: { 'Content-Type': 'multipart/form-data', }, }).then(() => { this.$message.success('上传成功'); }); }, }, }; </script> ``` Spring Boot 后端代码: ```java @RestController @RequestMapping("/api") public class UploadController { @PostMapping("/upload") public void upload(@RequestParam("file") MultipartFile file) { try { List<DemoData> dataList = EasyExcel.read(file.getInputStream()).head(DemoData.class).sheet().doReadSync(); // 保存 dataList 到数据库 } catch (IOException e) { e.printStackTrace(); } } } ``` 其,DemoData 是要导入的 Excel 表格的实体类,可以使用 @ExcelProperty 注解标注表格的每一列对应的属性。需要注意的是,在使用 EasyExcel 进行读取时,Excel 表格的第一行会被默认为表头,因此需要在读取表格时指定表头对应的实体类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值