0


用exceljs和file-saver插件实现纯前端表格导出Excel(支持样式配置,多级表头)

exceljs在Jquery(HTML)和vue项目中实现导出功能

前言

最近,做公司一个老项目(jquery),有个需求是将表格中的json数据,导出为Excel文件,表格表头还是动态多层级,导出的excel样式和项目中表格一致;

老项目中之前用的都是xlsx插件,我查询了一下文章,也看到过用xlsx实现多层表头下载,但是感觉比较麻烦,看到推荐使用exceljs插件比较方便;就了解一下,用在项目中得以实现;

话不多说,上案例图:
在这里插入图片描述
导出excel效果:
在这里插入图片描述

这个案例我主要演示的是两层分组表头和样式配置的代码;如果要想仔细研究该插件,可以阅读 Exceljs官方文档;

怎么使用,下面记录非常详情,每一步代码还有注释解析,方便自己和大家理解

Jquery(HTML)中实现导出

第一步,先在项目本地中导入exceljs和file-saver包

在这里插入图片描述
在这里插入图片描述
以上插件包,也可以 npm install exceljs ,npm install file-saver获取,执行命令后项目中会多一个node_modules包,然后找到这两个文件复制出来放到项目中,然后删除无用的node_modules,和pakege.json文件;

第二步,封装导出Excel方法(可直接复制粘贴使用)

在项目中创建assets文件,新建一个exportDataToExcel.js文件

/**
     * 导出数据到Excel方法
     * @param {Array[Object]} config.data 表格数据
     * @param {Array[String]} config.fields 字段列表
     * @param {Array[String]} config.headers excel表头列表[[]],可以是多级表头[['A1','B1'],['A2','B2']]
     * @param {Array[Object]} config.merges 需要合并的单元格,需要考虑表头的行数[{row:1, col:1, rowspan: 1, colspan: 2}]
     * @param {Array[Object]} config.attrs 单元格样式配置
     * @param {Array[Object]} config.views 工作表视图配置
     * @param {Array[Number]} columnsWidth 每个字段列对应的宽度
     * @param {Object} config.protect 工作表保护【此配置会保护全表,一般推荐只针对单元格进行保护配置】
     * @param {String} sheetName 工作表名称,默认从sheet1开始
     * @param {String} fileName excel文件名称
     */functionexportDataToExcel(config, fileName){if(!config)return;const options ={
        fileName: fileName ||`导出excel文件【${Date.now()}】.xlsx`,
        worksheets:[]}if(!Array.isArray(config)){
        config =[config]}
    config.forEach((item)=>{// 深拷贝data【JSON.stringify有缺陷,可自行换成_.cloneDeep】const data =JSON.parse(JSON.stringify(item.data));const results = data.map(obj=>{return item.fields.map(key=>{return obj[key]})})// 生成完整excel数据let excelData =[];
        excelData = excelData.concat(item.headers).concat(results);// 单元格合并处理【excel数据的第一行/列是从1开始】let excelMerges =[];
        excelMerges = item.merges.map(m=>{return[m.row +1, m.col +1, m.row + m.rowspan, m.col + m.colspan]})// 单元格配置处理 excel数据的第一行/列是从1开始】let excelAttrs =[];
        excelAttrs = item.attrs.map(attr=>{
            attr.rowStart +=1;
            attr.rowEnd +=1;
            attr.colStart +=1;
            attr.colEnd +=1;return attr
        })
        options.worksheets.push({
            data: excelData,
            merges: excelMerges,
            attrs: excelAttrs,
            views: item.views,
            columnsWidth: item.columnsWidth,
            protect: item.protect,
            sheetName: item.sheetName
        })})createExcel(options)}// 创建Excel文件方法asyncfunctioncreateExcel(options){if(!options.worksheets.length)return;// 创建工作簿const workbook =newExcelJS.Workbook();for(let i =0; i < options.worksheets.length; i++){const sheetOption = options.worksheets[i];// 创建工作表const sheet = workbook.addWorksheet(sheetOption.sheetName ||'sheet'+(i +1));// 添加数据行
            sheet.addRows(sheetOption.data);// 配置视图
            sheet.views = sheetOption.views;// 单元格合并处理【开始行,开始列,结束行,结束列】if(sheetOption.merges){
            sheetOption.merges.forEach((item)=>{
                sheet.mergeCells(item)});}// 工作表保 if(sheetOption.protect){const res =await sheet.protect(sheetOption.protect.password, sheetOption.protect.options);}// 单元格样式处理if(sheetOption.attrs.length){
            sheetOption.attrs.forEach((item)=>{const attr = item.attr ||{};// 获取开始行-结束行; 开始列-结束列const rowStart = item.rowStart;const rowEnd = item.rowEnd;const colStart = item.colStart;const colEnd = item.colEnd;if(rowStart){// 设置行for(let r = rowStart; r <= rowEnd; r++){// 获取当前行const row = sheet.getRow(r);if(colStart){// 列设置for(let c = colStart; c <= colEnd; c++){// 获取当前单元格const cell = row.getCell(c);
                        Object.keys(attr).forEach((key)=>{// 给当前单元格设置定义的样式
                        cell[key]= attr[key];});}}else{// 未设置列,整行设置【大纲级别】
                    Object.keys(attr).forEach((key)=>{
                        row[key]= attr[key];});}}}elseif(colStart){// 未设置行,只设置了列for(let c = colStart; c <= colEnd; c++){// 获取当前列,整列设置【大纲级别】const column = sheet.getColumn(c);
                    Object.keys(attr).forEach((key)=>{
                    column[key]= attr[key];});}}else{// 没有设置具体的行列,则为整表设置
                Object.keys(attr).forEach((key)=>{
                    sheet[key]= attr[key];});}})}// 列宽设置if(sheetOption.columnsWidth){for(let i =0; i < sheet.columns.length; i++){
                sheet.columns[i].width = sheetOption.columnsWidth[i]}}}// 生成excel文件
    workbook.xlsx.writeBuffer().then(buffer=>{// application/octet-stream 二进制数据saveAs(newBlob([buffer],{ type:'application/octet-stream'}), options.fileName)})}

第三步,在项目中使用

在HTML中使用,不能使用模块导入,只能通过< script >标签引入;

<!DOCTYPE html><html lang="en"><head>//引入我们放入项目的文件的的压缩js文件<script src="/static/exceljs/dist/exceljs.min.js"></script><script src="/static/file-saver/dist/FileSaver.min.js"></script>//引入封装导出Excel方法<script src="/static/assets/exportDataToExcel.js"></script></head><body><script>//表格数据var exportTableData =[{name:'张三',sexy:'男',age:22,hobby:'篮球',provices:'河南省',city:'郑州',status:'未婚'},{name:'李四',sexy:'女',age:23,hobby:'排球',provices:'北京市',city:'北京市',status:'未婚'},{name:'王二',sexy:'男',age:28,hobby:'足球',provices:'山东省',city:'青岛',status:'已婚'},]//点击导出按钮事件functiononExport(){let config =exportConfig();exportDataToExcel(config,"人员信息表.xlsx");}//导出表格配置functionexportConfig(){//配置表头header1为一级表头,header2为二级表头,被合并的单元格为空写占位符""://这是实现导出多级表头的关键两点的中的第一点,分几层表头写几个header;const header1 =["姓名","个人信息","","","居住城市","","婚姻状况"];const header2 =["","性别","年龄","爱好","省份","城市",""];//表格展示字段,顺序要正确const fields =["name","sexy","age","hobby","provices","city","status"]//这是实现导出多级表头的关键两点的中的第二点,合并表头单元格;//row:代表行,col:代表列,rowspan:代表合并行数,colspan:代表合并列数;//也就是表头有几个合并的单元格地方,merges数组属性就有几个,不合并的表头不用管,我们只需要设置合并的表头;//如果是正常表格,只有一行标表头,无合并,merges 直接设置空数组[];const merges =[//导出表格的第一行第一列,行合并2个单元格,列就用自己的一个;{row:0, col:0, rowspan:2, colspan:1},//导出表格的第一行第二列,行合并1个单元格,列合并3个单元格;{row:0, col:1, rowspan:1, colspan:3},{row:0, col:4, rowspan:1, colspan:2},{row:0, col:6, rowspan:2, colspan:1},]// 如果导出前要处理数据,需要深克隆一份表格数据,然后进行处理
        exportTableData =JSON.parse(JSON.stringify(exportTableData));const config ={
                data: exportTableData,//exportTableData为表格数据,为空的话,导出表格只显示表头
                fields:fields,
                headers:[header1, header2],
                merges: merges,
                attrs:[],
                view:[],
                columnsWidth:[20,20,20,20,20,20,20,],//每行列的宽// protect: {},
                sheetName:"个人信息"};// 设置全表单元格边框,居中布局
         config.attrs.push({
                rowStart:0,
                rowEnd: config.data.length +1,//表格表头多几层,就加几个
                colStart:0,
                colEnd: config.fields.length -1,
                attr:{
                    alignment:{ vertical:"middle", horizontal:"center"},
                    border:{
                        top:{ style:"thin"},
                        left:{ style:"thin"},
                        bottom:{ style:"thin"},
                        right:{ style:"thin"}}}});// 设置表头填充颜色,字体加粗
            config.attrs.push({
                rowStart:0,
                rowEnd:1,//表格表头多几层,就写几
                colStart:0,
                colEnd: config.fields.length -1,
                attr:{
                    fill:{
                        type:"pattern",
                        pattern:"solid",
                        fgColor:{ argb:"c5c8ce"}},
                    font:{
                        bold:true}}});return config;}</script></body
</html>

vue中实现导出

第一步,还是先安装,可以使用npm,yarn,pnpm,都可以

npm install exceljs
npm install file-saver

第二步,在assets/index.js中暴露出一个exportDataToExcel方法

这个方法跟上面的方法是基本一样的,有两个点不同:
1.引入方式不同,vue项目可以使用模块引入,
2.还有方法中一个函数的使用,最后的FileSaver.saveAs(),在HTML代码中该方法可以直接用saveAs();主要原因还是引入的方式不同而已;

下面,一样的代码我就省略了,主要写不一样的代码展示:

// 封装exceljsconst ExcelJS =require('exceljs');const FileSaver =require('file-saver');exportfunctionexportDataToExcel(config, fileName){...}asyncfunctioncreateExcel(options){...// 生成excel文件
  workbook.xlsx.writeBuffer().then(buffer=>{// application/octet-stream 二进制数据
    FileSaver.saveAs(newBlob([buffer],{ type:'application/octet-stream'}), options.fileName)})}

第三步,项目中的使用

把第二步写的方法在项目中导入;

<script>import{ exportDataToExcel }from"../assets/index.js";data(){return{
         exportTableData:[{name:'张三',sexy:'男',age:22,hobby:'篮球',provices:'河南省',city:'郑州',status:'未婚'},{name:'李四',sexy:'女',age:23,hobby:'排球',provices:'北京市',city:'北京市',status:'未婚'},{name:'王二',sexy:'男',age:28,hobby:'足球',provices:'山东省',city:'青岛',status:'已婚'},]};},
 methods:{onExport(){const config =this.exportConfig();exportDataToExcel(config,"人员信息表.xlsx");},//该方法和上面在HTML中的一样exportConfig(){...}}</script>

记录是为了自己日后学习和方便使用,也希望能够帮助到你;

标签: 前端 excel html5

本文转载自: https://blog.csdn.net/qq_44182284/article/details/141066538
版权归原作者 前端探险家 所有, 如有侵权,请联系我们删除。

“用exceljs和file-saver插件实现纯前端表格导出Excel(支持样式配置,多级表头)”的评论:

还没有评论