前段时间做了个前端导出的功能,自定义导出文件名。把思路和代码分享下,希望对大家有所帮助。
需求:导出页面列表展示的所有数据。
思路:
- 数据量大了,让后端生成excel二进制文件流,前端拿流直接下载;
- 后端不生成,那么轮询调接口返回数据,页面做个等待的进度条,进度条提示语显示已获取条数据/共条数据;获取到所有数据后处理获取数据的格式,使用js-xlsx 下载excel格式文件。
通过浏览器地址栏访问下面地址 https://unpkg.com/xlsx@0.13.3/dist/xlsx.full.min.js,得到的js保存到本地,index.html中引入;如果项目中引入了ts,会报错找不到名称“XLSX,解决办法可参考一下链接 。
如果地址失效了,在github上下载,附链接 https://github.com/SheetJS/sheetjs;最后,要是github上下载不了,可以上我的仓库里拉取代码,附仓库链接https://gitee.com/wanglun945/wl-easy-ui
function updownFileExcel (method: string, url: string, queryParams) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.responseType = 'blob';
xhr.setRequestHeader("token", "*****");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onload = function(e) {
var blob = new Blob([this.response], {type: 'application/octet-stream'});
var fileReader: FileReader = new FileReader();
fileReader.onload = function() {
try {
var r = JSON.parse(fileReader.result as string);
var message = r.message, flag = r.flag;
flag == "0" && Message.error({content: message, duration: 3});
} catch (e) {
var href = URL.createObjectURL(blob);
var fileName = xhr.getResponseHeader('Content-disposition');
var elink = document.createElement('a');
elink.download = fileName ? decodeURI(fileName.split('=')[1].replace(/"/g, '')) : '';
elink.style.display = 'none';
elink.href = href;
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href);
document.body.removeChild(elink);
}
}
fileReader.readAsText(blob);
};
xhr.onerror = function (e) {
Message.error({content:'网络异常,请稍后再试!', duration: 3});
}
xhr.send(JSON.stringify(queryParams));
}
在index.html中引入xlsx.full.min.js后,使用 ExportExcel类,传入三个参数,分别是导出的数据,excel表格文件名,excel文件文件名。data数据类型格式要求 string[][]。
export default class ExportExcel {
data: string[][];
sheetNames: string[];
excelName: string;
constructor (data: string[][], sheetNames: string[], excelName: string) {
this.data = data;
this.sheetNames = sheetNames;
this.excelName = excelName;
}
getSheetsData () {
let sheets = [XLSX.utils.aoa_to_sheet(this.data)];
let blob = this.sheet2blob(sheets, this.sheetNames);
this.updownExcel(blob, this.excelName + ".xlsx");
}
sheet2blob (sheet, sheetName): Blob {
let workbook = {
SheetNames: sheetName,
Sheets: {}
};
sheetName.forEach((n, i) => {
workbook.Sheets[n] = sheet[i]
})
let wbout = XLSX.write(workbook, {bookType: 'xlsx', bookSST: false, type: 'binary'});
let blob = new Blob([this.toBuffer(wbout)], {type: 'application/octet-stream'});
return blob
}
toBuffer (s): ArrayBuffer {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf
}
updownExcel (blob, fileName) {
const aLink = document.createElement('a');
aLink.download = fileName;
aLink.style.display = 'none';
aLink.href = URL.createObjectURL(blob);
document.body.appendChild(aLink);
aLink.click();
URL.revokeObjectURL(aLink.href);
document.body.removeChild(aLink);
}
}
使用demo:
import { defineComponent } from "vue";
import ExportExcel from "./ts/exportExcel"
import { Button } from 'view-ui-plus';
export default defineComponent({
setup() {
let data = [
["标题1", "标题2", "标题3"],
["1-a", "2-a", "3-a"],
["1-b", "2-b", "3-b"]
];
let excel = new ExportExcel(data, ["sheet表名"], "excel名称");
return () => (
<>
<Button onClick={() => excel.getSheetsData()}>导出</Button>
</>
)
}
})