nestJS 使用ExcelJS 实现数据的excel导出功能

nestJS 使用ExcelJS 实现数据的excel导出功能

下面展示如何在 NestJS 中使用 ExcelJS 实现 Excel 导出功能,并设置表头和数据行的样式(包括字体、颜色等)
  1. 安装必要的依赖:
base 复制代码
npm install exceljs
npm install @nestjs/platform-express
  1. 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);
    }
  }
}
  1. 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 {}
  1. 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 文件。

相关推荐
a***56063 小时前
node.js下载、安装、设置国内镜像源(永久)(Windows11)
node.js
IT_陈寒3 小时前
Redis性能翻倍的5个冷门技巧,90%开发者都不知道第3个!
前端·人工智能·后端
p***97613 小时前
SpringBoot(7)-Swagger
java·spring boot·后端
j***29483 小时前
springboot集成onlyoffice(部署+开发)
java·spring boot·后端
晨非辰3 小时前
C++ 波澜壮阔 40 年:从基础I/O到函数重载与引用的完整构建
运维·c++·人工智能·后端·python·深度学习·c++40周年
张较瘦_3 小时前
Springboot | Spring Boot 3 纯 JDBC 实现宠物管理系统增删改查(无 ORM 框架)
spring boot·后端·数据库开发
jingling5554 小时前
vue | 在 Vue 3 项目中集成高德地图(AMap)
前端·javascript·vue.js
油丶酸萝卜别吃4 小时前
Vue3 中如何在 setup 语法糖下,通过 Layer 弹窗组件弹出自定义 Vue 组件?
前端·vue.js·arcgis
h***67375 小时前
SpringBoot整合easy-es
spring boot·后端·elasticsearch
J***Q29211 小时前
Vue数据可视化
前端·vue.js·信息可视化