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

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

npm install --save xlsx file-saver

然后需要安装

npm install xlsx-style

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

1、在\node_modules\xlsx-style\dist\cpexcel.js 807行把 var cpt = require('./cpt' + 'able'); 
改成 var cpt = cptable;

2、在\node_modules\xlsx-style\ods.js 10行和13行把路径改为 require('./xlsx')

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

require('script-loader!file-saver');
require('./Blob.js');//这里是你的Blob.js的地址
require('script-loader!xlsx/dist/xlsx.core.min');
import XLSXS from "xlsx-style"必须要引入才可以,否则报错
export function export_json_to_excelhb({
    multiHeader2 = [], // 第一行表头
    multiHeader = [], // 第二行表头
    header, // 第三行表头
    data,//传递的数据
    filename, //文件名
    merges = [], // 合并
    autoWidth = true,//用于设置列宽的
    bookType = 'xlsx'
} = {}) {
    /* original data */
    filename = filename || '列表';
    data = [...data]
    data.unshift(header);
    for (let i = multiHeader2.length - 1; i > -1; i--) {
        data.unshift(multiHeader2[i])
    }
    for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i])
    }
    var ws_name = "SheetJS";
    var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);
    let borderAll = { //单元格外侧框线
        top: {
            style: 'medium',
        },
        bottom: {
            style: 'medium'
        },
        left: {
            style: 'medium'
        },
        right: {
            style: 'medium'
        }
    };

    for (let key in ws) {
        if (ws[key] instanceof Object) {
            ws[key].s = {
                border: borderAll,
                alignment: {
                    horizontal: 'center', //水平居中对齐
                    vertical: 'center',//垂直居中
                    wrapText: 1,//自动换行
                },
                font: {
                    sz: 10,//单元格中字体的样式与颜色设置
                    color: {
                        rgb: '495060'
                    }
                },
                bold: true,
                numFmt: 0
            }
        }
    }
    ws['I2'] = ws['H2'] = ws['G2'] = ws['F2'] = ws['E2'] = ws['D2'] = ws['C2'] = ws['B2'] = ws['A2']//用于第二行的单元格的样式设置(如果是合并的第一行,就是1)
    if (merges.length > 0) {
        if (!ws['!merges']) ws['!merges'] = [];
        merges.forEach(item => {
            ws['!merges'].push(XLSX.utils.decode_range(item))
        })
    }
    if (autoWidth) {
        let colWidths = [];
        // 计算每一列的所有单元格宽度
        // 先遍历行
        data.forEach((row) => {
            // 列序号
            let index = 0
            // 遍历列
            for (const key in row) {
                if (colWidths[index] == null) colWidths[index] = []
                switch (typeof row[key]) {
                    case 'string':
                    case 'number':
                    case 'boolean':                     colWidths[index].push(getCellWidth(row[key]))
                        break
                    case 'object':
                    case 'function':
                        colWidths[index].push(0)
                        break
                }
                index++
            }
        })
        ws['!cols'] = [];
        colWidths.forEach((widths, index) => {
            // 计算列头的宽度
            widths.push(getCellWidth(header[index]))
            // 设置最大值为列宽
            ws['!cols'].push({
                wch: Math.max(...widths)
            })
        })
    }
    console.log(ws);
    /* add worksheet to workbook */
    wb.SheetNames.push(ws_name);
    wb.Sheets[ws_name] = ws;
    var wbout = XLSXS.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: 'binary'
    });
    saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    }), `${filename}.${bookType}`);
}
export function getCellWidth(value) {
    if (value == null) {
        return 10
    } else if (value.toString().charCodeAt(0) > 255) {
        // 判断是否包含中文
        let length = value.toString().length * 2
        if (length > 60) {
            length = length - 40 
//这里的宽度可以自己设定,在前面设置wrapText: 1可以在单元格内换行
        }
        return length
    } else {
        return value.toString().length * 1.2
    }
}


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

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

 最终的实现结果如下图

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

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

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

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

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

你可能感兴趣的:(前端导出excel,javascript,excel)