Vue +springboot 导出excel

两种实现方式:1.后台返回json,前台通过xlsx解析,然后生成excel文件;2.后台返回文件流;

第一种方式:贴出前台代码,后台的就不需要了吧,就是很简单的json数据;

 //导出
      exportTable() {
        var jsono = [{
          "应用名字" : "appname",
          "关键字" : "keyword",
          
         
        }]
        var keyMap = []; 
        var valueMap = [];
        var list1 = []
        for (var k in jsono[0]) {
            keyMap.push(k)
            valueMap.push(jsono[0][k])
        }
        for (var i=0;i<this.dataList.length;i++) {      
            list1[i] = []
            
            for (var j in valueMap) {
              
                list1[i][keyMap[j]]= this.dataList[i][valueMap[j]]   
                     
            }          
        }
        var ws = xlsx.utils.json_to_sheet(list1);
        var wb = xlsx.utils.book_new();
        xlsx.utils.book_append_sheet(wb, ws, "People");//sheet名称
        let out = xlsx.write(wb, {
          bookType: "xlsx",
          bookSST: true,
          type: "array"
        });
        try {
          fileSaver.saveAs(
            new Blob([out], {
              type: "application/octet-stream"
            }),
            "列表.xlsx"
          );
        } catch (e) {
          // 错误处理方式
        }
        return out;
      },

第二种:同样,先贴出前台代码:

// 导出方法

exportTable(){
    this.$http({
        url: this.$http.adornUrl('/*/getExportData'),//获取文件流的接口路径
        method: 'post',
        data: {//请求参数
            "id":"12"
            },    
    responseType: 'blob' // 表明返回服务器返回的数据类型 很重要!!
    }).then((res) => {
        //将文件流转成blob形式
        const blob = new Blob([res.data],{type: 'application/vnd.ms-excel'});
        let filename ='1.xls';
        //创建一个超链接,将文件流赋进去,然后实现这个超链接的单击事件
        const elink = document.createElement('a');
        elink.download = filename;
        elink.style.display = 'none';
        elink.href = URL.createObjectURL(blob);
        document.body.appendChild(elink);
        elink.click();
        URL.revokeObjectURL(elink.href); // 释放URL 对象
        document.body.removeChild(elink);
    }).catch(error => {
        this.$message.error('导出失败');
        // console.log(error)

    })

},

后台代码我不想贴了,因为用的jxl的技术,很老,我就只贴出遇到的问题跟解决方式吧:
(1)第一个问题:前台不识别文件流

        responseType: 'blob' // 表明返回服务器返回的数据类型 很重要!!

    这个一定要加在请求头里面,否则识别不了文件流

(2)第二个问题:跨域

因为是前后端分离,IP跟端口肯定不一样,浏览器不接受这种跨域返回的文件流,所以需要在response的header里面加一条属性:

response.setHeader("Access-Control-Allow-Origin", "http://***:8001");//解决跨域

网上有很多说放个*就行,像这样:

response.setHeader("Access-Control-Allow-Origin", "*");//解决跨域

但是我这试了不行,所以就把前台的具体IP跟端口写进去了,反正是管用。

 

//费了很大功夫,把后台返回文件流的代码更新成poi方式了,然后我发现,后台jxl方式,需要解决跨域,而改成poi就不需要跨域了,很神奇,也没空去了解更多;先把后台代码记录一下:

public static void export(List<Map<String,Object>> list, LinkedHashMap<String, String> fieldMap,String filName,
                       HttpServletResponse response) throws IOException {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet(filName+"1");//新建sheet
        HSSFCellStyle contextstyle =wb.createCellStyle();
        HSSFRow row = null;
        int rowIndex = 0 ;
        row = sheet.createRow(0);
        row.setHeight((short) (22.50 * 20));//设置行高
        // 定义存放英文字段名和中文字段名的数组
        String[] enFields = new String[fieldMap.size()];
        String[] cnFields = new String[fieldMap.size()];
        // 填充数组
        int count = 0;
        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
            enFields[count] = entry.getKey();

            cnFields[count] = entry.getValue();
            count++;
        }
        //设置表头
        for(int i=0; i<cnFields.length;i++){
            row.createCell(i).setCellValue(cnFields[i]);
        }
        for (int i = 0; i < list.size(); i++) {
            if(rowIndex>65535 ){
                sheet = wb.createSheet(filName+"2");
                row = sheet.createRow(0);
                row.setHeight((short) (22.50 * 20));//设置行高
                //设置表头
                for(int k=0; k<cnFields.length;k++){
                    row.createCell(k).setCellValue(cnFields[k]);
                }
            }
            row = sheet.createRow(i + 1);
            for(int j = 0; j<enFields.length;j++) {
                Object data = list.get(i).get(enFields[j]);//获取第i行第j列所放数据
                HSSFCell contentCell = row.createCell(j);
                boolean isNum = false;
                boolean isInteger = false;
                if (data != null || "".equals(data)) {
                    //判断data是否为数值型
                    isNum = data.toString().matches("^(-?\\d+)(\\.\\d+)?$");
                    //判断data是否为整数(小数部分是否为0)
                    isInteger=data.toString().matches("^[-\\+]?[\\d]*$");
                }
                if(isNum){
                    HSSFDataFormat df = wb.createDataFormat(); // 此处设置数据格式
                    if (isInteger) {
                        //数据格式只显示整数
                        contextstyle.setDataFormat(df.getBuiltinFormat("0"));
                        // 设置单元格内容为double类型
                        contentCell.setCellValue(data.toString());
                    }else{
                        //保留两位小数点
                        contextstyle.setDataFormat(df.getBuiltinFormat("0.00"));
                        // 设置单元格内容为double类型
                       contentCell.setCellValue(Double.parseDouble(data.toString()));
                        // 设置单元格格式
                        contentCell.setCellStyle(contextstyle);
                    }
                }else {
                    contentCell.setCellValue(list.get(i).get(enFields[j]) == null ? "" : list.get(i).get(enFields[j]).toString());
                }
            }
            rowIndex++;
        }
        // 遍历集合数据,产生数据行
        sheet.setDefaultRowHeight((short) (16.5 * 20));
        //列宽自适应
        for (int i = 0; i <= 13; i++) {
            sheet.autoSizeColumn(i);
        }
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        OutputStream os = response.getOutputStream();
        response.setHeader("Content-disposition", "attachment;filename=balancelog.xls");//默认Excel名称
        wb.write(os);
        os.flush();
        os.close();
    }

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值