前端页面

导出Excel效果图

参数
- 必传参数:headers表头(如图第二行),excelData表格数据
- 可传参数:excelTitle标题(如图第一行), fileName文件名称, colWidth每列宽度, rowHeight每行高度, merges单元格合并(如图合并标题)
安装
pnpm install -xlsx
pnpm install xlsx-js-style
代码
<script setup lang="ts">
import { exportExcel } from "@/utils/excel";
const option = {
height: 400,
selection: true,
index: true,
indexLabel: "序号",
indexWidth: "100",
showSummary: true,
editBtn: false,
addBtn: false,
column: [
{
label: "姓名",
prop: "userName",
fixed: true
},
{
label: "性别",
prop: "sex"
},
{
label: "电话",
prop: "phone"
},
{
label: "角色",
prop: "role"
},
{
label: "状态",
prop: "status"
}
]
};
const data = [
{ id: "1", userName: "张三", sex: "男", phone: "123455667", role: "管理员", status: "0" },
{ id: "2", userName: "张三", sex: "男", phone: "123455667", role: "管理员", status: "0" },
{ id: "3", userName: "张三", sex: "男", phone: "123455667", role: "管理员", status: "0" }
];
const headers = option.column.map(item => {
return {
key: item.prop,
title: item.label
};
});
const fileName = ref();
const title = ref();
function exportTableData() {
const excelOptions = {
headers: headers,
excelData: data,
excelTitle: title.value,
fileName: fileName.value
};
exportExcel(excelOptions);
}
</script>
<template>
<div class="user">
<h3>导出表格数据Excel</h3>
<div style="display: flex">
<span>文件名称</span><el-input v-model="fileName" style="width: 240px" placeholder="请输入导出的文件名称" /><br />
<span>Excel表格标题</span><el-input v-model="title" style="width: 240px" placeholder="请输入Excel表格标题" />
</div>
<el-button @click="exportTableData">导出</el-button>
<avue-crud :data="data" :option="option"></avue-crud>
</div>
</template>
<style lang="scss" scoped>
.user {
padding: 20px;
background-color: white;
height: 94%;
}
</style>
import XLSX from "xlsx-js-style";
export interface excelOptions {
excelTitle?: any[];
fileName?: string;
headers: any;
merges?: any[];
excelData: any[];
colWidth?: any[];
rowHeight?: any[];
}
export function exportExcel(options: excelOptions) {
let { excelTitle, headers, excelData, fileName, colWidth, rowHeight, merges } = options;
excelTitle = excelTitle ? [excelTitle] : ["Excel标题"];
fileName = fileName || "导出表格数据";
colWidth =
colWidth ||
headers.map(item => {
return {
wpx: 50
};
});
rowHeight =
rowHeight ||
headers.map(item => {
return {
hpx: 30
};
});
merges = merges || [
{ s: { r: 0, c: 0 }, e: { r: 0, c: (headers.length - 1) as number } }
];
const cellStyle = {
font: {
bold: true,
sz: 12,
name: "宋体"
},
alignment: {
vertical: "center",
horizontal: "center"
},
border: {
top: { style: "thin", color: { rgb: "FF000000" } },
bottom: { style: "thin", color: { rgb: "FF000000" } },
left: { style: "thin", color: { rgb: "FF000000" } },
right: { style: "thin", color: { rgb: "FF000000" } }
}
};
const headerStyle = {
...cellStyle,
fill: {
fgColor: { rgb: "87CEEB" }
}
};
const excel_title = excelTitle;
const excel_headers_key = headers.map((item: any) => item.key);
const excel_headers_title = headers.map((item: any) => item.title);
const excel_data = excelData.map((item: []) => {
let arr: any[] = [];
excel_headers_key.forEach((key: any) => {
arr.push(item[key]);
});
return arr;
});
excel_data.unshift(excel_title,excel_headers_title);
let exc = XLSX.utils.book_new();
let exc_data = XLSX.utils.aoa_to_sheet(excel_data);
exc_data["!cols"] = colWidth;
exc_data["!rows"] = rowHeight;
exc_data["!merges"] = merges;
excel_data.forEach((row: any, rowIndex: number) => {
row.forEach((cell: any, colIndex: number) => {
const cellRef = XLSX.utils.encode_cell({ c: colIndex, r: rowIndex });
if (rowIndex === 0) {
exc_data[cellRef].s = headerStyle;
} else {
exc_data[cellRef].s = cellStyle;
}
});
});
XLSX.utils.book_append_sheet(exc, exc_data, fileName);
XLSX.writeFile(exc, fileName + ".xlsx", { bookType: "xlsx", type: "buffer" });
}