安装
npm install xlsx file-saver
基础用法
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
const data = [
{ name: '张三', age: 18, city: '北京' },
{ name: '李四', age: 20, city: '上海' }
]
const ws = XLSX.utils.json_to_sheet(data)
const wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
const buf = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })
const blob = new Blob([buf], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
saveAs(blob, '数据.xlsx')
封装 useExportExcel
// useExportExcel.js
import * as XLSX from 'xlsx'
import { saveAs } from 'file-saver'
import { ref } from 'vue'
export function useExportExcel() {
const exporting = ref(false)
const exportExcel = (data = [], fileName = '数据表', headerMap = {}) => {
if (!data.length) return
exporting.value = true
try {
// 按 headerMap 重命名列
const exportData = data.map(row => {
const newRow = {}
Object.keys(row).forEach(key => {
newRow[headerMap[key] || key] = row[key]
})
return newRow
})
const ws = XLSX.utils.json_to_sheet(exportData)
const wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
const buf = XLSX.write(wb, { bookType: 'xlsx', type: 'array' })
const blob = new Blob([buf], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
saveAs(blob, `${fileName}.xlsx`)
} finally {
exporting.value = false
}
}
const exportSelected = (allData, selectedRows, fileName, headerMap = {}) => {
exportExcel(selectedRows?.length ? selectedRows : allData, fileName, headerMap)
}
return { exporting, exportExcel, exportSelected }
}
配合 Element Plus el-table 使用
<template>
<el-button :loading="exporting" @click="onExportAll">导出全部</el-button>
<el-button :loading="exporting" @click="onExportSelected">导出选中</el-button>
<el-table :data="tableData" @selection-change="selectedRows = $event">
<el-table-column type="selection" />
<el-table-column prop="name" label="姓名" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="city" label="城市" />
</el-table>
</template>
<script setup>
import { ref } from 'vue'
import { useExportExcel } from './useExportExcel'
const tableData = ref([
{ name: '张三', age: 18, city: '北京' },
{ name: '李四', age: 20, city: '上海' }
])
const selectedRows = ref([])
const { exporting, exportExcel, exportSelected } = useExportExcel()
const headerMap = { name: '姓名', age: '年龄', city: '城市' }
const onExportAll = () => exportExcel(tableData.value, '用户列表', headerMap)
const onExportSelected = () => exportSelected(tableData.value, selectedRows.value, '选中用户', headerMap)
</script>
导出 DOM table
如果页面已有 <table> 元素,不需要操作数据,直接从 DOM 生成:
const table = document.getElementById('myTable')
const wb = XLSX.utils.table_to_book(table)
XLSX.writeFile(wb, 'table.xlsx')
大数据后端流式下载
超过 5 万行时前端导出会明显卡顿(浏览器内存限制),推荐后端生成流式 Excel:
const exportExcelFromServer = async (params) => {
const res = await axios({
url: '/api/export',
method: 'get',
params,
responseType: 'blob'
})
const blob = new Blob([res.data])
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = '数据.xlsx'
link.click()
URL.revokeObjectURL(link.href)
}
后端(Laravel + Maatwebsite\Excel):
return Excel::download(new UserExport(), 'users.xlsx');