前端实现Excel导出【xlsx】【xlsx-js-style】
最终效果
场景
有的时候我们需要根据服务端返回的数据来导出excel表格
优化一:设置单元格样式
比如:可以调节背景色、字体样式、border
xlsx基础库不提供样式设置,可以使用xlsx-js-style
库,这个库是xlsx库的fork版本,并添加了样式定义
详细样式可以查看https://github.com/gitbrent/xlsx-js-style/
- 安装插件
npm i -s xlsx-js-style
- 导出单元格带样式
const data = [
["zs", 20, "1991-06-01"],
["ww", 14, "2001-09-01"],
["ls", 31, "1993-04-14"],
];
const workbook = XLSX.utils.book_new();
const worksheet = XLSX.utils.json_to_sheet(data);
// 设置单元格属性
worksheet["A1"].s = {
font: { bold: true },
alignment: {
horizontal: "center",
vertical: "center",
},
fill: {
fgColor: {
rgb: "FF0000",
},
},
};
XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
XLSX.writeFile(workbook, "data.xlsx");
优化二:去除默认表头,表头自定义
const data = [
['zs', 20, '1991-06-01'],
['ww', 14, '2001-09-01'],
['ls', 31, '1993-04-14'],
]
// 表头设置
data.unshift(['姓名', '年龄', '出生日期'])
const workbook = XLSX.utils.book_new()
const worksheet = XLSX.utils.json_to_sheet(data, {
skipHeader: true,
})
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, 'data.xlsx')
优化三:设置列宽
const data = [
['zs', 20, '1991-06-01'],
['ww', 14, '2001-09-01'],
['ls', 31, '1993-04-14'],
]
const workbook = XLSX.utils.book_new()
const worksheet = XLSX.utils.json_to_sheet(data, {
skipHeader: true,
})
// 设置列宽
worksheet['!cols'] = [
{
wpx: 200,
},
]
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, 'data.xlsx')
优化四:合并单元格
const data = [
['zs', 20, '1991-06-01'],
['ww', 14, '2001-09-01'],
['ls', 31, '1993-04-14'],
]
const workbook = XLSX.utils.book_new()
const worksheet = XLSX.utils.json_to_sheet(data, {
skipHeader: true,
})
// s 表示要合并的单元格范围的左上角单元格,r 表示该单元格的行号,c 表示该单元格的列号,行列号从 0 开始计数。
// 所以 { r: 0, c: 0 } 表示第 1 行第 1 列的单元格,即 A1 单元格。
// e 表示要合并的单元格范围的右下角单元格,其含义与 s 相同。
// 所以 { r: 1, c: 1 } 表示第 2 行第 2 列的单元格,即 B2 单元格。
// 因此,{ s: { r: 0, c: 0 }, e: { r: 1, c: 1 } } 表示要合并第 1 行第 1 列和第 2 行第 2 列之间的元格。
// 注意,合并会以开始位置单元格中的内容为准,所以合并后的单元格中的内容为 A1 单元格中的内容。
worksheet['!merges'] = [
{
s: {
r: 0,
c: 0,
},
e: {
r: 1,
c: 1,
},
},
]
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, 'data.xlsx')
终极版
实现优化一、二、三
import { exportExcel } from '@/utils/excel'
const exportClick6 = () => {
// 页面上展示的列, 比如使用了element-ui中的table组件
const columns = [
{
prop: 'name',
label: '姓名',
width: 150,
excelStyle: {
font: { bold: true },
alignment: {
horizontal: 'center',
vertical: 'center',
},
fill: {
fgColor: {
rgb: 'FFFF00',
},
},
},
},
{
prop: 'age',
label: '年龄',
width: 300,
},
{
prop: 'date',
label: '出生日期',
excelStyle: {
fill: {
fgColor: {
rgb: '00FFFF',
},
},
},
},
]
const tableData = [
{
name: 'zs',
age: 20,
date: '1991-06-01',
address: '广州市',
},
{
name: 'ww',
age: 14,
date: '2001-09-01',
},
{
name: 'ls',
age: 31,
date: '1993-04-14',
},
]
exportExcel('test', tableData, columns)
}
utils/excel
import * as XLSX from 'xlsx-js-style'
export function exportExcel(excelName, data, columns) {
const newData = []
const keys = columns.map((item) => item['prop'])
const headers = columns.map((item) => item['label'])
data.forEach((item) => {
const row = []
for (let key of keys) {
row.push(item[key])
}
newData.push(row)
})
// 添加表头
newData.unshift(headers)
const workbook = XLSX.utils.book_new()
const worksheet = XLSX.utils.json_to_sheet(newData, {
skipHeader: true,
})
// 设置列宽
const columnsWidth = columns.map((item) => {
return {
wpx: item.width,
}
})
worksheet['!cols'] = columnsWidth
// 设置表头样式
columns.forEach((item, index) => {
if (item['excelStyle']) {
const cell = indexToLetters(index) + 1
worksheet[cell].s = item['excelStyle']
}
})
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
XLSX.writeFile(workbook, `${excelName}.xlsx`)
}
function indexToLetters(i) {
if (i >= 0 && i <= 25) {
return String.fromCharCode(65 + i)
} else {
return undefined
}
}