实现Excel的导入、导出

实现Excel的导入、导出

关于excel的操作在工作中经常会遇到,如果只是一次性使用的话,最简单的方式就是通过数据库的可视化工具(如Navicat)查询结果集之后直接一键生成excel了,当然这只能解燃眉之急,并不是长久之计。
首先Excel的导出是比导入简单的,在应用中导出也导出应用的多,导出主要分为前端导出和后端导出。

1. 通过前端方式导出Excel

前提读者你的前端项目是VUE的如果不是可以看第二个

  • .安装依赖
npm install -S file-saver
npm install -S xlsx
npm install -D script-loader
  • 导入Blob.js和Export2Excel.js文件
    相当于我们要用的工具类了。
    下载地址(https://pan.baidu.com/s/1mmzFl9U0jtQvBK0AjL0urg?pwd=83yc),提取码:83yc
    ( 笔者已经优化过Export2Excel.js了,之前其他地方下载存在过多列导致报错的问题,这里已经无需考虑了,直接拿来用就好)
  • 使用方式
    将上面所说的js必须放到同一目录下
    在这里插入图片描述

引入我们的工具类

import { export_json_to_excel2 } from "@/utils/Export2Excel";

在method里面添加两个方法

exportExcel() {
      require.ensure([], () => {
        const row = Object.keys(this.tableData[0]).sort().slice(0, -3);
        const rowc = [].concat(row);
        row.unshift("序号", "项目号码", "项目名称", "姓名");
        rowc.unshift("index", "projectCode", "projectName", "userName");
        const header = row;
        // 上面设置Excel的表格第一行的标题
        const filterVal = rowc;
        const list = this.tableData; //把data里的tableData存到list
        for (let i = 0; i < list.length; i++) {
          list[i]["index"] = i + 1;
        }
        var header2 = [
          "序号",
          "项目号码",
          "项目名称",
          "姓名",
          "项目工作量(原始工作量,人时)每人每天不超过7.5小时",
        ];
        for (let j = 0; j < row.length; j++) {
          header2.push("");
        }
        const multiHeader = [header2]; // 前一行的表头数据,二维数组,不够的用空白补全
        const data = this.formatJson(filterVal, list);
        const merges = ["A1:A2", "B1:B2", "C1:C2", "D1:D2", "E1:Q1"]; // 合并单元格的数据,如何合并参考上面图片讲解
        export_json_to_excel2({
          multiHeader,
          header,
          merges,
          data,
          filename: "工作量核算表",
        });
      });
    },
    formatJson(filterVal, jsonData) {
      return jsonData.map((v) => filterVal.map((j) => v[j]));
    },

准备我们的data数据(这只是笔者提供的例子,可以根据自己的需要去改变)

  tableData: [
        {"2021-09": 0,"2021-10": 75,"2021-11": 7.5,projectCode: "123",projectName: "测试1",userName: "小红",},
        {"2021-09": 24.5,"2021-10": 62.5,"2021-11": 10.5,projectCode: "123",projectName: "测试1",userName: "小丽",},
      ], 

调用我们的方法

//`方法:数据导出`
    download() {
      this.exportExcel();
    },
  • 实现效果
    在这里插入图片描述

2. 通过后端方式导出Excel

为什么会有前端导出和后端导出呢?其实现在的系统很多都是前后端分离的,前端的人无需接触后台也能开发出一个导出功能(笔者是这么想的),后端导出其实就是POI,也是工作中用的比较多的,相对于前端导出,后端导出的安全性要高,处理的效率也比较高,能应用的场景更多,前提你得对POI有一定的了解。

1.引入pom(注:部分功能会因为poi的版本不同而有差异。)

  <!-- poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>

2.实现代码

    @SuppressWarnings("resource")
    @RequestMapping("/exportWorkloads")
    public void exportWorkloads(HttpServletResponse response) throws Exception {

        String[] tableHeaders = {"姓名", "工作日期", "工作小时数", "财务小时数", "工作内容"};

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("Sheet1");
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        Font font = workbook.createFont();
        font.setBold(true);
        cellStyle.setFont(font);

        // 将第一行的五个单元格给合并
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 4));
        HSSFRow row = sheet.createRow(0);
        HSSFCell beginCell = row.createCell(0);
        //第一行的表头
        String title = "测试测试";
        beginCell.setCellValue(title);
        beginCell.setCellStyle(cellStyle);

        row = sheet.createRow(1);
        // 创建第二行的表头
        for (int i = 0; i < tableHeaders.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(tableHeaders[i]);
            cell.setCellStyle(cellStyle);
        }
        //导出的表格数据
        ArrayList<Map> maps = new ArrayList<>();
        for (int i = 1; i < 4; i++) {
            HashMap<String, String> map = new HashMap<>();
            map.put("姓名","马云"+i);
            map.put("工作日期","2022-07-0"+i);
            map.put("工作小时数",String.valueOf(i));
            map.put("财务小时数",String.valueOf(i));
            map.put("工作内容","我是第"+i+"天的工作内容");
            maps.add(map);
        }
        for (int i = 0, j = maps.size(); i < j; i++) {
            //填充数据
            row = sheet.createRow(i + 2);
            Map<String,String> map = maps.get(i);
            row.createCell(0).setCellValue(map.get("姓名"));
            row.createCell(1).setCellValue(map.get("工作日期"));
            row.createCell(2).setCellValue(map.get("工作小时数"));
            row.createCell(3).setCellValue(map.get("财务小时数"));
            row.createCell(4).setCellValue(map.get("工作内容"));
        }
        OutputStream outputStream = response.getOutputStream();
        response.reset();
        response.setContentType("application/vnd.ms-excel");
        String filename = "我是导出的文件名";
        //文件名要进行编码转换,默认是UTF8可能会显示异常
        String basename = new String(filename.getBytes("gb2312"), "ISO8859-1");
        response.setHeader("Content-disposition", "attachment;filename=" + basename + ".xls");
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

3.实现效果
在这里插入图片描述

3. 导入Excel

导入Excel可以理解为从Excel读出数据,笔者使用的工具类来自于与Hutool,后端开发的应该都知道,这是功能强大的工具类了。
1.引入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.3</version>
</dependency>

2.准备我们的视图数据
在这里插入图片描述
3.前端上传文件
在这里插入图片描述

附上关键代码(使用什么组件都可以,笔者使用原生的input)

//组件
<input type="file" ref="feedbakcfile" @change="getFile($event)" />

//method
getFile(event) {
    this.file = event.target.files[0];
},
//提交方法
 exportUp() {
      if (!this.file) {
           this.notifyError("请选择文件上传");
            return;
        }
        let formData = new FormData();
        formData.append("file", this.file);
        //根据你使用的技术写ajax,这里要注意header!
        request({
           url: "/eip/excel/read",
           method: "post",
           data: formData,
           header: { "Content-Type": "multipart/form-data" },
         })
          .then((r) => {
             if (r.success) {
                this.notifySuccess("导入成功");
              } else {
                this.$message.error(r.message);
              }
            })
            .catch((e) => {
              this.notifyError((e || {}).message || "导入失败");
            });
     },

4.代码片段

  /**
     * 导入
     *
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/read")
    @ResponseBody
    public Map<String, Object> read(MultipartFile file) throws Exception {
        Map<String, Object> result = new HashMap<>();
        //首先判断是不是空的文件
        if (!file.isEmpty()) {
            //对文文件的全名进行截取然后在后缀名进行删选。
            int begin = file.getOriginalFilename().indexOf(".");
            int last = file.getOriginalFilename().length();
            //获得文件后缀名
            String a = file.getOriginalFilename().substring(begin, last);
            if (!(a.endsWith(".xlsx") || a.endsWith(".xls"))) {
                result.put("success",false);
                result.put("message","文件类型只能为xlsx、xls!");
                return result;
            }
        } else {
            result.put("success",false);
            result.put("message","文件不能为空!");
            return result;
        }
        byte[] byteArr = file.getBytes();
        InputStream inputStream = new ByteArrayInputStream(byteArr);
        ExcelReader reader = ExcelUtil.getReader(inputStream, true);
        //从第3行读起,第一行默认是0
        List<List<Object>> lists = reader.read(2);
        if (lists.size() == 0) {
            result.put("success",false);
            result.put("message","数据为空。");
            return result;
        }
        //目标数据
        List<Map> maps = new ArrayList<>();
        for (int i = 0, j = lists.size(); i < j; i++) {
            List<Object> data = lists.get(i);
            HashMap<String, String> map = new HashMap<>();
            String date = ((DateTime) data.get(0)).toString("yyyy-MM-dd");
            String name = data.get(1).toString();
            String plan = data.get(2).toString();
            String planTask = data.get(3).toString();
            map.put("date",date);
            map.put("name",name);
            map.put("plan",plan);
            map.put("planTask",planTask);
            maps.add(map);
        }
        //可以打印看看maps是不是你想要的数据
        result.put("success",true);
        return result;
   }
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值