目录
一、背景描述
二、功能分析
三、详细开发
1.导出为excel
2.导出为cvs
四、总结
一、背景描述
有些业务常见,例如前端已经获取到表格的所有数据了,并且后端技术人员比较繁忙,总会提出前端分页,前端排序,甚至前端导出数据为excel的需求,所以这个文章就记录一下这个功能怎么实现。实现的功能:导出表格的数据为Excel或cvs,并且前端分页加排序。(不引入第三方库实现导出功能)
二、功能分析
不引入第三方库,所以就前端生成Excel并导出。
前端生成 Excel 文件的方式:首先获取表格数据内容,并对表头进行处理,以确保没有额外的空白单元格。然后,它构建了一个包含表格内容的 HTML 文件,其中包括 Excel 文件所需的一些元信息和样式。接下来,它将该 HTML 文件转换为 Blob 对象,然后通过创建链接并触发下载的方式,实现了文件的下载。
分页排序就比较简单了,只要复制一份表格数据,处理并展示这个数据就行,原始的数据可以用于导出数据。
如下:
三、详细开发
1.导出为excel
首先需要一个表格和导出按钮,如下:
<el-col :span="4" > <el-button type="primary" @click="exportToExcel">导出</el-button> </el-col> <el-table :data="sortedAndPaginatedVerificationTableData" stripe border ref="tableRef" @sort-change="handleSortChange" > <el-table-column prop="age" label="年龄" width="150" sortable> </el-table-column> <el-table-column prop="status" label="状态" width="120" sortable> </el-table-column> <el-table-column prop="message" label="信息" sortable > </el-table-column> </el-table>
复制
接着导出功能的实现,2种方式:
第一种,可忽略不看。
//导出Excel exportToExcel(){ //第一种方式 // 获取表格内容 const excelContent = this.$refs.tableRef.$el.innerHTML; // 处理表头,确保没有额外的空白单元格 const headerElement = document.createElement('div'); headerElement.innerHTML = excelContent; const headerCells = headerElement.querySelectorAll('th'); // 移除最后一个空单元格 if (headerCells.length > 0) { const lastCell = headerCells[headerCells.length - 1]; lastCell.parentNode.removeChild(lastCell); } // 构建 Excel 文件内容 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'> <head> <!--[if gte mso 9]> <xml> <x:ExcelWorkbook> <x:ExcelWorksheets> <x:ExcelWorksheet> <x:Name>{worksheet}</x:Name> <x:WorksheetOptions> <x:DisplayGridlines/> </x:WorksheetOptions> </x:ExcelWorksheet> </x:ExcelWorksheets> </x:ExcelWorkbook> </xml> <![endif]--> <style> td{border: .5pt solid;} </style> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> ${headerElement.innerHTML} </body> </html> `; // 创建 Blob 对象 const blob = new Blob([excelFile], { type: 'application/vnd.ms-excel' }); // 创建链接并触发下载 const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = '表格.xlsx'; // 设置默认文件名 link.style.display = "none"; document.body.appendChild(link); link.click(); window.URL.revokeObjectURL(link.href); document.body.removeChild(link); }
复制
第二种:
//导出Excel exportToExcel(){ //第二种方式 // 获取表格数据 const tableData = this.tableData; // 构建 Excel 文件内容 let excelContent = `<html><head><meta charset="UTF-8"></head><body><table border="1">`; // 添加表头 excelContent += '<tr>'; for (const column of this.$refs.tableRef.columns) { if (column.property) { excelContent += `<th>${column.label}</th>`; } } excelContent += '</tr>'; // 添加表格数据 for (const row of tableData) { excelContent += '<tr>'; for (const column of this.$refs.tableRef.columns) { if (column.property) { excelContent += `<td>${row[column.property]}</td>`; } } excelContent += '</tr>'; } // 构建完整的 Excel 文件内容 excelContent += '</table></body></html>'; // 创建 Blob 对象 const blob = new Blob([excelContent], { type: 'application/vnd.ms-excel' }); // 创建链接并触发下载 const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = '表格.xlsx'; // 设置默认文件名 link.style.display = "none"; document.body.appendChild(link); link.click(); window.URL.revokeObjectURL(link.href); }
复制
这里tableData是表格的原始数据,如果前端已经获取到表格的所有数据,就可以对整个数据进行导出,也就是推荐第二种方式,第一种方式可以对表格样式进行控制,但是数据是考虑当前页面的表格数据,也就是本页数据的导出,所以后来我摒弃了第一种方式,直接使用的第二种方式。
第二种方式的好处:
首先,它获取表格数据并遍历每一行,以构建 Excel 文件内容。
在构建表头时,它遍历了表格的列属性,以获取每一列的标签(label),并添加到表头中,不用控制表格过滤空白单元格,这是第一种的弊端。
2.导出为cvs
let csvContent = "data:text/csv;charset=utf-8,"; csvContent += "年龄,状态,信息\n"; // 添加表头 // 添加数据行 this.verificationTableData.forEach(row => { let csvRow = []; csvRow.push(row.age); csvRow.push(row.status); csvRow.push(row.message); csvContent += csvRow.join(",") + "\n"; }); // 创建下载链接 const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); link.setAttribute("href", encodedUri); link.setAttribute("download", "data.csv"); document.body.appendChild(link); // 触发点击下载 link.click(); document.body.removeChild(link);
复制
3.前端排序和分页
其实我已经写过不少这个功能,为何还要再提,只是因为我在写上面的功能时,无法沿用之前的写法能实现这个功能,所以记录一下。
sortColumn: '', // 存储当前排序的列 sortOrder: '', // 存储当前排序的顺序 computed: { sortedAndPaginatedVerificationTableData() { // console.log("sortedAndPaginatedVerificationTableData") let data = this.tableData.slice(); if(data.length<1){ return [] } // console.log("sortedAndPaginatedVerificationTableData",'com') // 根据排序规则进行排序 if (this.sortColumn && this.sortOrder) { data.sort((a, b) => { const valueA = a[this.sortColumn]; const valueB = b[this.sortColumn]; if (this.sortOrder === 'ascending') { if (valueA > valueB) return 1; if (valueA < valueB) return -1; return 0; } else { if (valueA > valueB) return -1; if (valueA < valueB) return 1; return 0; } }); } // 如果需要分页,则进行分页操作 if (this.page) { const startIndex = (this.page.page - 1) * this.page.limit; const endIndex = this.page.page * this.page.limit; data = data.slice(startIndex, endIndex); } return data; } }, handleSortChange(column, order) { // 更新当前排序的列和顺序 this.sortColumn = column.prop; this.sortOrder = column.order; console.log('change',column,order,this.sortColumn,this.sortOrder ); },
复制
四、总结
使用 HTML 表格和 Blob,将数据动态生成为 HTML 表格,然后通过 HTML5 的 Blob 和 URL.createObjectURL 方法来创建一个链接,最后让用户点击链接下载生成的 Excel 文件。虽然不是真正的 Excel 文件,但可以在大多数情况下满足导出需求。