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

javascript csv 导出 前端导出csv文件_javascript csv 导出

 

思路 使用 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);
});