安装插件
xlsx-js-style相当于xlsx的生基本,xlsx导出不能对单元格样式进行调整
安装了xlsx-js-style 就不需要安装 xlsx了
npm install xlsx-js-style
引入插件
import XLSXS from 'xlsx-js-style'
示例数据
// 示例数据 data
const data = [
{ transactionDate: '2024-01-01', '17lowerPriceDisplay': 100, '17upperPriceDisplay': 150, '17averagePriceDisplay': 120, xxxxx2: '12', xxxxx1: '11' },
{ transactionDate: '2024-01-02', '17lowerPriceDisplay': 110, '17upperPriceDisplay': 160, '17averagePriceDisplay': 125, xxxxx2: '12', xxxxx1: '11' },
]
// 示例 表格列
const columns = [
{ title: '日期', dataIndex: 'transactionDate', width: 100, fixed: 'left' },
{ title: 'ssss', dataIndex: '17lowerPriceDisplay', colSpan: 0, width: 120 },
{ title: 'ssss', dataIndex: '17upperPriceDisplay', colSpan: 3, width: 120 },
{ title: 'ssss', dataIndex: '17averagePriceDisplay', colSpan: 0, width: 120 },
{ title: 'xxxxx', dataIndex: 'xxxxx1', colSpan: 0, width: 120 },
{ title: 'xxxxx', dataIndex: 'xxxxx2', colSpan: 0, width: 120 },
]
表格头
表格头对应的key
const headers = columns.map(item => { return item.title })
const fields = columns.map(item => { return item.dataIndex })
数据转换 二维数组
let dataCopy = data.map((obj) => {
return fields.map((field) => {
return obj[field]
})
})
if (headers.length > 0) {
dataCopy.splice(0, 0, headers)
} else {
dataCopy.splice(0, 0, fields)
}
生成工作表
const ws = XLSX.utils.aoa_to_sheet(dataCopy) // 创建工作表
单元格格式设置
// 设置列宽度自适应
const colWidths = columns.map(col => col.width || 100);
ws['!cols'] = colWidths.map(width => ({ wpx: width }));
// 设置内容居中
// 设置单元格公共样式
let borderAll = { //单元格外侧框线
top: {
style: 'thin',
},
bottom: {
style: 'thin',
},
left: {
style: 'thin',
},
right: {
style: 'thin',
}
};
for (let key in ws) {
// 单元格公共样式设置
if (ws[key] instanceof Object) {
ws[key].s = {
border: borderAll,
alignment: {
horizontal: 'center', //水平居中对齐
vertical: 'center',//垂直居中
wrapText: 1,//自动换行
},
// fill: { //背景色
// fgColor: { rgb: 'dbf3f2' }
// },
font: {
sz: 12,//单元格中字体的样式与颜色设置
color: {
rgb: '000000'
}
},
bold: true,
numFmt: 0
}
}
}
动态合并列 导出excel
// 记录合并单元格的信息
const merges = [];
let startCol = 0;
let currentTitle = columns[0].title;
// 确定合并区域
columns.forEach((col, index) => {
if (col.title === currentTitle) {
// 继续合并
} else {
if (index - startCol > 1) {
// 如果需要合并的区域大于1列
merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: index - 1 } });
}
// 更新标题和起始列
currentTitle = col.title;
startCol = index;
}
});
// 处理最后一个区域
if (columns.length - startCol > 1) {
merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: columns.length - 1 } });
}
// 应用合并区域到工作表
ws['!merges'] = merges;
// 创建工作簿
const wb = XLSX.utils.book_new();
console.log(wb, '创建工作簿')
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
// 导出 Excel 文件
XLSX.writeFile(wb, 'export.xlsx');
完整代码 vue3
<template>
<div>
<button @click="exportExcel">导出 Excel</button>
</div>
</template>
<script>
// import * as XLSX from 'xlsx'
import XLSX from 'xlsx-js-style'
export default {
methods: {
exportExcel() {
// 示例数据
const data = [
{ transactionDate: '2024-01-01', '17lowerPriceDisplay': 100, '17upperPriceDisplay': 150, '17averagePriceDisplay': 120, xxxxx2: '12', xxxxx1: '11' },
{ transactionDate: '2024-01-02', '17lowerPriceDisplay': 110, '17upperPriceDisplay': 160, '17averagePriceDisplay': 125, xxxxx2: '12', xxxxx1: '11' },
]
// 列配置
const columns = [
{ title: '日期', dataIndex: 'transactionDate', width: 100, fixed: 'left' },
{ title: 'ssss', dataIndex: '17lowerPriceDisplay', colSpan: 0, width: 120 },
{ title: 'ssss', dataIndex: '17upperPriceDisplay', colSpan: 3, width: 120 },
{ title: 'ssss', dataIndex: '17averagePriceDisplay', colSpan: 0, width: 120 },
{ title: 'xxxxx', dataIndex: 'xxxxx1', colSpan: 0, width: 120 },
{ title: 'xxxxx', dataIndex: 'xxxxx2', colSpan: 0, width: 120 },
]
const fields = columns.map(item => { return item.dataIndex })
const headers = columns.map(item => { return item.title })
let dataCopy = data.map((obj) => {
return fields.map((field) => {
return obj[field]
})
})
if (headers.length > 0) {
dataCopy.splice(0, 0, headers)
} else {
dataCopy.splice(0, 0, fields)
}
// 生成工作表
// const ws = XLSX.utils.json_to_sheet(data, { header: columns.map(col => col.dataIndex) });
const ws = XLSX.utils.aoa_to_sheet(dataCopy) // 创建工作表
// 设置列宽度自适应
const colWidths = columns.map(col => col.width || 100);
ws['!cols'] = colWidths.map(width => ({ wpx: width }));
// 设置内容居中
// 设置单元格公共样式
let borderAll = { //单元格外侧框线
top: {
style: 'thin',
},
bottom: {
style: 'thin',
},
left: {
style: 'thin',
},
right: {
style: 'thin',
}
};
for (let key in ws) {
// 单元格公共样式设置
if (ws[key] instanceof Object) {
ws[key].s = {
border: borderAll,
alignment: {
horizontal: 'center', //水平居中对齐
vertical: 'center',//垂直居中
wrapText: 1,//自动换行
},
// fill: { //背景色
// fgColor: { rgb: 'dbf3f2' }
// },
font: {
sz: 12,//单元格中字体的样式与颜色设置
color: {
rgb: '000000'
}
},
bold: true,
numFmt: 0
}
}
}
// 记录合并单元格的信息
const merges = [];
let startCol = 0;
let currentTitle = columns[0].title;
// 确定合并区域
columns.forEach((col, index) => {
if (col.title === currentTitle) {
// 继续合并
} else {
if (index - startCol > 1) {
// 如果需要合并的区域大于1列
merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: index - 1 } });
}
// 更新标题和起始列
currentTitle = col.title;
startCol = index;
}
});
// 处理最后一个区域
if (columns.length - startCol > 1) {
merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: columns.length - 1 } });
}
// 应用合并区域到工作表
ws['!merges'] = merges;
// 创建工作簿
const wb = XLSX.utils.book_new();
console.log(wb, '创建工作簿')
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
// 导出 Excel 文件
XLSX.writeFile(wb, 'export.xlsx');
}
}
};
</script>