|
@@ -0,0 +1,62 @@
|
|
|
+import { Ref } from 'vue'
|
|
|
+import { ElMessage, ElTable } from 'element-plus'
|
|
|
+import * as XLSX from 'xlsx'
|
|
|
+import FileSaver from 'file-saver'
|
|
|
+
|
|
|
+interface ExportOptions {
|
|
|
+ tableRef: Ref<InstanceType<typeof ElTable>>
|
|
|
+ sheetName?: string
|
|
|
+ fileName?: string
|
|
|
+ headerRowNumber?: number
|
|
|
+}
|
|
|
+
|
|
|
+type ExportHandler = (option: ExportOptions) => void
|
|
|
+
|
|
|
+export default function useTableExport() {
|
|
|
+ const exportToExcel: ExportHandler = ({
|
|
|
+ tableRef,
|
|
|
+ sheetName = 'sheet1',
|
|
|
+ fileName = '导出表格.xlsx',
|
|
|
+ headerRowNumber = 1,
|
|
|
+ }) => {
|
|
|
+ try {
|
|
|
+ const tableNode = (tableRef.value.$el as HTMLElement).cloneNode(
|
|
|
+ true
|
|
|
+ ) as HTMLElement
|
|
|
+ // 设置了列的fixed属性后会有两个table元素,导出数据会重复,需要去掉一个table
|
|
|
+ const fixedTable = tableNode.querySelector('.el-table__fixed')
|
|
|
+ fixedTable && tableNode.removeChild(fixedTable)
|
|
|
+ // 自定义的表头里包含筛选,直接导出会把筛选的下拉数据也写到表头单元格里,需要先去掉筛选弹出框
|
|
|
+ const tableHeaderCellPopovers = tableNode.querySelectorAll(
|
|
|
+ '.table-header-cell-popover'
|
|
|
+ )
|
|
|
+ tableHeaderCellPopovers.forEach(node => {
|
|
|
+ const childNode = node.querySelector('.el-popover')
|
|
|
+ if (childNode) {
|
|
|
+ node.removeChild(childNode)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ // 生成要导出的xlsx数据对象,raw: true表示不使用excel的格式解析,输出为纯文本,sheet设置xlsx这一页的标题
|
|
|
+ const tableBook = XLSX.utils.table_to_book(tableNode, {
|
|
|
+ raw: true,
|
|
|
+ sheet: sheetName,
|
|
|
+ })
|
|
|
+ const tableBuffer = XLSX.write(tableBook, {
|
|
|
+ bookType: 'xlsx',
|
|
|
+ bookSST: true,
|
|
|
+ type: 'buffer',
|
|
|
+ cellStyles: true,
|
|
|
+ })
|
|
|
+ FileSaver.saveAs(
|
|
|
+ new Blob([tableBuffer], { type: 'application/octet-stream' }),
|
|
|
+ fileName
|
|
|
+ )
|
|
|
+ } catch (error: any) {
|
|
|
+ ElMessage.error(error.message)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ exportToExcel,
|
|
|
+ }
|
|
|
+}
|