安装需要的插件

npm install --save xlsx
npm install --save xlsx-style  # 如果需要修改样式,则需要安装
    # 1.解决引入xlsx-style报错问题 
    # 2.找到:node_modules\xlsx-style\dist\xlsx.full.min.js 并把这个js文件拷贝到static文件夹下
    # 3.再index.html中引入 <script src="static/xlsx.full.min.js"></script>

    # 方法2安装第三方修改后的版本。
    # npm install --save yxg-xlsx-style

新建Export2Excel.js文件

import { saveAs } from "file-saver";
import XLSX from "yxg-xlsx-style";

function datenum(v, date1904) {
    if (date1904) v += 1462;
    var epoch = Date.parse(v);
    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}

function sheet_from_array_of_arrays(data, opts) {
    var ws = {};
    var range = {
        s: {
            c: 10000000,
            r: 10000000
        },
        e: {
            c: 0,
            r: 0
        }
    };
    for (var R = 0; R != data.length; ++R) {
        for (var C = 0; C != data[R].length; ++C) {
            if (range.s.r > R) range.s.r = R;
            if (range.s.c > C) range.s.c = C;
            if (range.e.r < R) range.e.r = R;
            if (range.e.c < C) range.e.c = C;
            var cell = {
                v: data[R][C]
            };
            if (cell.v == null) continue;
            var cell_ref = XLSX.utils.encode_cell({
                c: C,
                r: R
            });

            if (typeof cell.v === "number") cell.t = "n";
            else if (typeof cell.v === "boolean") cell.t = "b";
            else if (cell.v instanceof Date) {
                cell.t = "n";
                cell.z = XLSX.SSF._table[14];
                cell.v = datenum(cell.v);
            } else cell.t = "s";

            ws[cell_ref] = cell;
        }
    }
    if (range.s.c < 10000000) ws["!ref"] = XLSX.utils.encode_range(range);
    return ws;
}

function Workbook() {
    if (!(this instanceof Workbook)) return new Workbook();
    this.SheetNames = [];
    this.Sheets = {};
}

function s2ab(s) {
    var buf = new ArrayBuffer(s.length);
    var view = new Uint8Array(buf);
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
    return buf;
}


/*
导出excl
style字段说明
style-coordinate:位置(A1)
style-fgColor:背景颜色ARGB(ff0f0f0f)
style-horizontal:水平排列("bottom"||"center"||"top")
style-fontSZ:字体大小("11")
style-fontBold:是否加粗(`true || false`)
style-color:字体颜色ARGB(ff0f0f0f)

merges:合并单元格参数
{
    s: {//s为开始
        c: 1,//开始列
        r: 0//可以看成开始行,实际是取值范围
    },
    e: {//e结束
        c: 4,//结束列
        r: 0//结束行
    }
}

*/
export function export_json_to_excel({
    multiHeader = [],
    style = [],
    header,
    data,
    filename,
    merges = [],
    autoWidth = true,
    bookType = "xlsx",
    sheetName = "SheetJS"
} = {}) {
    /* original data */
    filename = filename || "excel-list";
    data = [...data];
    data.unshift(header);

    for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i]);
    }

    let wb = new Workbook();
    let ws = sheet_from_array_of_arrays(data);

    if (merges.length > 0) {
        if (!ws["!merges"]) ws["!merges"] = [];
        merges.forEach(item => {
            ws["!merges"].push(item);
        });
    }

    //设置单元格格式
    if (style.length > 0) {
        style.forEach(item => {
            if (ws[item.coordinate]) {
                ws[item.coordinate].s = {
                    fill: { fgColor: item.fgColor ? { rgb: item.fgColor } : { auto: 1 } },
                    alignment: { horizontal: item.horizontal ? item.horizontal : "bottom" },
                    font: {
                        sz: item.fontSZ ? item.fontSZ : "11",
                        bold: item.fontBold ? item.fontBold : "false",
                        color: item.color ? { rgb: item.color } : { auto: 1 }
                    }
                };
            }
        });
    }

    if (autoWidth) {
        /*设置worksheet每列的最大宽度*/
        const colWidth = data.map(row =>
            row.map(val => {
                /*先判断是否为null/undefined*/
                if (val == null) {
                    return {
                        wch: 10
                    };
                } else if (val.toString().charCodeAt(0) > 255) {
                    /*再判断是否为中文*/
                    return {
                        wch: val.toString().length * 2
                    };
                } else {
                    return {
                        wch: val.toString().length
                    };
                }
            })
        );
        /*以第一行为初始值*/
        let result = colWidth[0];
        for (let i = 1; i < colWidth.length; i++) {
            for (let j = 0; j < colWidth[i].length; j++) {
                if (result[j]["wch"] < colWidth[i][j]["wch"]) {
                    result[j]["wch"] = colWidth[i][j]["wch"];
                }
            }
        }
        ws["!cols"] = result;
    }

    /* add worksheet to workbook */
    wb.SheetNames.push(sheetName);
    wb.Sheets[sheetName] = ws;

    var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: "binary"
    });
    saveAs(
        new Blob([s2ab(wbout)], {
            type: "application/octet-stream"
        }),
        `${filename}.${bookType}`
    );
}

/*
sheet字段说明
sheet-data:数据
sheet-header:头
sheet-multiHeader:多级头
sheet-merges:合并单元格参数,参考export_json_to_excel
sheet-style:单元格样式参数,参考export_json_to_excel
sheet-autoWidth:是否自动宽度
sheet-sheetName:表名
*/
export function export_json_to_excel_batch({
    sheet,
    filename,
    bookType = "xlsx"
} = {}) {
    /* original data */
    filename = filename || "excel-list";

    let wb = new Workbook();

    for (let j = 0; j < sheet.length; j++) {
        let data = [...sheet[j].data];
        data.unshift(sheet[j].header);

        if (sheet[j].multiHeader) {
            for (let i = sheet[j].multiHeader.length - 1; i > -1; i--) {
                data.unshift(sheet[j].multiHeader[i]);
            }
        }

        let ws = sheet_from_array_of_arrays(data);

        //处理单元格合并
        if (sheet[j].merges) {
            if (sheet[j].merges.length > 0) {
                if (!ws["!merges"]) ws["!merges"] = [];
                sheet[j].merges.forEach(item => {
                    ws["!merges"].push(item);
                });
            }
        }

        //设置单元格格式
        if (sheet[j].style.length > 0) {
            sheet[j].style.forEach(item => {
                if (ws[item.coordinate]) {
                    ws[item.coordinate].s = {
                        fill: { fgColor: item.fgColor ? { rgb: item.fgColor } : {} },
                        alignment: {
                            horizontal: item.horizontal ? item.horizontal : "bottom"
                        },
                        font: {
                            sz: item.fontSZ ? item.fontSZ : "11",
                            bold: item.fontBold ? item.fontBold : "false",
                            color: item.color ? { rgb: item.color } : { auto: 1 }
                        }
                    };
                    if (!item.fgColor) {
                        delete ws[item.coordinate].s.fill
                    }
                }
            });
        }

        if (!sheet[j].autoWidth) {
            sheet[j].autoWidth = true;
        }
        if (sheet[j].autoWidth) {
            /*设置worksheet每列的最大宽度*/
            const colWidth = data.map(row =>
                row.map(val => {
                    /*先判断是否为null/undefined*/
                    if (val == null) {
                        return {
                            wch: 10
                        };
                    } else if (val.toString().charCodeAt(0) > 255) {
                        /*再判断是否为中文*/
                        return {
                            wch: val.toString().length * 2
                        };
                    } else {
                        return {
                            wch: val.toString().length
                        };
                    }
                })
            );
            /*以第一行为初始值*/
            let result = colWidth[0];
            for (let i = 1; i < colWidth.length; i++) {
                for (let j = 0; j < colWidth[i].length; j++) {
                    if (result[j]["wch"] < colWidth[i][j]["wch"]) {
                        result[j]["wch"] = colWidth[i][j]["wch"];
                    }
                }
            }
            ws["!cols"] = result;
        }


        /* add worksheet to workbook */
        wb.SheetNames.push(sheet[j].sheetName);
        wb.Sheets[sheet[j].sheetName] = ws;
    }

    var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: "binary"
    });
    saveAs(
        new Blob([s2ab(wbout)], {
            type: "application/octet-stream"
        }),
        `${filename}.${bookType}`
    );
}

导出excl

import { export_json_to_excel } from "@/utils/Export2Excel";
export default {
    data() {
        return {
            multiHeader : ["大标题","",""],
            style : [{
              coordinate: "A1",
              fgColor: "ffa9d08e",
              horizontal: "center",
              fontSZ: "12",
              fontBold: "true"
            },{
              coordinate: "A2",
              fgColor: "ffa9d08e",
              horizontal: "center",
              fontSZ: "12",
              fontBold: "true"
            }],
            header : ['Id', 'Title', 'Author'],
            data: [["1","test","test"],["2","test","test"]],
            filename: "downExcel",
            merges : [{ s: { c: 0, r: 0 }, e: { c: 2, r: 0 } }]
        }
    },
    methods:{
        export_json_to_excel({
            multiHeader: multiHeader,
            style: style,
            header: header,
            data: data,
            filename: filename,
            merges: merges
        });
    }
}

导出多表excl

import { export_json_to_excel_batch } from "@/utils/Export2Excel";
// 参考上面的函数和导出excl。

(完)