excel的导出

前言: 

excel的导出是开发常见的功能,但是excel都是谁导出呢?

一般情况excel都是由后端导出生成blob格式返给前端,前端进行下载,当然前端也可以自己利用数据进行excel导出,前端导出需要考虑兼容性问题,这篇文章将介绍前端导出和后端导出的一些插件使用,当然对于数据量大的处理也需要提一下,所以文章还会讲解数据量大的问题

node端导出

1.node-xlsx

官网: node-xlsx - npm

根据官网,可以看到这个插件既可以生成excel,也可以对excel进行解析,这里主要讲解生成excel

(1)下载插件

npm install node-xlsx

(2)使用

引入
const xlsx = require('node-xlsx')
创建buffer
buffer = xlsx.build([{name: 'excel表名', data: 'excel数据'}], sheetOptions);

参数说明:

       sheetOptions :为表格样式

const sheetOptions = {'!cols': [{wch: 6}, {wch: 7}]};

        data的数据格式为[{},{}] 可以传入多个对象生成多个小excel ,每个对象的数据格式

{
  name: 'excel小表名'
  data: [['一行一列数据', '一行二列数据'],
         ['二行一列数据', '二行二列数据']]
  
}

除了直接写成buffer,也可以写成文件保存在后端,给前端excel的地址进行下载

写成文件的坏处: 会存储,占用内存,一定量要进行清除

const fs = require('fs')
fs.writeFile("文件名称.xlsx", buffer, function (err) {
  if (err) {
    console.log('写入失败‘);
  } else {
    console.log("写入成功!");
  }
});

使用案例:

egg的写的导出excel的service类

const xlsx = require('node-xlsx')
const Service = require('egg').Service;


class exportFileService extends Service {
    constructor(prop) {
        super(prop);
    }


 // const column = [
 //          { header: '姓名', key: 'name', width: 30 },
 //          { header: '年龄', key: 'age', width: 30 },
 //          { header: '生日', key: 'birthday', width: 30 },
 // ];
 // data = [{name:xx, age:xx, birthday:xx}]

    toExport(column, data, filename = '导出') {
        return new Promise((reslove, reject) => {
            const { ctx } = this;
            const colArr = []
            colArr.push([...column.map(col => col.header)])
            //xlsx数据
            data.forEach(item => {
                colArr.push([...column.map(col => item[col.key])])
            })
    
            console.log(column, data, 'dada')
    
           
            const buffer = xlsx.build([{ name: '导出sheet1', data: colArr }], { '!cols': [{ wch: 20 }, { wch: 20 }, { wch: 20 }, { wch: 20 }, { wch: 20 }, { wch: 20 },] });
            

            reslove({buffer})
         })
       
        


    }
}

module.exports = exportFileService;

egg端调用servece反给前端

  async downLoad() {
            const { ctx, service } = this;
            const { id, type } = ctx.request.body;
            let result = [],
             

            // node段请求后端接口返回数据
                const res = await ctx.service.getList.list({ id, type})
                if (res.status === 200 && res.data.length) {
                
                    result = res.data;
                }

 const header = [
     { header: '姓名', key: 'name', width: 30 },
     { header: '年龄', key: 'age', width: 30 },
     { header: '生日', key: 'birthday', width: 30 },
 ];
              
            
            // node端进行转excel
            try {
             
                let res = await service.exportExcel.toExport(header, result);
               
                ctx.set('Content-disposition', `attachment;filename=1.xlsx`);
                // 返回文件buffer
                ctx.body = res.buffer;
            } catch(err) {
                ctx.status = 500
                ctx.body = err
            }

        }

前端调用下载

         down(data) {
            axios({
                method: 'post',
                url: '/list/downLoad',
                responseType: 'blob',
                headers: {
                    'Content-Type': 'application/json',
                },
                data,
            }).then(res => {
                
                if (res.status === 200) {
                    let name = data.type === 'all' ? '全部列表' : '失败列表'
                    this.saveFile(res.data, `${name}${data.id}`);
                      )
                    
                
                }
            }).catch(error => {
               
               
            });
         }

 saveFile(file, filename) {
        const ieKit = /(?:ms|\()(ie)\s([\w\.]+)|trident|(edge|edgios|edga|edg)/i.test(window.navigator.userAgent);
        const blobData = new Blob([ file ], { type: 'application/vnd.ms-excel' });
        if (ieKit) {
            navigator.msSaveBlob && navigator.msSaveBlob(blobData, filename + '.xlsx');
        } else {
            const objectURL = window.URL.createObjectURL(blobData);
            const save_link = document.createElement('a');
            const event = document.createEvent('MouseEvents');
            save_link.href = objectURL;
            save_link.download = filename + '.xlsx';
            event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            save_link.dispatchEvent(event);
            window.URL.revokeObjectURL(objectURL);
        }
    }

 2.exceljs

官网:https://github.com/exceljs/exceljs/blob/master/README_zh.md

(1) 下载

npm install exceljs

(2) 使用

直接看官网吧,因为官网写的很详细,如果去创建一个excel,怎么向一个表增加数据,api有些多,所以自己看吧,最后也是可以返回一个buffer给前端,前端下载;

其实有了buffer,再利用fs写一个文件给前端文件地址也是ok的

前端直接导出excel

1.js-export-excel

官网:GitHub - jiengsad/js-export-excel: json导出excel(纯js 支持中文) ES6 module

是一个纯js进行导出的,所以适用于vue和react,因此要注意其兼容性,ie 10+

// 直接导出文件
const ExportJsonExcel = require("js-export-excel");

var option = {};

option.fileName = "excel";

option.datas = [
  {
    sheetData: [
      { one: "一行一列", two: "一行二列" },
      { one: "二行一列", two: "二行二列" },
    ],
    sheetName: "sheet",
    sheetFilter: ["two", "one"],
    sheetHeader: ["第一列", "第二列"],
    columnWidths: [20, 20],
  },
  {
    sheetData: [
      { one: "一行一列", two: "一行二列" },
      { one: "二行一列", two: "二行二列" },
    ],
  },
];

var toExcel = new ExportJsonExcel(option); //new
toExcel.saveExcel(); //保存

数据量大excel导出处理

在本个案例中,node做的处理是-》循环调用后端接口,拿到所有数据开始写入excel,最后将二进制流返给前端

当数据量过大,比如3w条数据,会发现node端一次性写入在本地导出下载都非常完美,但是发布到线上之后,数据量过大,会直接服务器错误,502;

前端也可以导出excel,如上所诉;但是前端导出会有兼容性问题(如果是测试部署后前端没有问题,前端去导出大数据是很完美的,测试下来速度很快),刚好这个项目部署到线上平台前端有兼容性,因此最后还是服务端进行处理;

由于问题是只有部署到线上才有问题,所以第一时间想到了是否是配置下载的大小被限制了,线上环境配置的容器内存很小,因此在写入大数量的时候,特别容易崩溃

性能消耗比较大的地方,一个是API数据写入excel库对象的时候,一个是写完以后把数据转为二进制流;

为了处理这个问题,最后变更node端;

(1)将写入的文件分批次(2000条,2000条)写入存在一个excel文件,不再一次性返多条数据的二进制流,而是变更为返回文件地址;

(2) 多个请求放入队列,当一个excel文件全部写入成功,才开始进行写入下一个请求的excel

(3)node端的Excel文件存储起来是没有用的且占用存储空间,因此还需要做一个定时清理的工作;

其实,这并不是最好的处理方案,这样处理下来

优点: 数据量的时候,不会再导致服务器崩溃,解决了服务器崩溃问题

缺点:对于前端来说,发起一个请求,得到了这条数据的一个状态,需要隔断时间轮询服务器是否已经下载完成

这里暂时不放源码了,这个方案并不是最优方案,目前发现可以进行创建流,分段传输,但是因为对node端还不是特别熟悉,所以需要再继续研究,希望有好的建议的也一起讨论

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Excel导出Java是指将Java对象中的数据导出Excel表格中。通常情况下,我们需要使用第三方库来实现这个功能,比如Apache POI和EasyExcel等。在Java对象中,我们需要使用注解来标记需要导出的字段,以及字段的顺序、名称、映射关系等信息。在导出时,我们需要将Java对象转换为Excel表格,并设置表头、样式等属性。最后,我们将生成的Excel表格保存到本地或者输出到浏览器中供用户下载。Excel导出Java是指将Java对象中的数据导出Excel表格中。通常情况下,我们需要使用第三方库来实现这个功能,比如Apache POI和EasyExcel等。在Java对象中,我们需要使用注解来标记需要导出的字段,以及字段的顺序、名称、映射关系等信息。在导出时,我们需要将Java对象转换为Excel表格,并设置表头、样式等属性。最后,我们将生成的Excel表格保存到本地或者输出到浏览器中供用户下载。 在上面的引用中,我们可以看到一个Excel导出的注解@ExcelExport,它包含了字段名称、导出排序、导出映射、导出模板示例值等属性。我们还可以看到一个Excel导入的注解@ExcelImport,它用于标记Java实体对象中需要导入的字段,并指定对应的表头名称。 在实际开发中,我们通常会在Controller层中编写导出Excel的代码。我们可以使用第三方库来生成Excel表格,并将其输出到浏览器中供用户下载。同时,我们还可以编写导入Excel的代码,将Excel表格中的数据读取到Java对象中进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值