You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ExcelJS写入流数据到Excel?代码生成空文件排查

问题分析与修复方案

你的代码生成空Excel文件主要有3个核心问题:

  • 异步流程未正确封装:processUpload是async函数,但内部依赖事件监听处理流,没有将整个流处理+文件提交的过程包装成Promise,导致外部调用时可能在文件写入完成前就结束流程,文件被截断为空。
  • addRow的异步特性未处理:worksheet.addRow()返回Promise,直接调用不等待的话,行数据还没写入缓冲区就执行了workbook.commit(),最终文件无内容。
  • 错误处理不完整:workbook.commit()的错误未捕获,流的错误也没有向外抛出,导致问题无法被及时发现。

修正后的代码

const excel = require("exceljs");

async function processUpload(stream, filename) {
  return new Promise((resolve, reject) => {
    let counter = 0;
    const options = {
      filename,
      useStyles: true,
      useSharedStrings: true,
    };

    const workbook = new excel.stream.xlsx.WorkbookWriter(options);
    const worksheet = workbook.addWorksheet("Sheet1");

    // 处理流数据,等待每行写入完成
    stream.on("data", async (row) => {
      counter++;
      try {
        await worksheet.addRow(row);
      } catch (err) {
        console.error("写入行失败:", err);
        reject(err);
        stream.destroy(); // 出错后终止流
      }
    });

    stream.on("end", async () => {
      try {
        await workbook.commit();
        console.log("Workbook committed and uploaded to GCS.", counter);
        resolve(filename);
      } catch (err) {
        console.error("提交工作簿失败:", err);
        reject(err);
      }
    });

    stream.on("error", (err) => {
      console.error("流处理错误:", err);
      reject(err);
      workbook.abort(); // 出错后终止工作簿写入
    });
  });
}

关键修复点说明

  1. 用Promise封装整个流程:让processUpload返回Promise,外部调用时可以通过await确保文件写入完成后再执行后续操作。
  2. 等待addRow完成:在data事件中使用await等待每行写入完成,避免数据丢失。
  3. 完善错误处理:捕获addRow和commit的错误,流出错时终止工作簿写入并向外抛出错误,确保问题能被感知。
  4. 异常时清理资源:出错时调用stream.destroy()和workbook.abort(),避免资源泄漏。

内容的提问来源于stack exchange,提问作者Ankit Kadam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 19:52:21