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
相关产品推荐
相关产品推荐

