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

相关推荐
不好听6134 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus4 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
GetcharZp4 小时前
抛弃低效SSH!这套Ansible+Web可视化神器,让你天天准点下班!
后端
前端小李子5 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech5 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn5 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧7 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
weixin_446260858 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
qetfw8 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具