导出excel文件最简单方案,前端生成文件使用xlsx
插件,解析后端接口文件流使用axios
建立utils/excel.ts
并将该文件代码复制进去
import { ElMessage } from 'element-plus';
import * as XLSX from 'xlsx';
export interface HandleExportExcelType {
header: string[]; // header的名称 如:['姓名', '性别', '年龄']
value: string[]; // list的数据key 如:['name', 'sex', 'age']
list: Record<string, any>[]; // 数据源 如:[{name: '张三', sex: '男', age: 18}]
fileName?: string;
workbookName?: string;
}
/**
* 导出excel文件-导出前记得先处理好后端返回的字段转成中文先
* @param event
*/
export function handleExportExcel(event: HandleExportExcelType) {
const data: Record<string, any>[] = [];
const { header, list, value } = event;
if (header.length !== value.length) {
console.error('请确认header和value数组长度一致');
} else if (list.length === 0) {
ElMessage.warning('暂无数据!');
} else {
for (let index = 0; index < list.length; index++) {
const element = list[index];
const obj: Record<string, any> = {};
for (let hIndex = 0; hIndex < header.length; hIndex++) {
const hElement = header[hIndex];
const data = value[hIndex]; // 长度一致所以可以直接使用header的index
obj[hElement] = element[data];
}
data.push(obj);
}
const ws = XLSX.utils.json_to_sheet(data); // 新建空workbook,然后加入worksheet
// ws['!cols'] = [{ wch: 10 }, { wch: 30 }, { wch: 25 }]; // 设置每列的列宽,10代表10个字符,注意中文占2个字符
const wb = XLSX.utils.book_new(); // 新建book
XLSX.utils.book_append_sheet(wb, ws, event.workbookName || '数据详情'); // 生成xlsx文件(book,sheet数据,sheet命名)
XLSX.writeFile(wb, event.fileName || '导出.xlsx'); // 写文件(book,xlsx文件名称)
}
}
axios下载文件功能,建立utils/down-file.ts
import axios from 'axios';
import { ElMessage } from 'element-plus';
/**
* 导出后端生成url下载文件 如果该方案不适用则可以采用前端方案
* @link https://blog.csdn.net/weixin_42246659/article/details/118936132?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164542407116781683996201%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164542407116781683996201&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-118936132.pc_search_result_positive&utm_term=vue3+xlsx&spm=1018.2226.3001.4187
* @param data
*/
export function downloadExportFile(data: { url: string; params?: Record<string, any>; fileName?: string }): Promise<void> {
// // 裁剪apiUrl最后一个/ 吧token添加上
const apiUrl = data.url[0] === '/' ? data.url.substring(1) : data.url;
const fileUrl = 'http://xxx.com/' + apiUrl;
return new Promise((resolve) => {
axios
.get<Blob>(fileUrl, {
params: data?.params,
headers: {
'token': 'token',
},
responseType: 'blob',
})
.then((res) => {
if (res.status === 200) {
console.log(res.data);
const href = window.URL.createObjectURL(res.data); // 创建下载的链接
// 获取响应头的文件命名 Content-Disposition: attachment;filename=xxx
const fileName = data?.fileName || res.headers['content-disposition'].split('filename=')[1];
createDownloadElement(href, decodeURIComponent(fileName));
window.URL.revokeObjectURL(href); // 释放掉blob对象
} else {
ElMessage.error('导出异常!');
}
resolve();
})
.catch((error) => {
console.error('导出失败!', error);
ElMessage.error('导出失败!');
resolve();
});
});
}
/**
* 下载JSON
* @param data
* @param fileName
*/
export function downloadJSON(data: any, fileName: string) {
const blob = new Blob([JSON.stringify(data)]);
const href = window.URL.createObjectURL(blob); // 创建下载的链接
createDownloadElement(href, `${fileName}-${new Date().getTime()}.json`);
window.URL.revokeObjectURL(href); // 释放掉blob对象
}
/**
* 创建a标签下载文件
* @param url
* @param name
*/
function createDownloadElement(url: string, name: string) {
console.log(url, name);
const downloadElement = document.createElement('a');
downloadElement.href = url;
downloadElement.download = name; // 下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); // 点击下载
document.body.removeChild(downloadElement); // 下载完成移除元素
}
vue3中使用
<template>
<el-button @click="handleExport">导 出</el-button>
<el-button @click="handleExportAxios">导 出</el-button>
</template>
<script lang="ts">
import { handleExportExcel } from '@/utils/excel';
import { downloadExportFile } from '@/utils/down-file';
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const handleExport = () => {
handleExportExcel({
header: ['姓名', '性别', '年龄'],
value: ['name', 'sex', 'age'],
list: [{ name: '张三', sex: '男', age: 18 }],
});
};
const handleExportAxios = () => {
downloadExportFile({
url: 'xxxx/xxx',
fileName: '下载.xlsx',
});
};
return {
handleExport,
handleExportAxios
};
},
});
</script>