背景:最近经常要给业务方拉数据生成表格、修改表格,遂记录下研究结果。
- node框架用的Nestjs
- 常用的excel库有xlsx、exceljs, 对于简单表格,两者差别不大,xlsx写起来更简洁,可以用这个。
- 快的话1小时可以搞定。

一、生成excel - xlsx
先看成果 装包 pnpm i xlsx
服务
typescript
import { Injectable } from '@nestjs/common';
import * as XLSX from 'xlsx';
@Injectable()
export class ExcelService {
// 创建Excel
async create() {
const users = [
{ id: 1, name: '张三2', age: 25, email: 'zhangsan@example.com' },
{ id: 2, name: '李四', age: 30, email: 'lisi@example.com' },
{ id: 3, name: '王五', age: 28, email: 'wangwu@example.com' },
];
const worksheet = XLSX.utils.json_to_sheet(users);
// 新建表格
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet);
// 指定路径和文件名
XLSX.writeFile(workbook, `${process.cwd()}/public/excel/user.xlsx`);
return 'Excel文件创建成功!'
}
}
控制器
less
@Get('create')
@ApiOperation({ summary: '创建Excel' })
async create() {
return await this.excelService.create();
}
二、生成excel方式2-exceljs
比较繁琐但是对样式控制更高,可以了解下 先看成果 装包 pnpm i exceljs fs
服务
typescript
import { Injectable } from '@nestjs/common';
import * as ExcelJS from 'exceljs';
import { join } from 'path';
import { existsSync, mkdirSync } from 'fs';
@Injectable()
export class ExcelService {
// 创建Excel
async create() {
// 创建工作簿和工作表
const workbook = new ExcelJS.Workbook();
// 指定sheet名
const worksheet = workbook.addWorksheet('用户数据');
// 设置表头
worksheet.columns = [
{ header: 'ID', key: 'id', width: 20 },
{ header: '姓名', key: 'name', width: 20 },
{ header: '年龄', key: 'age', width: 10 },
{ header: '邮箱', key: 'email', width: 30 },
];
// 添加数据
const users = [
{ id: 1, name: '张三2', age: 25, email: 'zhangsan@example.com' },
{ id: 2, name: '李四', age: 30, email: 'lisi@example.com' },
{ id: 3, name: '王五', age: 28, email: 'wangwu@example.com' },
];
// 添加行,方式1
// worksheet.addRows(users);
// 方式2
users.forEach((item) => worksheet.addRow(item))
// 设置表头样式
worksheet.getRow(1).eachCell((cell) => {
cell.font = { bold: true };
cell.alignment = { horizontal: 'center' };
cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFCCCCCC' }, };
});
// 确保保存目录存在:根目录下uploads文件夹
const publicDir = join(process.cwd(), 'public/excel');
if (!existsSync(publicDir)) mkdirSync(publicDir, { recursive: true });
// 生成文件名(包含时间戳避免重复)
const timestamp = new Date().getTime();
const fileName = `users_${timestamp}.xlsx`;
const filePath = join(publicDir, fileName);
// 保存 Excel 文件
await workbook.xlsx.writeFile(filePath);
// 返回文件路径和 URL
return { path: filePath };
}
}
控制器
less
@Get('create')
@ApiOperation({ summary: '创建Excel' })
async create() {
return await this.excelService.create();
}
三、修改excel
注意:wps不会自动更新表格,修改完后需要在wps中重新打开excel。 需求:修改用户表中2条数据的名字;
- 获取所有sheet的名字: workbook.SheetNames
- 操控某个sheet: workbook.Sheets['用户数据']或workbook.Sheets[workbook.SheetNames[0]];
- 先装包 pnpm i xlsx

服务
typescript
import { Injectable } from '@nestjs/common';
import { existsSync } from 'fs';
import * as XLSX from 'xlsx';
@Injectable()
export class ExcelService {
edit() {
// 1.找到文件
const filePath = `${process.cwd()}/public/excel/users.xlsx`;
if (!existsSync(filePath)) return (`文件不存在: ${filePath}`);
// 读取文件内容
const workbook = XLSX.readFile(filePath);
// 获取第一个工作表
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 数据转化
const tableData = XLSX.utils.sheet_to_json(worksheet);
console.log('tableData: ', tableData);
// 2.修改数据
const newTableData = tableData.map((row: any) => {
if (row['姓名'] === '张三2') row['姓名'] = '张三3';
if (row['ID'] === 2) row['姓名'] = '李四3';
return row
})
console.log('newTableData: ', newTableData);
// 3.替换工作簿中的工作表
workbook.Sheets[firstSheetName] = XLSX.utils.json_to_sheet(newTableData);
// 4. 写回文件
XLSX.writeFile(workbook, filePath);
return '更新完毕';
}
}
控制器中使用
less
@Get('edit')
@ApiOperation({ summary: '修改Excel' })
edit() {
return this.excelService.edit();
}
四、删除excel文件
核心 fs.unlinkSync(文件路径);
比较简单直接看代码
typescript
import * as fs from 'fs';
@Get('del')
@ApiOperation({ summary: '删除Excel' })
async del() {
const filePath = `${process.cwd()}/public/excel/yuanGong.xlsx`;
await fs.unlinkSync(filePath);
return '删除Excel';
}
至此都已搞定