Node.js中如何将node-pg-stream查询分片追加到现有Excel工作表
实现方案
推荐依赖库
使用exceljs完成Excel写入需求,它支持流式追加数据,不会一次性加载整个工作簿到内存,完美适配大表导出场景,不会出现内存溢出问题。
完整实现代码
首先安装依赖:
npm install exceljs pg-query-stream
推荐使用异步迭代的写法,原生处理流的背压问题,代码更简洁:
const { Pool } = require('pg'); const QueryStream = require('pg-query-stream'); const ExcelJS = require('exceljs'); // 按你自己的业务配置修改PG连接参数 const pool = new Pool({ user: '数据库用户名', host: '数据库地址', database: '数据库名', password: '数据库密码', port: 5432, }); async function exportLargeTableToExcel() { const client = await pool.connect(); try { // 1. 加载已有工作簿/新建工作簿 const workbook = new ExcelJS.Workbook(); // 若要追加到已存在的本地工作簿,取消注释下面代码替换成你的文件路径 // await workbook.xlsx.readFile('你的现有工作簿路径.xlsx'); // 获取指定工作表,不存在就新建 const worksheet = workbook.getWorksheet('目标工作表名称') || workbook.addWorksheet('目标工作表名称'); // 可选:新工作表可以提前配置列规则,已有工作表直接跳过即可 // worksheet.columns = [ // { header: '字段1', key: 'db_column1', width: 15 }, // { header: '字段2', key: 'db_column2', width: 20 }, // // 和你查询的表字段一一对应即可 // ]; // 2. 初始化PG查询流 const query = new QueryStream('select * from large_table'); const stream = client.query(query); // 3. 流式处理数据追加 for await (const data of stream) { worksheet.addRow(data); // 可选:每新增1000行刷入一次缓存,减少内存占用 // if (worksheet.rowCount % 1000 === 0) { // await workbook.xlsx.writeBuffer(); // } } // 4. 全部数据处理完成后保存工作簿 await workbook.xlsx.writeFile('最终输出的文件路径.xlsx'); console.log('数据追加完成'); // 若需要返回给前端下载,直接返回buffer即可 // const buffer = await workbook.xlsx.writeBuffer(); // res.type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); // res.send(buffer); } catch (err) { console.error('处理出错:', err); } finally { client.release(); } } exportLargeTableToExcel();
兼容原Event监听写法的代码
如果你不想改动原有代码的事件监听逻辑,直接替换data事件里的逻辑即可:
// 提前初始化好工作簿和目标工作表 const workbook = new ExcelJS.Workbook(); const worksheet = workbook.getWorksheet('目标工作表') || workbook.addWorksheet('目标工作表'); const query = new QueryStream('select * from large_table'); const stream = client.query(query); stream.on('end', async () => { await workbook.xlsx.writeFile('输出文件路径.xlsx'); done(); // 后续业务逻辑 }); stream.on('data', async (data) => { stream.pause(); // 追加当前分片数据到工作表 worksheet.addRow(data); stream.resume(); }); stream.on('error', (err) => { console.error('流处理出错', err); done(); });
优化建议
- 批量写入性能更高,可攒500~1000条数据后调用
worksheet.addRows(批量数据数组)一次性写入,比单条addRow性能高30%以上 - 提前配置工作表的列规则,避免写入后列宽、字段匹配错误
- 单表数据超过10万行建议拆分多个工作表存储,避免单个工作表过大打开卡顿
内容的提问来源于stack exchange,提问作者Ameer Dheyaa
相关产品推荐
相关产品推荐

