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

Google Apps Script合并Sheet为PDF遇setTimeout未定义错误及openByUrl适配求助

解决「ReferenceError: setTimeout is not defined」并适配openByUrl的方案

错误原因

setTimeout是浏览器端专属的JavaScript API,Google Apps Script(GAS)的服务器端运行环境不支持该函数。原代码在当前Sheet可用,大概率是因为执行上下文是客户端(如侧边栏、自定义对话框的HTML页面),而切换到openByUrl或其他Sheet时,代码运行在服务器端,触发了环境不兼容的错误。

解决方案步骤

1. 替换setTimeout为GAS原生延迟方法

将所有setTimeout调用替换为GAS服务器端支持的Utilities.sleep(毫秒数):

// 原浏览器端代码
setTimeout(() => {
  // 后续逻辑
}, 1000);

// 修改为GAS兼容代码
Utilities.sleep(1000);
// 后续逻辑

2. 调整异步逻辑为async/await模式

pdf-lib依赖异步操作,GAS服务器端支持async/await语法,需将原代码中的.then()链式调用改为同步化的await写法,避免依赖浏览器事件循环:

// 原浏览器端异步写法
PDFLib.PDFDocument.create().then(async (doc) => {
  // 处理PDF文档
}).catch(err => console.error(err));

// 修改为GAS服务器端兼容写法
async function mergeSheetsToPdf() {
  try {
    const doc = await PDFLib.PDFDocument.create();
    // 处理PDF文档的逻辑
  } catch (err) {
    console.error(err);
  }
}

3. 适配openByUrl访问目标表格

将SpreadsheetApp.getActiveSpreadsheet()替换为SpreadsheetApp.openByUrl("目标表格URL"),确保URL正确且脚本拥有访问权限(首次运行会触发授权提示,需允许):

// 原代码
const ss = SpreadsheetApp.getActiveSpreadsheet();

// 修改后代码
const targetSheetUrl = "https://docs.google.com/spreadsheets/d/你的表格ID/edit";
const ss = SpreadsheetApp.openByUrl(targetSheetUrl);

完整修改后代码示例

// 先复制pdf-lib的UMD版本代码到此处(可从pdf-lib官网获取UMD包内容)

async function mergeQuanQualToPdf() {
  const targetSheetUrl = "https://docs.google.com/spreadsheets/d/你的表格ID/edit";
  const ss = SpreadsheetApp.openByUrl(targetSheetUrl);
  
  // 获取两个标签的指定范围
  const quanSheet = ss.getSheetByName("Quan");
  const qualSheet = ss.getSheetByName("Qual");
  const quanRange = quanSheet.getRange("A1:Z100"); // 替换为实际范围
  const qualRange = qualSheet.getRange("A1:Z100"); // 替换为实际范围

  // 将Sheet范围转换为PDF
  const quanPdfBytes = await getSheetAsPdf(ss, quanSheet.getSheetId(), quanRange);
  const qualPdfBytes = await getSheetAsPdf(ss, qualSheet.getSheetId(), qualRange);

  // 合并PDF
  const mergedDoc = await PDFLib.PDFDocument.create();
  const quanDoc = await PDFLib.PDFDocument.load(quanPdfBytes);
  const qualDoc = await PDFLib.PDFDocument.load(qualPdfBytes);

  const quanPages = await mergedDoc.copyPages(quanDoc, quanDoc.getPageIndices());
  quanPages.forEach(page => mergedDoc.addPage(page));
  
  const qualPages = await mergedDoc.copyPages(qualDoc, qualDoc.getPageIndices());
  qualPages.forEach(page => mergedDoc.addPage(page));

  // 保存合并后的PDF到Drive
  const mergedPdfBytes = await mergedDoc.save();
  DriveApp.createFile(Utilities.newBlob(mergedPdfBytes, "application/pdf", "合并结果.pdf"));
}

async function getSheetAsPdf(ss, sheetId, range) {
  const url = `https://docs.google.com/spreadsheets/d/${ss.getId()}/export?` +
    `format=pdf&` +
    `gid=${sheetId}&` +
    `range=${encodeURIComponent(range.getA1Notation())}&` +
    `portrait=true&` +
    `fitw=true&` +
    `sheetnames=false&` +
    `printtitle=false&` +
    `pagenumbers=false&` +
    `gridlines=false&` +
    `fzr=false`;

  // 替换原setTimeout为GAS延迟方法
  Utilities.sleep(500);
  const response = UrlFetchApp.fetch(url, {headers: {Authorization: `Bearer ${ScriptApp.getOAuthToken()}`}});
  return response.getBlob().getBytes();
}

注意事项

  • 需将pdf-lib的UMD版本代码复制到脚本顶部(GAS服务器端无法直接引入外部库,需手动复制)。
  • 首次运行脚本时,需授权脚本访问Google Sheets和Drive的权限。
  • 可根据需求调整getSheetAsPdf中的URL参数(如页面方向、是否显示网格线等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:12:43