Use xlsx, xlsx-style, file-saver plug-ins in vue to print excel files with table raw data

 The printed excel file is as follows: 

 1. You need to install the plug-in (the xlsx plug-in already has the line break function after use, if you have no style requirements for the exported excel file, you don’t need to download the xlsx-style plug-in)

npm i -S xlsx
npm i -S file-saver

Choose to use xlsx-style according to the situation: if you need to change the background color of the cell, add a border, etc.

npm i -S xlsx-style

Problems encountered during installation:

Can‘t resolve ‘./cptable‘ in ‘xxx\node_modules_xlsx

Solution: Add the following code to the vue.config.js file

  chainWebpack: (config) => {
    //忽略的打包文件
    config.externals({
      './cptable': 'var cptable'
    });
  },

2. Add the key js file, I added it under the tools folder

 The complete content of the js file is as follows:

Blob.js

/* eslint-disable */
/* Blob.js
 * A Blob implementation.
 * 2014-05-27
 *
 * By Eli Grey, http://eligrey.com
 * By Devin Samarin, https://github.com/eboyjr
 * License: X11/MIT
 *   See LICENSE.md
 */
 
/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
 plusplus: true */
 
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
 
(function (view) {
    "use strict";
 
    view.URL = view.URL || view.webkitURL;
 
    if (view.Blob && view.URL) {
        try {
            new Blob;
            return;
        } catch (e) {}
    }
 
    // Internally we use a BlobBuilder implementation to base Blob off of
    // in order to support older browsers that only have BlobBuilder
    var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
            var
                get_class = function(object) {
                    return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
                }
                , FakeBlobBuilder = function BlobBuilder() {
                    this.data = [];
                }
                , FakeBlob = function Blob(data, type, encoding) {
                    this.data = data;
                    this.size = data.length;
                    this.type = type;
                    this.encoding = encoding;
                }
                , FBB_proto = FakeBlobBuilder.prototype
                , FB_proto = FakeBlob.prototype
                , FileReaderSync = view.FileReaderSync
                , FileException = function(type) {
                    this.code = this[this.name = type];
                }
                , file_ex_codes = (
                    "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
                    + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
                ).split(" ")
                , file_ex_code = file_ex_codes.length
                , real_URL = view.URL || view.webkitURL || view
                , real_create_object_URL = real_URL.createObjectURL
                , real_revoke_object_URL = real_URL.revokeObjectURL
                , URL = real_URL
                , btoa = view.btoa
                , atob = view.atob
 
                , ArrayBuffer = view.ArrayBuffer
                , Uint8Array = view.Uint8Array
                ;
            FakeBlob.fake = FB_proto.fake = true;
            while (file_ex_code--) {
                FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
            }
            if (!real_URL.createObjectURL) {
                URL = view.URL = {};
            }
            URL.createObjectURL = function(blob) {
                var
                    type = blob.type
                    , data_URI_header
                    ;
                if (type === null) {
                    type = "application/octet-stream";
                }
                if (blob instanceof FakeBlob) {
                    data_URI_header = "data:" + type;
                    if (blob.encoding === "base64") {
                        return data_URI_header + ";base64," + blob.data;
                    } else if (blob.encoding === "URI") {
                        return data_URI_header + "," + decodeURIComponent(blob.data);
                    } if (btoa) {
                        return data_URI_header + ";base64," + btoa(blob.data);
                    } else {
                        return data_URI_header + "," + encodeURIComponent(blob.data);
                    }
                } else if (real_create_object_URL) {
                    return real_create_object_URL.call(real_URL, blob);
                }
            };
            URL.revokeObjectURL = function(object_URL) {
                if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
                    real_revoke_object_URL.call(real_URL, object_URL);
                }
            };
            FBB_proto.append = function(data/*, endings*/) {
                var bb = this.data;
                // decode data to a binary string
                if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
                    var
                        str = ""
                        , buf = new Uint8Array(data)
                        , i = 0
                        , buf_len = buf.length
                        ;
                    for (; i < buf_len; i++) {
                        str += String.fromCharCode(buf[i]);
                    }
                    bb.push(str);
                } else if (get_class(data) === "Blob" || get_class(data) === "File") {
                    if (FileReaderSync) {
                        var fr = new FileReaderSync;
                        bb.push(fr.readAsBinaryString(data));
                    } else {
                        // async FileReader won't work as BlobBuilder is sync
                        throw new FileException("NOT_READABLE_ERR");
                    }
                } else if (data instanceof FakeBlob) {
                    if (data.encoding === "base64" && atob) {
                        bb.push(atob(data.data));
                    } else if (data.encoding === "URI") {
                        bb.push(decodeURIComponent(data.data));
                    } else if (data.encoding === "raw") {
                        bb.push(data.data);
                    }
                } else {
                    if (typeof data !== "string") {
                        data += ""; // convert unsupported types to strings
                    }
                    // decode UTF-16 to binary string
                    bb.push(unescape(encodeURIComponent(data)));
                }
            };
            FBB_proto.getBlob = function(type) {
                if (!arguments.length) {
                    type = null;
                }
                return new FakeBlob(this.data.join(""), type, "raw");
            };
            FBB_proto.toString = function() {
                return "[object BlobBuilder]";
            };
            FB_proto.slice = function(start, end, type) {
                var args = arguments.length;
                if (args < 3) {
                    type = null;
                }
                return new FakeBlob(
                    this.data.slice(start, args > 1 ? end : this.data.length)
                    , type
                    , this.encoding
                );
            };
            FB_proto.toString = function() {
                return "[object Blob]";
            };
            FB_proto.close = function() {
                this.size = this.data.length = 0;
            };
            return FakeBlobBuilder;
        }(view));
 
    view.Blob = function Blob(blobParts, options) {
        var type = options ? (options.type || "") : "";
        var builder = new BlobBuilder();
        if (blobParts) {
            for (var i = 0, len = blobParts.length; i < len; i++) {
                builder.append(blobParts[i]);
            }
        }
        return builder.getBlob(type);
    };
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

 Export2Excel.js, if you have style requirements for the printed form, you need to read the code carefully to understand the style object properties of the excel file. It is recommended to read this article JavaScript export excel file, and modify the file style_FEWY's blog-CSDN blog_js bubble sort

/* eslint-disable */

require('script-loader!file-saver');
require('./Blob.js');
require('script-loader!xlsx/dist/xlsx.core.min');
import XLSXS from "xlsx-style"
function generateArray(table) {
    var out = [];
    var rows = table.querySelectorAll('tr');
    var ranges = [];
    for (var R = 0; R < rows.length; ++R) {
        var outRow = [];
        var row = rows[R];
        var columns = row.querySelectorAll('td');
        for (var C = 0; C < columns.length; ++C) {
            var cell = columns[C];
            var colspan = cell.getAttribute('colspan');
            var rowspan = cell.getAttribute('rowspan');
            var cellValue = cell.innerText;
            if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;

            //Skip ranges
            ranges.forEach(function (range) {
                if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
                for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
                }
            });

            //Handle Row Span
            if (rowspan || colspan) {
                rowspan = rowspan || 1;
                colspan = colspan || 1;
                ranges.push({
                s: {
                    r: R,
                    c: outRow.length
                },
                e: {
                    r: R + rowspan - 1,
                    c: outRow.length + colspan - 1
                }
                });
            };

            //Handle Value
            outRow.push(cellValue !== "" ? cellValue : null);

            //Handle Colspan
            if (colspan)
                for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
        }
        out.push(outRow);
    }
    return [out, ranges];
};

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 = XLSXS.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'] = XLSXS.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;
}

export function export_table_to_excel(id) {
    var theTable = document.getElementById(id);
    var oo = generateArray(theTable);
    var ranges = oo[1];

    /* original data */
    var data = oo[0];
    var ws_name = "SheetJS";

    var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);

    /* add ranges to worksheet */
    // ws['!cols'] = ['apple', 'banan'];
    ws['!merges'] = ranges;

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

    var wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: false,
        type: 'binary'
    });

    saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
    }), "test.xlsx")
}
export function export_json_to_excel({
    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: 'thin',//表示用细框线
        },
        bottom: {
            style: 'thin'
        },
        left: {
            style: 'thin'
        },
        right: {
            style: 'thin'
        }
    };
    for (let key in ws) {
        if (ws[key] instanceof Object) {
            ws[key].s = {
                name:'宋体',
                border: borderAll,
                alignment: {
                    horizontal: 'center', //水平居中对齐
                    vertical: 'center',//垂直居中
                    wrapText: 1,//自动换行
                },
                font: {
                    sz: 10,//单元格中字体的样式与颜色设置
                    color: {
                        rgb: '495060'
                    }
                },
                bold: true,
                numFmt: 0
            }
        }
    }
    let arr = ["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1", "I1", "J1", "K1", "L1", "M1", "N1", "O1", "P1", "Q1", "R1", "S1", "T1", "U1", "V1", "W1", "X1", "Y1", "Z1"];
    let arr1 = ["A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2", "I2", "J2", "K2", "L2", "M2", "N2", "O2", "P2", "Q2", "R2", "S2", "T2", "U2", "V2", "W2", "X2", "Y2", "Z2"];
    arr.some(function (v) {//对单独的1  2 行进行样式修改,去掉框线,放大字体
        let a = merges[0].split(':')
        if (v == a[1]) {
            ws[v].s.border = {}
          return true;
        }else {
            ws[v].s.border = {}
        }
        ws[v].s.font= {
            sz: 14,//单元格中字体的样式与颜色设置
            color: {
                rgb: '495060'
            },
            bold: true,
        }
      })
      arr1.some(function (v) {
        if (ws[v]) {
            ws[v].s.border = {}
        }
      })
    if (merges.length > 0) {
        if (!ws['!merges']) ws['!merges'] = [];
        merges.forEach(item => {
            ws['!merges'].push(XLSXS.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)
            })
        })
    }
    /* 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
    }
}

If you do not need to operate the style, you can replace the method in the Export2Excel.js file with the following

// 对此方法进行修改,如下:
 export function export_json_to_excel({
     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);       
    if (merges.length > 0) {
         if (!ws['!merges']) ws['!merges'] = [];
             merges.forEach(item => {
            ws['!merges'].push(XLSX.utils.decode_range(item))
        })
    }

    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(ws_name);
     wb.Sheets[ws_name] = ws;

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

3. For the use on the page, the format required for some key variables is pasted at the end of the article

    //html部分
<el-button
            size="small"
            icon="el-icon-download"
            @click="exportDataEvent"
            circle
          >
          </el-button>
//js部分
    exportDataEvent() {
      this.handleExportMarketingList(information,tableColumn);},

// 导出方法
    handleExportMarketingList(information, optionColumnList) {
      import("_b/pages/utils/vendor/Export2Excel.js").then((excel) => {//根据实际路径进行修改
        let tHeader = [];
        optionColumnList.forEach((ele) => {
          tHeader.push(ele.title);
        });
        let multiHeader = [[]];
        tHeader.forEach((ele, index) => {
          index === 0
            ? multiHeader[0].push("汇总表")
            : multiHeader[0].push("");
        });
        let multiHeader2 = [[]];
        tHeader.forEach((ele, index) => {
          index === 0
            ? multiHeader2[0].push(`名称:${this.proName}`)
            : multiHeader2[0].push("");
        });
        multiHeader2[0].splice(
          multiHeader2[0].length - 1,
          1,
          `编号:${this.proCode}`
        );
        const filterVal = optionColumnList;
        let data = information.map((v) => filterVal.map((j) => v[j.field]));
        const englishWordList = [
          "A",
          "B",
          "C",
          "D",
          "E",
          "F",
          "G",
          "H",
          "I",
          "J",
          "K",
          "L",
          "M",
          "N",
          "O",
          "P",
          "Q",
          "R",
          "S",
          "T",
          "U",
          "V",
          "W",
          "X",
          "Y",
          "Z",
        ];
        // 进行所有表头的单元格合并
        let typeList = [];
        data.forEach((ele) => {
          typeList.push(ele[0]);
        });
        data = data.concat(this.footerDataList);
        let merges = [
          `A1:${englishWordList[tHeader.length - 1]}1`,
          `A2:${englishWordList[tHeader.length - 2]}2`,
        ];
        for (let i = 1; merges.length < (data.length - 4) / 2 + 2; i += 2) {
          merges.push(`A${3 + i}:A${4 + i}`);
        }
        merges.push(`A${data.length}:B${data.length}`);
        merges.push(`A${data.length + 1}:B${data.length + 1}`);
        merges.push(`A${data.length + 2}:B${data.length + 2}`);
        merges.push(`A${data.length + 3}:B${data.length + 3}`);
        excel.export_json_to_excel({
          multiHeader,
          multiHeader2,
          header: tHeader,
          data,
          filename: "汇总",
          merges,
        });
      });
    },

 

 

 

Guess you like

Origin blog.csdn.net/weixin_45294459/article/details/127107399