• vue实现通用导出(excel,csv, pdf文件)组件 前端导出


    后台管理项目中经常使用文件导入导出,故封装了一个通用table的导出组件的实现

    思路 使用 Dropdown 控件选择导出类型 触发导出

    tableColumns: [
    {
    title: '序号',
    key: 'Ordinal',
    align: 'center'
    },
    {
    title: '产品编号',
    key: 'ProductNo',
    align: 'left'
    }
    ]
    tableData: [{Ordinal:1,ProductNo:'1234',ProductDesc:'1232222'}]

     导出文件大部分情况下是后端处理,有时候我们只需要js处理 该怎么做呢?

    1.导出CSV
        首先实现导出CSV格式 
        拼接 csv格式其实就是个纯文本文件,中间使用逗号或者换行符进行拼接
        这里使用 json2cvs这个包 需要npm 安装 npm install json2csv  -s
        下载方式 
            IE浏览器 不支持a标签进行下载,会打开url 故
            对于微软系浏览器(IE和Edge)和非微软系列浏览器采用两种不同的方式进行下载
            IE和Edge 采用了  navigator.msSaveBlob 方法 此方法为IE10及以上特有,IE10以下勿采用
            非微软浏览器 使用a标签的click事件进行下载
    关键代码

    try {
    const result = json2csv.parse(rows, {
    fields: fields,
    excelStrings: true
    });
    if (this.MyBrowserIsIE()) {
    // IE10以及Edge浏览器
    var BOM = "uFEFF";
    // 文件转Blob格式
    var csvData = new Blob([BOM + result], { type: "text/csv" });
    navigator.msSaveBlob(csvData, `${fileName}.csv`);
    } else {
    let csvContent = "data:text/csv;charset=utf-8,uFEFF" + result;
    // 非ie 浏览器
    this.createDownLoadClick(csvContent, `${fileName}.csv`);
    }
    } catch (err) {
    alert(err);
    }

    //创建a标签下载
    createDownLoadClick(content, fileName) {
    const link = document.createElement("a");
    link.href = encodeURI(content);
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    },

    // 判断是否IE浏览器
    MyBrowserIsIE() {
    let isIE = false;
    if (
    navigator.userAgent.indexOf("compatible") > -1 &&
    navigator.userAgent.indexOf("MSIE") > -1
    ) {
    // ie浏览器
    isIE = true;
    }
    if (navigator.userAgent.indexOf("Trident") > -1) {
    // edge 浏览器
    isIE = true;
    }
    return isIE;
    },

    2.导出Excel类型文件
     
      导出excel借鉴了iview-admin 自带的excel操作js(需要npm安装 xlsx)npm install xlsx -s
    需要导出的地方调用excel.export_array_to_excel函数即可

    const param = {
    title: titles,
    key: keys,
    data: this.exportData,
    autoWidth: true,
    filename: this.exportFileName
    };
    excel.export_array_to_excel(param);

    完整excel操作js代码如下 excel.js

    1 /* eslint-disable */
    2 import XLSX from 'xlsx';
    3
    4 function auto_width(ws, data) {
    5 /*set worksheet max width per col*/
    6 const colWidth = data.map(row => row.map(val => {
    7 /*if null/undefined*/
    8 if (val == null) {
    9 return {
    10 'wch': 10
    11 };
    12 }
    13 /*if chinese*/
    14 else if (val.toString().charCodeAt(0) > 255) {
    15 return {
    16 'wch': val.toString().length * 2
    17 };
    18 } else {
    19 return {
    20 'wch': val.toString().length
    21 };
    22 }
    23 }))
    24 /*start in the first row*/
    25 let result = colWidth[0];
    26 for (let i = 1; i < colWidth.length; i++) {
    27 for (let j = 0; j < colWidth[i].length; j++) {
    28 if (result[j]['wch'] < colWidth[i][j]['wch']) {
    29 result[j]['wch'] = colWidth[i][j]['wch'];
    30 }
    31 }
    32 }
    33 ws['!cols'] = result;
    34 }
    35
    36 function json_to_array(key, jsonData) {
    37 return jsonData.map(v => key.map(j => {
    38 return v[j]
    39 }));
    40 }
    41
    42 // fix data,return string
    43 function fixdata(data) {
    44 let o = ''
    45 let l = 0
    46 const w = 10240
    47 for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
    48 o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
    49 return o
    50 }
    51
    52 // get head from excel file,return array
    53 function get_header_row(sheet) {
    54 const headers = []
    55 const range = XLSX.utils.decode_range(sheet['!ref'])
    56 let C
    57 const R = range.s.r /* start in the first row */
    58 for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
    59 var cell = sheet[XLSX.utils.encode_cell({
    60 c: C,
    61 r: R
    62 })] /* find the cell in the first row */
    63 var hdr = 'UNKNOWN ' + C // <-- replace with your desired default
    64 if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
    65 headers.push(hdr)
    66 }
    67 return headers
    68 }
    69
    70 export const export_table_to_excel = (id, filename) => {
    71 const table = document.getElementById(id);
    72 const wb = XLSX.utils.table_to_book(table);
    73 XLSX.writeFile(wb, filename);
    74
    75 /* the second way */
    76 // const table = document.getElementById(id);
    77 // const wb = XLSX.utils.book_new();
    78 // const ws = XLSX.utils.table_to_sheet(table);
    79 // XLSX.utils.book_append_sheet(wb, ws, filename);
    80 // XLSX.writeFile(wb, filename);
    81 }
    82
    83 export const export_json_to_excel = ({
    84 data,
    85 key,
    86 title,
    87 filename,
    88 autoWidth
    89 }) => {
    90 const wb = XLSX.utils.book_new();
    91 data.unshift(title);
    92 const ws = XLSX.utils.json_to_sheet(data, {
    93 header: key,
    94 skipHeader: true
    95 });
    96 if (autoWidth) {
    97 const arr = json_to_array(key, data);
    98 auto_width(ws, arr);
    99 }
    100 XLSX.utils.book_append_sheet(wb, ws, filename);
    101 XLSX.writeFile(wb, filename + '.xlsx');
    102 }
    103
    104 // 导出不带有汉字标题的execel内容
    105 export const export_array_to_excel = ({
    106 key,
    107 data,
    108 title,
    109 filename,
    110 autoWidth
    111 }) => {
    112 const wb = XLSX.utils.book_new();
    113 const arr = json_to_array(key, data);
    114 arr.unshift(title)
    115 const ws = XLSX.utils.aoa_to_sheet(arr);
    116 if (autoWidth) {
    117 auto_width(ws, arr);
    118 }
    119 XLSX.utils.book_append_sheet(wb, ws, filename);
    120 XLSX.writeFile(wb, filename + '.xlsx');
    121 }
    122
    123 // 导出带有汉字标题的execel内容
    124 export const export_array_to_excel2 = ({
    125 key,
    126 data,
    127 title,
    128 filename,
    129 autoWidth
    130 }) => {
    131 const wb = XLSX.utils.book_new();
    132 const arr = json_to_array(key, data);
    133 arr.unshift(key)
    134 arr.unshift(title)
    135 const ws = XLSX.utils.aoa_to_sheet(arr);
    136 if (autoWidth) {
    137 auto_width(ws, arr);
    138 }
    139 XLSX.utils.book_append_sheet(wb, ws, filename);
    140 XLSX.writeFile(wb, filename + '.xlsx');
    141 }
    142
    143 export const read = (data, type) => {
    144 /* if type == 'base64' must fix data first */
    145 // const fixedData = fixdata(data)
    146 // const workbook = XLSX.read(btoa(fixedData), { type: 'base64' })
    147 const workbook = XLSX.read(data, {
    148 type: type
    149 });
    150 const firstSheetName = workbook.SheetNames[0];
    151 const worksheet = workbook.Sheets[firstSheetName];
    152 const header = get_header_row(worksheet);
    153 const results = XLSX.utils.sheet_to_json(worksheet);
    154 return {
    155 header,
    156 results
    157 };
    158 }
    159
    160 export const readesxle = async (file, header, jsointitle) => {
    161 return new Promise(function (resolve, reject) {
    162 const resultdata = {
    163 ErrCode: "9",
    164 ErrText: '导入文件格式不正确。',
    165 Rows: []
    166 }
    167 const fileExt = file.name.split('.').pop().toLocaleLowerCase()
    168 if (fileExt === 'xlsx' || fileExt === 'xls') {
    169 const reader = new FileReader();
    170
    171 const thisXLSX = XLSX;
    172 const thisheader = header;
    173 const thisjsointitle = jsointitle;
    174 reader.readAsArrayBuffer(file)
    175 reader.onloadstart = e => {}
    176 // reader.onprogress = e => {
    177 // this.progressPercent = Math.round(e.loaded / e.total * 100)
    178 // }
    179 reader.onerror = e => {
    180 resultdata.ErrText = '文件读取出错';
    181 resultdata.ErrCode = "1";
    182 resolve(resultdata);
    183 }
    184 reader.onload = e => {
    185 const data = e.target.result
    186 const
    187 workbook = thisXLSX.read(data, {
    188 type: "array"
    189 });
    190 let tempFlag = true;
    191
    192 const firstSheetName = workbook.SheetNames[0];
    193 const worksheet = workbook.Sheets[firstSheetName];
    194 const sheetsheader = get_header_row(worksheet);
    195 const sheetarray = thisXLSX.utils.sheet_to_json(worksheet);
    196
    197 thisheader.forEach((item, index) => {
    198 if (sheetsheader.findIndex(x => x == item) == -1) {
    199 tempFlag = false
    200 }
    201 });
    202 if (tempFlag) {
    203 let sheetresult = [];
    204 for (let i = 0; i < sheetarray.length; i++) {
    205 sheetresult.push({});
    206 for (let j = 0; j < thisheader.length; j++) {
    207 if (sheetarray[i][thisheader[j]] == undefined || sheetarray[i][thisheader[j]] == null)
    208 sheetresult[i][thisjsointitle[j]] = "";
    209 else
    210 sheetresult[i][thisjsointitle[j]] = sheetarray[i][thisheader[j]];
    211 }
    212 }
    213 resultdata.ErrCode = "0";
    214 resultdata.EErrText = "文件导入成功";
    215 resultdata.Rows = sheetresult;
    216 } else {
    217 resultdata.ErrCode = "1";
    218 resultdata.EErrText = "导入文件格式不正确。";
    219 resultdata.Rows = [];
    220 }
    221 resolve(resultdata);
    222 }
    223 } else {
    224 resultdata.ErrCode = "1";
    225 resultdata.ErrText = '文件:' + file.name + '不是EXCEL文件,请选择后缀为.xlsx或者.xls的EXCEL文件。';
    226 resolve(resultdata);
    227 }
    228 })
    229 }
    230
    231 export default {
    232 export_table_to_excel,
    233 export_array_to_excel,
    234 export_json_to_excel,
    235 export_array_to_excel2,
    236 read,
    237 readesxle
    238 }

    3.导出pdf

            最开始使用jspdf 包 把 需要导出的table使用 canvas生成图片,然后把图片插入pdf内,但是这种方式不容易控制,并且生成的pdf清晰度不高,如果直接写pdf又会产生对中文支持的不友好,后采用前后端配合生成pdf文件并导出
    使用blob的方式 后端返回文件流前端 接收并下载

    //思路 webapi返回二进制的文件流 js 通过Blob接收并转换成pdf文件下载
    this.$axios({
    method: "post",
    Prefix: "",
    data: {
    ExCode: "IRAP_RPT_DownLoadFile",
    fileName: this.exportFileName,
    access_token: this.$cookies.get("access_token"),
    valueKeys: valueKeys, //"Product,Version,Description",
    labeNames: labeNames, // "产品,版本,描述",
    tableData: tableData
    }
    // responseType:'blob'
    })
    .then(response => {
    // base64字符串转 byte[]
    var bstr = atob(response.data.FileInfo),
    n = bstr.length,
    u8arr = new Uint8Array(n);
    while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
    }
    // 转blob
    var blob = new Blob([u8arr], {
    type: `application/pdf;charset-UTF-8`
    });

    if (this.MyBrowserIsIE()) {
    // IE10以及Edge浏览器
    var BOM = "uFEFF";
    // 传入 Blob 对象
    navigator.msSaveBlob(blob, `${this.exportFileName}.pdf`);
    } else {
    // 非ie 浏览器
    let content = window.URL.createObjectURL(blob);
    this.createDownLoadClick(content, `${this.exportFileName}.pdf`);
    }
    })
    .catch(err => {
    console.log(err);
    });

  • 相关阅读:
    Vsftp的PASV mode(被动模式传送)和Port模式及 Linux下VsFTP配置全方案
    vsftpd:500 OOPS: vsftpd: refusing to run with writable root inside chroot ()错误的解决方法
    CentOS7.2部署FTP
    Apache与Nginx的优缺点比较
    MySQL存储引擎--MyISAM与InnoDB区别
    CentOS 7下搭建配置SVN服务器
    Remi 安装源
    tmpx75 I2C 温度传感器驱动程序添加
    QT 5.7.0 交叉编译记录
    am335x SGX 移植
  • 原文地址:https://www.cnblogs.com/masterhxh/p/12991694.html
Copyright © 2020-2023  润新知