2023.9.1今天我学习了如何使用el-table实现前端的导出功能,该方法的好处有无论你的el-table长什么样子,导出之后就是什么样子。
1.安装三个插件
npm install file-save
npm install xlsx
npm install xlsx-style
2.创建Export2Excel.js
// 根据dom导出表格import { saveAs } from 'file-saver'import * as XLSX from 'xlsx'import * as XLSXStyle from "xlsx-style";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;}export function exportToExcel(idSelector, fileName, titleNum = 1) { // 设置导出的内容是否只做解析,不进行格式转换 false:要解析, true:不解析 const xlsxParam = { raw: true } let table = document.querySelector(idSelector).cloneNode(true) // 因为element-ui的表格的fixed属性导致多出一个table,会下载重复内容,这里删除掉 if (table.querySelector('.el-table__fixed-right')) { table.removeChild(table.querySelector('.el-table__fixed-right')) } if (table.querySelector('.el-table__fixed')) { table.removeChild(table.querySelector('.el-table__fixed')) } const wb = XLSX.utils.table_to_book(table, xlsxParam) let range = XLSX.utils.decode_range(wb.Sheets['Sheet1']['!ref']) let cWidth = [] for (let C = range.s.c; C < range.e.c; ++C) { //SHEET列 let len = 100 //默认列宽 let len_max = 400 //最大列宽 for (let R = range.s.r; R <= range.e.r; ++R) { //SHEET行 let cell = { c: C, r: R } //二维 列行确定一个单元格 let cell_ref = XLSX.utils.encode_cell(cell) //单元格 A1、A2 if (wb.Sheets['Sheet1'][cell_ref]) { // if (R == 0){ if (R < titleNum) { wb.Sheets['Sheet1'][cell_ref].s = { //设置第一行单元格的样式 style alignment: { horizontal: 'center', vertical: 'center' } } } else { wb.Sheets['Sheet1'][cell_ref].s = { alignment: { horizontal: 'center', vertical: 'center' } } } //动态自适应:计算列宽 let va = JSON.parse(JSON.stringify(wb.Sheets['Sheet1'][cell_ref].v)) var card1 = JSON.parse(JSON.stringify(va)).match(/[\u4e00-\u9fa5]/g) //匹配中文 var card11 = '' if (card1) { card11 = card1.join('') } var card2 = JSON.parse(JSON.stringify(va)).replace(/([^\u0000-\u00FF])/g, '') //剔除中文 let st = 0 if (card11) { // st += card11.length * 16 //中文字节码长度 st += card11.length * 20 //中文字节码长度 } if (card2) { // st += card2.length * 8 //非中文字节码长度 st += card2.length * 10 //非中文字节码长度 } if (st > len) { len = st } } } if (len > len_max) {//最大宽度 len = len_max } cWidth.push({ 'wpx': len }) //列宽 } wb.Sheets['Sheet1']['!cols'] = cWidth const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' }) try { saveAs(new Blob([s2ab(wbout)], { type: '' }), `${fileName}.xlsx`) } catch (e) { if (typeof console !== 'undefined') { console.log(e, wbout) } } return wbout}
3.按需引入
<template> <div> <el-table id='table'> //形式一 <el-table-column> <template> <span>可以用插槽形式</span> </template> </el-table-column> //形式二 <el-table-column lable=可以用这种形式' prop='xxx'/> //形式三(不可用) <el-table-column> <template> <el-input v-model=''/>//该方式无法识别到 </template> </el-table-column> </el-table>//给表格一个id <el-button @click='demo'>导出</el-button> </div></template><script>import { exportToExcel } from '@/Export2Excel'export default{ data(){ return{} }, methods:{ demo(){ exportToExcel('#table', '导出名称')//id选择器,导出名称,调用这个方法就可以了 } }}</script>
4.vue.config.js引入
//在这个方法里面 configureWebpack: { name: name, resolve: { alias: { '@': resolve('src') } }, plugins: [ // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 new CompressionPlugin({ cache: false, // 不启用文件缓存 test: /\.(js|css|html)?$/i, // 压缩文件格式 filename: '[path].gz[query]', // 压缩后的文件名 algorithm: 'gzip', // 使用gzip压缩 minRatio: 0.8 // 压缩率小于1才会压缩 }) ], //加入这三行 externals: [{ './cptable': 'var cptable' }] },
效果:
扩展:
当我们会出现这样的表格需求时,如果只是用v-if判断,导出来会全部也有,因为我们只做了v-if的判断
实现代码如下:
<span v-if="index===0">{{scope.row.xxxx}}</span>//如果是第一行就显示值<span v-else></span>//如果不是就为空
这样就可以防止只需要第一个行数据的时候其他还会显示的问题。