nestJS 使用ExcelJS 实现数据的excel导出功能
下面展示如何在 NestJS 中使用 ExcelJS 实现 Excel 导出功能,并设置表头和数据行的样式(包括字体、颜色等)
- 安装必要的依赖:
base
npm install exceljs
npm install @nestjs/platform-express
- excel.controller.ts
ts
import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';
import { ExcelService } from './excel.service';
@Controller('excel')
export class ExcelController {
constructor(private readonly excelService: ExcelService) {}
@Get('export')
async exportExcel(@Res() res: Response) {
// 模拟数据 - 实际应用中可能来自数据库
const mockData = [
{
id: 1,
name: '张三',
email: 'zhangsan@example.com',
age: 28,
registerDate: new Date('2023-01-15'),
status: '活跃'
},
{
id: 2,
name: '李四',
email: 'lisi@example.com',
age: 32,
registerDate: new Date('2023-02-20'),
status: '活跃'
},
{
id: 3,
name: '王五',
email: 'wangwu@example.com',
age: 45,
registerDate: new Date('2023-03-10'),
status: '禁用'
},
{
id: 4,
name: '赵六',
email: 'zhaoliu@example.com',
age: 23,
registerDate: new Date('2023-04-05'),
status: '活跃'
}
];
try {
// 生成 Excel 文件
const buffer = await this.excelService.generateExcel(mockData);
// 设置响应头,告诉浏览器这是一个 Excel 文件
// 如果框架中封装了处理文件流返回的装饰器,直接
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', 'attachment; filename="用户数据报表.xlsx"');
// 发送文件
res.send(buffer);
// 如果框架中封装了处理文件流返回的装饰器,直接创建可读流return即可
// const stream = new StreamableFile(excelBuffer);
// return stream
} catch (error) {
res.status(500).send('导出 Excel 失败: ' + error.message);
}
}
}
- excel.module.ts
ts
import { Module } from '@nestjs/common';
import { ExcelController } from './excel.controller';
import { ExcelService } from './excel.service';
@Module({
controllers: [ExcelController],
providers: [ExcelService],
exports: [ExcelService]
})
export class ExcelModule {}
- excel.service.ts
ts
import { Injectable } from '@nestjs/common';
import * as ExcelJS from 'exceljs';
@Injectable()
export class ExcelService {
async generateExcel(data: any[]): Promise<Buffer> {
// 创建工作簿
const workbook = new ExcelJS.Workbook();
workbook.creator = 'NestJS Application';
workbook.lastModifiedBy = 'NestJS Application';
workbook.created = new Date();
workbook.modified = new Date();
workbook.lastPrinted = new Date();
// 添加工作表
const worksheet = workbook.addWorksheet('数据报表');
// 定义表头
const headers = [
{ header: 'ID', key: 'id', width: 10 },
{ header: '名称', key: 'name', width: 20 },
{ header: '邮箱', key: 'email', width: 30 },
{ header: '年龄', key: 'age', width: 10 },
{ header: '注册日期', key: 'registerDate', width: 15 },
{ header: '状态', key: 'status', width: 15 }
];
// 设置表头
worksheet.columns = headers;
// 设置表头样式
const headerRow = worksheet.getRow(1);
headerRow.font = {
name: 'Arial',
size: 12,
bold: true,
color: { argb: 'FFFFFF' } // 白色字体
};
headerRow.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '4285F4' } // 谷歌蓝背景
};
headerRow.alignment = {
vertical: 'middle',
horizontal: 'center'
};
headerRow.height = 20;
// 添加数据行
data.forEach((item, index) => {
const row = worksheet.addRow(item);
// 设置奇数行和偶数行不同样式
const isEvenRow = (index + 1) % 2 === 0;
row.font = {
name: 'Arial',
size: 11,
color: { argb: '000000' } // 黑色字体
};
// 隔行变色
if (isEvenRow) {
row.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'F8F9FA' } // 浅灰色
};
}
// 设置对齐方式
row.alignment = {
vertical: 'middle',
horizontal: 'left'
};
// 设置行高
row.height = 18;
// 为状态列设置特殊样式
const statusCell = row.getCell('status');
if (item.status === '活跃') {
statusCell.font = {
...statusCell.font,
color: { argb: '008000' } // 绿色
};
} else if (item.status === '禁用') {
statusCell.font = {
...statusCell.font,
color: { argb: 'FF0000' } // 红色
};
}
// 为日期列设置格式
const dateCell = row.getCell('registerDate');
dateCell.numFmt = 'yyyy-mm-dd';
});
// 设置所有单元格边框
worksheet.eachRow({ includeEmpty: false }, (row) => {
row.eachCell({ includeEmpty: false }, (cell) => {
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
});
});
// 转换为 buffer 并返回
return await workbook.xlsx.writeBuffer();
}
}
样式设置说明
- 表头样式:使用蓝色背景、白色粗体 Arial 字体,垂直和水平居中
- 数据行样式:使用 Arial 字体,隔行使用不同背景色区分
- 状态列:根据状态值使用不同颜色(活跃为绿色,禁用为红色)
- 日期列:设置了日期格式
- 边框:所有单元格都添加了细边框
要使用这个功能,只需将 ExcelModule 导入到你的 AppModule 中,然后访问 /excel/export
即可下载生成的 Excel 文件。