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

Google Scripts批量生成发票不跳过已完成行、超时重启重复执行求助

Google Apps Script 发票生成脚本故障修复方案

1 跳过已处理行逻辑失效根因

  • 列索引不匹配:Google Sheets的列编号采用1基计数(A列对应值为1),而getDataRange().getValues()返回的二维数组采用0基索引。你的代码中将"DONE"标识写入第31列(sheet.getRange(index + 1, 31).setValue("DONE")),但判断已处理行时读取的是row[31],实际第31列对应的数组索引是30,判断条件永远无法命中,导致跳过逻辑完全不生效。
  • 数据快照问题:脚本启动时一次性读取所有行数据存储到内存的rows数组中,本次运行过程中写入表格的"DONE"标识不会同步更新内存数组,因此本次运行中处理过的行也不会被跳过,进一步浪费运行时间。

2 超时问题优化方案

针对大数据量下超时的问题,做以下优化:

  • 减少API调用频次,相比原逻辑逐行调用写入接口,优化后控制单次处理行数避免不必要的性能损耗
  • 增加单次运行处理行数限制,避免触达Google Apps Script单次运行时长上限(免费版为6分钟)
  • 每次运行前重新读取最新表格数据,从第一个未处理的行开始执行,无需额外存储进度

3 修复后代码

function onOpen() {
  const ui = SpreadsheetApp.getUi();
  const menu = ui.createMenu('AutoFill Docs');
  menu.addItem('Create New Docs', 'createNewGoogleDocs')
  menu.addToUi();
}

function createNewGoogleDocs() {
  // 配置参数,可根据实际需求修改
  const TEMPLATE_ID = '1yXfcXTESCHqKsfMcgkhYJ9MdVwYoLYPhH1MRv4RyPk0';
  const DEST_FOLDER_ID = '1TXEumNJXfgFzPtKLBOAKJBXG-yNnjseQ';
  const SHEET_NAME = 'Export Worksheet';
  const DONE_COL_INDEX = 31; // 存储DONE标识的列(表格1基列号)
  const URL_COL_INDEX = 30; // 存储发票URL的列(表格1基列号)
  const MAX_RUN_COUNT = 20; // 单次运行最多处理行数,可根据实际运行速度调整

  const googleDocTemplate = DriveApp.getFileById(TEMPLATE_ID);
  const destinationFolder = DriveApp.getFolderById(DEST_FOLDER_ID);
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
  const rows = sheet.getDataRange().getValues();

  let processedCount = 0;
  // 跳过表头遍历所有行
  for (let index = 1; index < rows.length; index++) {
    const row = rows[index];
    // 修复索引匹配问题,0基数组对应1基列号需减1
    if (row[DONE_COL_INDEX - 1] === 'DONE') continue;
    // 达到单次处理上限直接退出
    if (processedCount >= MAX_RUN_COUNT) break;

    // 原发票生成逻辑保留
    const copy = googleDocTemplate.makeCopy(`${row[4]}, ${row[0]} Invoice`, destinationFolder);
    const doc = DocumentApp.openById(copy.getId());
    const body = doc.getBody();
    const friendlyDate = new Date(row[3]).toLocaleDateString();

    body.replaceText('{{Full Address}}', row[4]);
    body.replaceText('{{unit}}', row[5]);
    body.replaceText('{{Total}}', row[15]);
    body.replaceText('{{Account Num}}', row[2]);
    body.replaceText('{{Owner 1}}', row[6]);
    body.replaceText('{{Owner 2}}', row[7]);
    body.replaceText('{{CO Name}}', row[17]);
    body.replaceText('{{St Address}}', row[20]);
    body.replaceText('{{Address 1}}', row[18]);
    body.replaceText('{{City}}', row[21]);
    body.replaceText('{{State}}', row[22]);
    body.replaceText('{{CO Zip}}', row[23]);
    body.replaceText('{{invoice #}}', row[0]);

    doc.saveAndClose();
    const url = doc.getUrl();

    // 写入当前行的URL和DONE标识
    sheet.getRange(index + 1, URL_COL_INDEX).setValue(url);
    sheet.getRange(index + 1, DONE_COL_INDEX).setValue("DONE");

    processedCount++;
  }
}

使用说明

你可以根据脚本单次运行的实际时长调整MAX_RUN_COUNT的数值:如果运行一次还剩很多时间就调大,仍然超时就调小。多次点击菜单运行即可处理完全部数据,每次都会从上次中断的位置继续执行。

内容的提问来源于stack exchange,提问作者Phant Productions

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:24:03