工具类:
export interface TableHeadInfo<T> {
key: T;
label: string
}
export interface ExportExcelParams<T extends { [key: string]: any }> {
headInfo: TableHeadInfo<keyof T>[],
data: T[],
tableName: string
}
export interface FormatCTX {
worksheet: string | 'Worksheet';
table: string
}
export class ExportExcel<T extends { [key: string]: any }> {
private uri: string = 'data:application/vnd.ms-excel;base64,';
private template: string = `<html><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]--></head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><body><table border="1">{table}</table></body></html>`;
constructor() { };
public export(params: ExportExcelParams<T>) {
const { headInfo, data, tableName } = params;
const head: string = this.getHead(headInfo);
const body: string = this.getBody(headInfo, data);
const table: string = head + body
this.downloadExcel(table, tableName)
};
//导出excel
private downloadExcel(tableData: string, tableName: string) {
const ctx: FormatCTX = {
worksheet: tableName || 'Worksheet',
table: tableData
}
let a: HTMLAnchorElement = document.createElement("a");
a.href = this.uri + this.base64(this.format(ctx))
a.download = tableName || 'excel' + '.xlsx';
a.click();
}
//获取table头部信息
private getHead(headInfo: TableHeadInfo<keyof T>[]): string {
let head = '<tr>';
headInfo.forEach((item, index) => {
head += `<th style="width:200px;text-align:center;font-size:18px">${item.label}</th>`
if (index == headInfo.length - 1) {
head += "</tr>"
}
})
return head;
};
//获取table内容
private getBody(headInfo: TableHeadInfo<keyof T>[], data: ExportExcelParams<T>["data"]): string {
let body: string = "";
data.forEach((item) => {
headInfo.forEach((hitem, hindex) => {
if (hindex == 0) {
body += '<tr>'
}
body += `<td style="text-align:center;font-size:18px;mso-number-format:'\@'">${(item[hitem.key] || item[hitem.key] === 0) ? item[hitem.key].toString() : ''}</td>`
if (hindex == headInfo.length - 1) {
body += "</tr>"
}
})
})
return body;
};
private format(ctx: FormatCTX): string {
return this.template.replace(/{(\w+)}/g, function (m, p) {
return ctx[p as keyof (FormatCTX)] as string;
})
};
//转base64
private base64(str: string): string {
//API 将字符串转换为一个 Uint8Array 类型的数据
const encoder = new TextEncoder();
const data = encoder.encode(str);
//btoa 函数只针对 Latin1 字符集
return btoa(String.fromCharCode(...data))
};
}
使用示例:
interface Data {
x: string,
y: string
}
let exportExcel = new ExportExcel<Data>()
exportExcel.export({
headInfo: [{ key: "x", label: "X" }, { key: "y", label: "Y" }],
data: [{ x: "1", y: "2" }],
tableName: "坐标位置"
})