问题描述:后端返回数据原先返回是多个json文件的压缩包二进制文件流,前端直接下载二进制文件流。但是客户要求下载excel类型文件。
解决方案:前端拿到表格的json数据转换成对应table的html字符串,使用插件js-xlsx。
给个链接,
import * as XLSX from 'xlsx' // JSONData为导出的json数据,fileName为导出的文件名,title为导出的第一行标题,filter为过滤字段 export default (JSONData, FileName, title, filter)=>{ if (!JSONData) { return } // 转化json为object //var arrData = typeof JSONData !== 'object' ? JSON.parse(JSONData) : JSONData let excel = '<table class="htmlTable">' for(let i =0;i<JSONData.length;i++){ const rowData = JSONData[i] const rowDatakeyList = Object.keys(rowData) let value = 0 for(let j=0;j<rowDatakeyList.length;j++){ const item = rowData[rowDatakeyList[j]] if(item.value){ value++ } } if(!value){ continue } let row = '<tr>' for(let j=0;j<rowDatakeyList.length;j++){ const item = rowData[rowDatakeyList[j]] row=row+`<td style="text-align:center;vertical-align:middle">${item.value||''}</td>` } excel =`${excel}${row}</tr>` } excel = excel +'</table>' var objE = document.createElement('div') // 因为我们这里的数据是string格式的,但是js-xlsx需要dom格式,则先新建一个div然后把数据加入到innerHTML中,在传childNodes[0]即使dom格式的数据 objE.innerHTML = excel var sheet = XLSX.utils.table_to_sheet(objE.childNodes[0], { raw: true })// 将一个table对象转换成一个sheet对象,raw为true的作用是把数字当成string,身份证不转换成科学计数法 return sheet2blob(sheet, FileName) // 因为我需要多个excel构成的压缩包,所以我在这里直接返回二进制文件流 // openDownloadDialog(sheet2blob(sheet, FileName), FileName + '.xlsx') // 若想下载excel文件使用这行 } // 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载 function sheet2blob(sheet, sheetName) { // sheetName是文件名,不能超过31.这个是插件内部限制 sheetName = sheetName || 'sheet1' // 不存在sheetName时使用sheet1代替 var workbook = { SheetNames: [sheetName], Sheets: {} } workbook.Sheets[sheetName] = sheet // 生成excel的配置项 workbook.Sheets[sheetName]['!cols'] = [ //生成excel的列的宽度 // { wch: 20 }, // 第一列 // { wch: 40 }, // 第二列 // { wch: 80 } // 第三列 ] var wopts = { bookType: 'xlsx', // 要生成的文件类型 bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性 type: 'binary' // 二进制格式 } var wbout = XLSX.write(workbook, wopts) var blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' }) // 字符串转ArrayBuffer 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 } return blob } // 下载的方法 function openDownloadDialog(url, saveName) { if (typeof url === 'object' && url instanceof Blob) { url = URL.createObjectURL(url) // 创建blob地址 } var aLink = document.createElement('a') aLink.href = url aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效 var 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) }
拿到二进制文件流后,需要放在一起进行压缩
使用的是这两个插件 jszip
file-saver
/** * 外部调用下载excel表格 */ downLoadExcelByFormOcr() { const zip = new JSzip() for(let i=0;i<this.picData.length;i++){ const item = this.picData[i] let subName = item.dataName.substring(0, item.dataName.lastIndexOf(".")); // 设置文件名 const file = JSONToExcelConvertor(this.formatTableResult(item), `tempFile_${i+1}`);
// 这个就是拿到上个方法返回的二进制文件流,第二个参数是随便写的文件名,为了过jsexcel的文件名(这个文件名用不到,所以随便写的) zip.file(`${subName}.xlsx`, file)
// 当把文件放进压缩包中时,又设置了一遍文件名,这个是最后生效的文件名 } zip.generateAsync({ type: 'blob' }).then(content2 => { saveAs(content2, 'excelFile.zip') // 下载,content2 是方法返回压缩包数据,第二个参数是压缩包名称
}) },
这三个函数都是将json转格式为了方便后面方法生成html字符串。不用理会
标签:sheet,zip,文件名,excel,sheetName,json,var From: https://www.cnblogs.com/cbb-web/p/17914667.html