ToB企服应用市场:ToB评测及商务社交产业平台

标题: vue中利用exceljs和file-saver插件实现纯前端表格导出Excel(支持样式配置 [打印本页]

作者: 科技颠覆者    时间: 2024-9-25 02:56
标题: vue中利用exceljs和file-saver插件实现纯前端表格导出Excel(支持样式配置
实现:利用Excel.js库创建excel文件,然后再利用 file-saver库将 Excel 文件生存到用户的本地盘算机。
1.安装,可以利用npm,yarn

   npm install exceljs
npm install file-saver
   2.封装生成excel的方法

  1. // 封装exceljs
  2. const ExcelJS = require('exceljs');
  3. const FileSaver = require('file-saver');
  4. exportDataToExcel(config, fileName) {
  5.         
  6.         if (!config) return;
  7.         const options = {
  8.             fileName: fileName || `导出excel文件【${Date.now()}】.xlsx`,
  9.             worksheets: []
  10.         }
  11.         if(!Array.isArray(config)) {
  12.             config = [config]
  13.         }
  14.         config.forEach((item) => {
  15.             // 深拷贝data【JSON.stringify有缺陷,可自行换成_.cloneDeep】
  16.             const data = JSON.parse(JSON.stringify(item.data));
  17.         
  18.             const results = data.map(obj => {
  19.             return item.fields.map(key => {
  20.                     return obj[key]
  21.                 })
  22.             })
  23.             // 生成完整excel数据
  24.             let excelData = [];
  25.             excelData = excelData.concat(item.headers).concat(results);
  26.             // 单元格合并处理【excel数据的第一行/列是从1开始】
  27.             let excelMerges = [];
  28.             excelMerges = item.merges.map(m => {
  29.                 return [m.row + 1, m.col + 1, m.row + m.rowspan, m.col + m.colspan]
  30.             })
  31.             // 单元格配置处理 excel数据的第一行/列是从1开始】
  32.             let excelAttrs = [];
  33.             excelAttrs = item.attrs.map(attr => {
  34.                 attr.rowStart += 1;
  35.                 attr.rowEnd += 1;
  36.                 attr.colStart += 1;
  37.                 attr.colEnd += 1;
  38.                 return attr
  39.             })
  40.             options.worksheets.push({
  41.                 data: excelData,
  42.                 merges: excelMerges,
  43.                 attrs: excelAttrs,
  44.                 views: item.views,
  45.                 columnsWidth: item.columnsWidth,
  46.                 protect: item.protect,
  47.                 sheetName: item.sheetName
  48.             })
  49.         })
  50.         this.createExcel(options)
  51. },
  52.     // 创建Excel文件方法
  53. async createExcel(options) {
  54.         if (!options.worksheets.length) return;
  55.         // 创建工作簿
  56.         const workbook = new ExcelJS.Workbook();
  57.         for (let i = 0; i < options.worksheets.length; i++) {
  58.             const sheetOption = options.worksheets[i];
  59.             // 创建工作表
  60.             const sheet = workbook.addWorksheet(sheetOption.sheetName || 'sheet' + (i + 1));
  61.             // 添加数据行
  62.             sheet.addRows(sheetOption.data);
  63.             // 配置视图
  64.             sheet.views = sheetOption.views;
  65.             // 单元格合并处理【开始行,开始列,结束行,结束列】
  66.             if (sheetOption.merges){
  67.             sheetOption.merges.forEach((item) => {
  68.                 sheet.mergeCells(item)
  69.             });
  70.             }
  71.             // 工作表保
  72.             if (sheetOption.protect) {
  73.             const res = await sheet.protect(sheetOption.protect.password, sheetOption.protect.options);
  74.             }
  75.             // 单元格样式处理
  76.             if (sheetOption.attrs.length) {
  77.             sheetOption.attrs.forEach((item) => {
  78.                 const attr = item.attr || {};
  79.                 // 获取开始行-结束行; 开始列-结束列
  80.                 const rowStart = item.rowStart;
  81.                 const rowEnd = item.rowEnd;
  82.                 const colStart = item.colStart;
  83.                 const colEnd = item.colEnd;
  84.             if (rowStart) { // 设置行
  85.             for (let r = rowStart; r <= rowEnd; r++) {
  86.                     // 获取当前行
  87.                     const row = sheet.getRow(r);
  88.                     if (colStart) { // 列设置
  89.                     for (let c = colStart; c <= colEnd; c++) {
  90.                         // 获取当前单元格
  91.                         const cell = row.getCell(c);
  92.                         Object.keys(attr).forEach((key) => {
  93.                         // 给当前单元格设置定义的样式
  94.                         cell[key] = attr[key];
  95.                         });
  96.                     }
  97.                     } else {
  98.                     // 未设置列,整行设置【大纲级别】
  99.                     Object.keys(attr).forEach((key) => {
  100.                         row[key] = attr[key];
  101.                     });
  102.                     }
  103.                 }
  104.                 } else if (colStart) { // 未设置行,只设置了列
  105.                 for (let c = colStart; c <= colEnd; c++) {
  106.                     // 获取当前列,整列设置【大纲级别】
  107.                     const column = sheet.getColumn(c);
  108.                     Object.keys(attr).forEach((key) => {
  109.                     column[key] = attr[key];
  110.                     });
  111.                 }
  112.                 } else {
  113.                 // 没有设置具体的行列,则为整表设置
  114.                 Object.keys(attr).forEach((key) => {
  115.                     sheet[key] = attr[key];
  116.                 });
  117.                 }
  118.             })
  119.         }
  120.         // 列宽设置
  121.         if (sheetOption.columnsWidth) {
  122.             for (let i = 0; i < sheet.columns.length; i++) {
  123.                 sheet.columns[i].width = sheetOption.columnsWidth[i]
  124.             }
  125.         }
  126.     }
  127.    
  128.     // 生成excel文件
  129.     workbook.xlsx.writeBuffer().then(buffer => {
  130.         // application/octet-stream 二进制数据
  131.         FileSaver.saveAs(new Blob([buffer], { type: 'application/octet-stream' }), options.fileName)
  132.     })
  133. }
复制代码
3.在项目中利用

  1. exportExcel(){
  2.             const header = [
  3.                 ["所在部门","隐患总数","已整改隐患数","整改率","一般隐患","较大隐患","重大隐患"],
  4.                 ["","","","","隐患数","已整改数","整改中数","整改率(%)","隐患数","已整改数","整改中数","整改率(%)","隐患数","已整改数","整改中数","整改率(%)"]
  5.             ]
  6.             const fields = ["name","count","count_yzg","count_zgz","zgl","count_common","count_common_yzg","count_common_zgz","ybyh_zgl","count_bigger","count_bigger_yzg","count_bigger_zgz","jdyh_zgl","count_biggest","count_biggest_yzg","count_biggest_zgz","zdyh_zgl"]
  7.             const merges = [
  8.                 //导出表格的第一行第一列,行合并2个单元格,列就用自己的一个;
  9.                 {row: 0, col: 0, rowspan: 2, colspan: 1},
  10.                 {row: 0, col: 1, rowspan: 2, colspan: 1},
  11.                 {row: 0, col: 2, rowspan: 2, colspan: 1},
  12.                 {row: 0, col: 3, rowspan: 2, colspan: 1},
  13.                 {row: 0, col: 4, rowspan: 2, colspan: 1},
  14.                 {row: 0, col: 5, rowspan: 1, colspan: 4},
  15.                 {row: 0, col: 9, rowspan: 1, colspan: 4},
  16.                 {row: 0, col: 13, rowspan: 1, colspan: 4},
  17.             ]
  18.             const config = this.exportConfig(header,fields,merges,this.tabledata[this.type]);//配置
  19.             this.$utils.exportDataToExcel(config, "隐患治理情况统计表.xlsx");
  20.         },
  21.         //导出表格配置
  22.         exportConfig(header = [], fields = [], merges = [], tableData = []){
  23.             // console.log(header, fields, merges, tableData );
  24.             // return
  25.         //配置表头header1为一级表头,header2为二级表头,被合并的单元格为空写占位符"":
  26.         // 如果导出前要处理数据,需要深克隆一份表格数据,然后进行处理
  27.         const exportTableData = JSON.parse(JSON.stringify(tableData));
  28.         const config = {
  29.                 data: exportTableData,//exportTableData为表格数据,为空的话,导出表格只显示表头
  30.                 fields: fields,
  31.                 headers: header,
  32.                 merges: merges,
  33.                 attrs: [],
  34.                 view: [],
  35.                 columnsWidth: [20, 20, 20, 20, 20,20, 20,20, 20, 20, 20, 20,20, 20,20,20],//每行列的宽
  36.                 // protect: {},
  37.                 sheetName: "个人信息"
  38.          };
  39.          // 设置全表单元格边框,居中布局
  40.          config.attrs.push({
  41.                 rowStart: 0,
  42.                 rowEnd: config.data.length + 1,//表格表头多几层,就加几个
  43.                 colStart: 0,
  44.                 colEnd: config.fields.length - 1,
  45.                 attr: {
  46.                     alignment: { vertical: "middle", horizontal: "center" },
  47.                     border: {
  48.                         top: { style: "thin" },
  49.                         left: { style: "thin" },
  50.                         bottom: { style: "thin" },
  51.                         right: { style: "thin" }
  52.                     }
  53.                 }
  54.            });
  55.            // 设置表头填充颜色,字体加粗
  56.             config.attrs.push({
  57.                 rowStart: 0,
  58.                 rowEnd: 1,//表格表头多几层,就写几
  59.                 colStart: 0,
  60.                 colEnd: config.fields.length - 1,
  61.                 attr: {
  62.                     fill: {
  63.                         type: "pattern",
  64.                         pattern: "solid",
  65.                         fgColor: { argb: "c5c8ce" }
  66.                     },
  67.                     font: {
  68.                         bold: true
  69.                     }
  70.                 }
  71.             });
  72.            return config;
  73. }
复制代码
  /**
       * 导出数据到Excel 传参参数
       * config.data 表格数据
       * config.fields 字段列表
       * config.headers excel表头列表[[]],可以是多级表头[['A1','B1'],['A2','B2']]
       * config.merges 需要归并的单元格,需要考虑表头的行数[{row:1, col:1, rowspan: 1, colspan: 2}]
       * config.attrs 单元格样式配置
       * config.views 工作表视图配置
       * columnsWidth 每个字段列对应的宽度
       * config.protect 工作表掩护【此配置会掩护全表,一样平常保举只针对单元格举行掩护配置】
       * sheetName 工作表名称,默认从sheet1开始
       * fileName excel文件名称
       */

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4