加载中...

纯前端js(或者vue)导出excel实现:合并单元格、设置单元格样式、单元格内换行

纯前端js(或者vue)导出excel实现:合并单元格、设置单元格样式、单元格内换行

前提是安装xlsx,已经可以导出普通的excel

npm install --save xlsx file-saver

然后需要安装

npm install xlsx-style

如果运行的时候报错
需要修改源码,然后重新运行:

  1. 1、在\node_modules\xlsx-style\dist\cpexcel.js 807行把 var cpt = require(''./cpt'' + ''able'');
  2. 改成 var cpt = cptable;
  3. 2、在\node_modules\xlsx-style\ods.js 10行和13行把路径改为 require(''./xlsx'')

Blob.js 和Export2Excel.js 网上有很多
我在Export2Excel中做了修改,代码如下:
//Export2Excel.js

  1. require(''script-loader!file-saver'');
  2. require(''./Blob.js'');//这里是你的Blob.js的地址
  3. require(''script-loader!xlsx/dist/xlsx.core.min'');
  4. import XLSXS from "xlsx-style"必须要引入才可以,否则报错
  1. export function export_json_to_excelhb({
  2.     multiHeader2 = [], // 第一行表头
  3.     multiHeader = [], // 第二行表头
  4.     header, // 第三行表头
  5.     data,//传递的数据
  6.     filename, //文件名
  7.     merges = [], // 合并
  8.     autoWidth = true,//用于设置列宽的
  9.     bookType = ''xlsx''
  10. } = {}) {
  11.     /* original data */
  12.     filename = filename || ''列表'';
  13.     data = [...data]
  14.     data.unshift(header);
  15.     for (let i = multiHeader2.length - 1; i > -1; i--) {
  16.         data.unshift(multiHeader2[i])
  17.     }
  18.     for (let i = multiHeader.length - 1; i > -1; i--) {
  19.         data.unshift(multiHeader[i])
  20.     }
  21.     var ws_name = "SheetJS";
  22.     var wb = new Workbook(),
  23.         ws = sheet_from_array_of_arrays(data);
  24.     let borderAll = { //单元格外侧框线
  25.         top: {
  26.             style: ''medium'',
  27.         },
  28.         bottom: {
  29.             style: ''medium''
  30.         },
  31.         left: {
  32.             style: ''medium''
  33.         },
  34.         right: {
  35.             style: ''medium''
  36.         }
  37.     };
  38.     for (let key in ws) {
  39.         if (ws[key] instanceof Object) {
  40.             ws[key].s = {
  41.                 border: borderAll,
  42.                 alignment: {
  43.                     horizontal: ''center'', //水平居中对齐
  44.                     vertical: ''center'',//垂直居中
  45.                     wrapText: 1,//自动换行
  46.                 },
  47.                 font: {
  48.                     sz: 10,//单元格中字体的样式与颜色设置
  49.                     color: {
  50.                         rgb: ''495060''
  51.                     }
  52.                 },
  53.                 bold: true,
  54.                 numFmt: 0
  55.             }
  56.         }
  57.     }
  58.     ws[''I2''] = ws[''H2''] = ws[''G2''] = ws[''F2''] = ws[''E2''] = ws[''D2''] = ws[''C2''] = ws[''B2''] = ws[''A2'']//用于第二行的单元格的样式设置(如果是合并的第一行,就是1)
  59.     if (merges.length > 0) {
  60.         if (!ws[''!merges'']) ws[''!merges''] = [];
  61.         merges.forEach(item => {
  62.             ws[''!merges''].push(XLSX.utils.decode_range(item))
  63.         })
  64.     }
  65.     if (autoWidth) {
  66.         let colWidths = [];
  67.         // 计算每一列的所有单元格宽度
  68.         // 先遍历行
  69.         data.forEach((row) => {
  70.             // 列序号
  71.             let index = 0
  72.             // 遍历列
  73.             for (const key in row) {
  74.                 if (colWidths[index] == null) colWidths[index] = []
  75.                 switch (typeof row[key]) {
  76.                     case ''string'':
  77.                     case ''number'':
  78.                     case ''boolean'':                     colWidths[index].push(getCellWidth(row[key]))
  79.                         break
  80.                     case ''object'':
  81.                     case ''function'':
  82.                         colWidths[index].push(0)
  83.                         break
  84.                 }
  85.                 index++
  86.             }
  87.         })
  88.         ws[''!cols''] = [];
  89.         colWidths.forEach((widths, index) => {
  90.             // 计算列头的宽度
  91.             widths.push(getCellWidth(header[index]))
  92.             // 设置最大值为列宽
  93.             ws[''!cols''].push({
  94.                 wch: Math.max(...widths)
  95.             })
  96.         })
  97.     }
  98.     console.log(ws);
  99.     /* add worksheet to workbook */
  100.     wb.SheetNames.push(ws_name);
  101.     wb.Sheets[ws_name] = ws;
  102.     var wbout = XLSXS.write(wb, {
  103.         bookType: bookType,
  104.         bookSST: false,
  105.         type: ''binary''
  106.     });
  107.     saveAs(new Blob([s2ab(wbout)], {
  108.         type: "application/octet-stream"
  109.     }), `${filename}.${bookType}`);
  110. }
  111. export function getCellWidth(value) {
  112.     if (value == null) {
  113.         return 10
  114.     } else if (value.toString().charCodeAt(0) > 255) {
  115.         // 判断是否包含中文
  116.         let length = value.toString().length * 2
  117.         if (length > 60) {
  118.             length = length - 40
  119. //这里的宽度可以自己设定,在前面设置wrapText: 1可以在单元格内换行
  120.         }
  121.         return length
  122.     } else {
  123.         return value.toString().length * 1.2
  124.     }
  125. }


在自己的文件中调用
数据的格式,比如:
data=[{mc:"aaa",sex:''女''},{mc:"bbb",sex:''男''}]
tHeader=["名称","性别"]
filterVal=["mc","sex"]

  1. handleExportexcel() {
  2. //@/excel/Export2Excel是自己的Export2Excel的文件的地址
  3. import("@/excel/Export2Excel").then((excel) => {
  4. const multiHeader = [["光缆熔接纤序表"]];
  5. const multiHeader2 = [["设备名称"];
  6. const tHeader = [];
  7. const filterVal = []; // 表头所对应的字段,这里未填写,请自行填写对应的字段,按实际需求请自行处理该步
  8. let data = rjdata.map((v) => filterVal.map((j) => v[j])); //rjdata为请求的数据,此处理是为了对应字段,如不需要此处理,直接为data赋值即可
  9. // 进行所有表头的单元格合并
  10. let merges = [
  11. "A1:I1",
  12. "A2:I2", //合并行
  13. "A4:A6",
  14. "B4:B6",
  15. ];//如果是A1到I1合并就写A1:I1
  16. let excelname = String(
  17. new Date().format("yyyy-MM-dd-HH-mm-ss")
  18. ).replace(/[^0-9]/gi, "");//导出的excel的名字
  19. excel.export_json_to_excelhb({
  20. multiHeader, // 这里是第一行的表头
  21. multiHeader2, // 这里是第二行的表头
  22. header: tHeader, // 这里是第三行的表头
  23. data,
  24. filename: excelname,
  25. merges,
  26. });
  27. });
  28. },
  29. },

 最终的实现结果如下图

New Image

参考了下面两个大佬的文章,我的需求比他们的复杂一点。 

参考链接:JavaScript导出excel文件,并修改文件样式_FEWY的博客-CSDN博客_js导出excel设置样式

Vue 前端导出Excel表格,多级表头合并_迈向前端攻城狮的路上-CSDN博客_vue导出excel表格合并单元格

xlsx-style ./cptable'' 报错解决办法 - 龙果果 - 博客园