js 前端实现将json格式数组下载到excel(xls、xlsx、csv)表格里
项目需求:上传文件时如果有错误信息,则上传不成功,需要提示用户下载查看错误信息。下载查看错误信息是前端根据后台返回的对象数组放到excel表格中的。
后台返回的数组:
效果如下:
在开始之前先要了解一下几个excel格式的区别:
1.后缀是xls的在2007版本之后的office打开会有提示(xls在wps上打开没有提示)
2.后缀是xlsx在2007版本之后的打开没有提示,但是在2007之前的版本会打不开
3.csv是最通用的一种文件格式,它可以非常容易的被导入各种pc表格及数据库中,此文件中一行即为数据表的一行。生成数据表字段用半角逗号隔开。但是csv不能设置样式。
第一种:生成xls
可粘贴的代码如下:
// 错误信息下载 exportEx = val => { let JSONData = val; let ShowLabel = ['序号', 'imei', '错误原因']; //先转化json let arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData; // 给数组内容换好位置 let finalData = []; arrData.forEach(item => { let obj = { rowNum: item.rowNum, imei: item.imei ? item.imei : '', errorMsg: item.errorMsg, }; finalData.push(obj); }); let excel = '<table>'; //设置表头 let row = '<tr>'; for (let i = 0; i < ShowLabel.length; i++) { row += '<td>' + ShowLabel[i] + '</td>'; } //换行 excel += row + '</tr>'; //设置数据 for (let i = 0; i < finalData.length; i++) { let row = '<tr>'; for (let index in finalData[i]) { let value = finalData[i][index]; if (index === 'imei') { // 当数字超过一定长度就科学计数法可以使用style='mso-number-format:"\@"' // 这个属性指定某单元格的数据格式,避免Excel自动转换格式 row += `<td style='mso-number-format:\"\\@\"'>${value}</td>`; } else { row += '<td>' + value + '</td>'; } } excel += row + '</tr>'; } excel += '</table>'; let excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>"; excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">'; excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel'; excelFile += '; charset=UTF-8">'; excelFile += '<head>'; excelFile += '<!--[if gte mso 9]>'; excelFile += '<xml>'; excelFile += '<x:ExcelWorkbook>'; excelFile += '<x:ExcelWorksheets>'; excelFile += '<x:ExcelWorksheet>'; excelFile += '<x:Name>'; excelFile += '{worksheet}'; excelFile += '</x:Name>'; excelFile += '<x:WorksheetOptions>'; excelFile += '<x:DisplayGridlines/>'; excelFile += '</x:WorksheetOptions>'; excelFile += '</x:ExcelWorksheet>'; excelFile += '</x:ExcelWorksheets>'; excelFile += '</x:ExcelWorkbook>'; excelFile += '</xml>'; excelFile += '<![endif]-->'; excelFile += '</head>'; excelFile += '<body>'; excelFile += excel; excelFile += '</body>'; excelFile += '</html>'; let uri = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(excelFile); let link = document.createElement('a'); link.href = uri; link.style = 'visibility:hidden'; link.download = '错误数据文件.xls'; document.body.appendChild(link); link.click(); document.body.removeChild(link); message.success('下载成功!'); this.setState({ errorMsgVisible: false, }); };
补充:在导出的excel中较长的数字会变成科学计数法展示,为了让过长的数字全部展示出来需要添加样式:style="mso-number-format:'\@';"
在代码中"\@"中的引号和反斜杠都需要添加转义符才能使用。
第二种:生成xlsx
需要引入js-xlsx插件
1.使用npm install xlsx
2.并在文件中引入 import XLSX from 'xlsx';
可复制的代码如下:
// 错误信息下载 exportEx = val => { let JSONData = val; let ShowLabel = ['序号', 'imei', '错误原因']; //先转化json let arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData; // 给数组内容换好位置 let finalData = []; arrData.forEach(item => { let obj = { rowNum: item.rowNum, imei: item.imei ? item.imei : '', errorMsg: item.errorMsg, }; finalData.push(obj); }); let excel = '<table>'; //设置表头 let row = '<tr>'; for (let i = 0; i < ShowLabel.length; i++) { row += '<td>' + ShowLabel[i] + '</td>'; } //换行 excel += row + '</tr>'; //设置数据 for (let i = 0; i < finalData.length; i++) { let row = '<tr>'; for (let index in finalData[i]) { let value = finalData[i][index]; if (index === 'imei') { // 当数字超过一定长度就科学计数法可以使用style='mso-number-format:"\@"' // 这个属性指定某单元格的数据格式,避免Excel自动转换格式 row += `<td style='mso-number-format:\"\\@\"'>${value}</td>`; } else { row += '<td>' + value + '</td>'; } } excel += row + '</tr>'; } excel += '</table>'; // 因为我们这里的数据是string格式的,但是js-xlsx需要dom格式,则先新建一个div然后把数据加入到innerHTML中,在传childNodes[0]即使dom格式的数据 let objE = document.createElement('div'); objE.innerHTML = excel; // 将一个table对象转换成一个sheet对象,raw为true的作用是把数字当成string,身份证不转换成科学计数法 let sheet = XLSX.utils.table_to_sheet(objE.childNodes[0], { raw: true }); this.openDownloadDialog(this.sheet2blob(sheet, '错误数据文件'), '错误数据文件.xlsx'); }; sheet2blob = (sheet, sheetName) => { sheetName = sheetName || 'sheet1'; // 不存在sheetName时使用sheet1代替 let workbook = { SheetNames: [sheetName], Sheets: {}, }; workbook.Sheets[sheetName] = sheet; // 生成excel的配置项 let wopts = { bookType: 'xlsx', // 要生成的文件类型 bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性 type: 'binary', // 二进制格式 }; let wbout = XLSX.write(workbook, wopts); let blob = new Blob([this.s2ab(wbout)], { type: 'application/octet-stream', }); // 字符串转ArrayBuffer return blob; }; s2ab = s => { let buf = new ArrayBuffer(s.length); let view = new Uint8Array(buf); for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff; return buf; }; openDownloadDialog = (url, saveName) => { if (typeof url === 'object' && url instanceof Blob) { url = URL.createObjectURL(url); // 创建blob地址 } let aLink = document.createElement('a'); aLink.href = url; aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效 let event; if (window.MouseEvent) event = new MouseEvent('click'); else { event = document.createEvent('MouseEvents'); event.initMouseEvent( 'click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null ); } aLink.dispatchEvent(event); message.success('下载成功!'); this.setState({ errorMsgVisible: false, }); };
第二种:生成csv
参考链接:https://blog.csdn.net/qq_35493664/article/details/88896638?utm_medium=distribute.pc_relevant_download.none-task-blog-BlogCommendFromBaidu-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-BlogCommendFromBaidu-1.nonecas