前言
之前做表格导出性能都是调用后端接口,由后端生成表格链接进行下载的,其实前端也是能够本人生成表格进行下载。
业务场景
在泛滥企业后盾治理中常常会遇到会须要导出页面统计类的表格或者输入打印类的图表,作为前端解决此类需要,我能想到的也就2中解决方向,一个是利用现有的表格类插件,二是利用canvas绘制图片导出。
目前好多企业都有大数据的需要,那未免对一些表格的数据须要进行解决。能够利用xlsx/csv进行解决。
csv表格解决
表格解决最简略的就是csv,对于页面中的table数据做转化解决就能够导出,有肯定的局限性,个性化能力较弱,个性化强的需要能够用XLSX插件解决。
导出csv表格解决
导出csv表格解决最次要的是处理单元格内的换行及字符编码问题解决。
let str = ``let columns = [表格头部列数组]let dataSource = [表格数据数组]columns.forEach((element) => { str += `${表格头部列名},`})/*** , 表格换行* \r\n 单元格换行,外层包裹双引号""*/dataSource.map((item) => { str +=`\r\n${行内容},"${单元格内容}\r\n${单元格内容}\r\n${单元格内容}"`})//encodeURIComponent解决中文乱码let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str)let link = document.createElement('a')link.href = urilink.download = `${表格名称}.csv`document.body.appendChild(link)link.click()document.body.removeChild(link)
canvas图片解决
另外一种解决形式就是canvas解决,目前解决canvas最罕用的插件就是html2canvas了,在前端经常是封装成导图组件应用。
const imageWrapper = 须要绘制的HTML标签const clientWidth = imageWrapper.offsetWidthconst clientHeight = imageWrapper.offsetHeightconst kh = [clientWidth, clientHeight]html2canvas(imageWrapper, { useCORS: true, logging: true}).then((canvas) => { const dataURL = canvas.toDataURL('image/png') const getUrlBase64 = (url, kh) => { return new Promise((resolve) => { let canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') const img = new Image() img.crossOrigin = 'Anonymous' // 容许跨域 img.src = url img.onload = () => { canvas.height = kh[1] canvas.width = kh[0] ctx.drawImage(img, 0, 0, kh[0], kh[1]) const dataURL = canvas.toDataURL('image/png') canvas = null resolve(dataURL) } }) } getUrlBase64(dataURL, kh).then((base64) => { // 下载 const link = document.createElement('a') link.href = base64 link.download = `Loan Statement.png` link.click() // 新页面关上 let arr = base64.split(',') //去掉base64格局图片的头部 let bstr = atob(arr[1]) //atob()办法将数据解码 let leng = bstr.length let u8arr = new Uint8Array(leng) while (leng--) { u8arr[leng] = bstr.charCodeAt(leng) //返回指定地位的字符的 Unicode 编码 } window.open(window.URL.createObjectURL(new File([u8arr], `${图片名称}`, { type: 'image/png' }))) })})
针对大数据表格解决类的需要
这类需要次要是针对大量表格须要对合乎正则的数据批量替换成大数据统计须要的一些标识。就须要辨认以后的表格内容,而后对数据进行解析再替换,最初导出,以下给出的是须要人为解决的的单个计划,感兴趣的能够集成为主动批量解决。利用的是xlsx插件解决导入的数据解析,及导出
const isUTF8(bytes)=> { var i = 0 while (i < bytes.length) { if ( // ASCII bytes[i] == 0x09 || bytes[i] == 0x0a || bytes[i] == 0x0d || (0x20 <= bytes[i] && bytes[i] <= 0x7e) ) { i += 1 continue } if ( // non-overlong 2-byte 0xc2 <= bytes[i] && bytes[i] <= 0xdf && 0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xbf ) { i += 2 continue } if ( // excluding overlongs (bytes[i] == 0xe0 && 0xa0 <= bytes[i + 1] && bytes[i + 1] <= 0xbf && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf) || // straight 3-byte (((0xe1 <= bytes[i] && bytes[i] <= 0xec) || bytes[i] == 0xee || bytes[i] == 0xef) && 0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xbf && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf) || // excluding surrogates (bytes[i] == 0xed && 0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x9f && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf) ) { i += 3 continue } if ( // planes 1-3 (bytes[i] == 0xf0 && 0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xbf && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf && 0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xbf) || // planes 4-15 (0xf1 <= bytes[i] && bytes[i] <= 0xf3 && 0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xbf && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf && 0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xbf) || // plane 16 (bytes[i] == 0xf4 && 0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8f && 0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xbf && 0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xbf) ) { i += 4 continue } return false } return true}
readFileType(file) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = function (evt) { resolve(isUTF8(new Uint8Array(evt.target.result))) } reader.readAsArrayBuffer(file) })}
let reader = new FileReader()let isCSV = file.name.split('.').pop().toLowerCase() === 'csv'if (isCSV) { reader.readAsArrayBuffer(file) const isUTF8 = await _this.readFileType(file) isUTF8 ? reader.readAsText(file) : reader.readAsText(file, 'gbk')} else { reader.readAsBinaryString(file)}reader.onload = function (e) { let data = e.target.result let workbook = XLSX.read(data, { type: 'binary' }) let sheetNames = workbook.SheetNames // 工作表名称汇合 let resultData = [] sheetNames.forEach((name) => { let worksheet = workbook.Sheets[name] // 只能通过工作表名称来获取指定工作表 resultData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) }) // 再对resultData数据json进行转换成表格所需数据进行展现}
// 导出xlxs表格const data = 表格数据let option = {} //option代表的就是excel文件let dataTable = [] //excel文件中的数据内容data.forEach((element) => { element.author = this.XLSXAuthor delete element.regExpMatch})let len = data.lengthif (len) { for (let i = 0; i < len; i++) { let row = data[i] let obj = {} for (let key in row) { if (typeof row[key] === 'object') { let arr = row[key] obj[key] = arr.map((item) => (typeof item === 'object' ? item.label : item)).join(',') } else { obj[key] = row[key] } } dataTable.push(obj) //设置excel中每列所获取的数据源 }}let tableKeys = Object.keys(dataTable[0])option.fileName = localStorage.getItem('XLSXFileName') //excel文件名称option.datas = [ { sheetData: dataTable, //excel文件中的数据源 sheetName: localStorage.getItem('XLSXFileName'), //excel文件中sheet页名称 sheetFilter: tableKeys, //excel文件中需显示的列数据 sheetHeader: tableKeys //excel文件中每列的表头名称 }]let toExcel = new ExportJsonExcel(option) //生成excel文件toExcel.saveExcel() //下载excel文件
这个案例是导入xlsx/csv表格,拿到表格数据再进行展现在页面,人为批改后再进行导出xlsx,如果想再深刻一点,能够应用node编写一个转换表格数据的服务。这个就须要配合一些大数据的一些规定提取去实现。
结语
本次分享的都是在工作中遇到的表格的一些解决办法,集体的一些浅见,写的不好请轻喷!!!!欢送一起交换!!!!
前端表格解决知多少?