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 文件。

相关推荐
MadPrinter6 小时前
SpringBoot学习日记 Day11:博客系统核心功能深度开发
java·spring boot·后端·学习·spring·mybatis
子兮曰6 小时前
🔥C盘告急!WSL磁盘暴增?三招秒清20GB+空间
前端·windows·docker
淦出一番成就6 小时前
Java反序列化接收多种格式日期-JsonDeserialize
java·后端
Jinuss6 小时前
Vue3源码reactivity响应式篇之EffectScope
前端·vue3
Java中文社群6 小时前
Hutool被卖半年多了,现状是逆袭还是沉寂?
java·后端
stoneship6 小时前
网页截图API-Npm工具包分享
前端
Jedi Hongbin6 小时前
Three.js shader内置矩阵注入
前端·javascript·three.js
etcix6 小时前
dmenux.c: integrate dmenu project as one file
c语言·前端·算法
光影少年7 小时前
react16到react19更新及底层实现是什么以及区别
前端·react.js·前端框架