Apps Script批量生成Slides超时,需拆分处理并归档至指定Drive文件夹
优化Google Apps Script幻灯片邮件合并脚本
问题背景
原脚本可读取Google Sheets数据批量生成演示文稿,但处理600+行时会触发超时错误,同时生成的文件默认存放在Drive根目录,需优化为分批处理并统一存储到「Certificates」文件夹。
优化方案
- 分批处理:每次处理固定数量的未完成行(默认50行),避免单次运行超时
- 指定存储文件夹:自动创建/获取「Certificates」文件夹,所有生成的演示文稿直接保存至此
- 高效数据更新:仅写入已修改的行,减少Spreadsheet操作开销
- 状态跟踪:通过单元格标记判断是否已生成文稿,无需额外存储状态
完整优化代码
// 配置项:可根据需求调整 const CONFIG = { BATCH_SIZE: 50, // 每次处理的行数 TEMPLATE_ID: "19PKvWoDtbeVHcqm4DnWUxRx1OBO817uG3cL5Ox-dQoo", // 幻灯片模板ID STATUS_COLUMN: 14, // 标记是否已生成的列索引(从0开始) FOLDER_NAME: "Certificates" // 目标文件夹名称 }; function mailMergeSlidesBatch() { const sheet = SpreadsheetApp.getActiveSheet(); const dataRange = sheet.getDataRange(); const sheetContents = dataRange.getValues(); const header = sheetContents.shift(); let updatedRows = []; let processedCount = 0; // 获取或创建目标文件夹 const targetFolder = getOrCreateFolder(CONFIG.FOLDER_NAME); // 遍历行,只处理未完成的,直到达到批次上限 sheetContents.forEach((row, index) => { if (processedCount >= CONFIG.BATCH_SIZE) return; if (row[CONFIG.STATUS_COLUMN] === "") { // 生成幻灯片并获取URL const slidesUrl = createSlidesForRow(row, targetFolder); // 更新行状态 row[CONFIG.STATUS_COLUMN] = slidesUrl; // 记录需要更新的行(原行索引+2,因为表头占1行,索引从1开始) updatedRows.push({ rowIndex: index + 2, values: row }); processedCount++; } }); // 批量更新工作表,减少读写操作 updatedRows.forEach(item => { sheet.getRange(item.rowIndex, 1, 1, item.values.length).setValues([item.values]); }); // 提示处理结果 const ui = SpreadsheetApp.getUi(); if (processedCount === 0) { ui.alert("所有幻灯片已生成完成!"); } else { ui.alert(`已完成${processedCount}份幻灯片生成,剩余未处理任务可再次运行脚本或设置自动触发器。`); } } function createSlidesForRow(row, targetFolder) { // 复制模板到目标文件夹 const templateFile = DriveApp.getFileById(CONFIG.TEMPLATE_ID); const deckName = `${row[4]} ${row[9]}${row[3]}`; const copyFile = templateFile.makeCopy(deckName, targetFolder); // 打开并编辑幻灯片 const deck = SlidesApp.openById(copyFile.getId()); // 替换占位符 deck.replaceAllText("{{id}}", row[0]); deck.replaceAllText("{{tag}}", row[3]); deck.replaceAllText("{{besetzung}}", row[4]); deck.replaceAllText("{{beginn}}", row[5]); deck.replaceAllText("{{ende}}", row[6]); deck.replaceAllText("{{halle}}", row[7]); deck.replaceAllText("{{stand}}", row[8]); deck.replaceAllText("{{firma}}", row[2]); deck.replaceAllText("{{veranstaltung}}", row[9]); // 替换QR码图片 const qrUrl = `https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=${row[12]}`; const imageShape = deck.getSlides()[0].getShapes().find(s => s.getText().asString().trim().toUpperCase() === "{{IMAGE}}" ); if (imageShape) { imageShape.replaceWithImage(qrUrl); } // 保存并关闭 deck.saveAndClose(); // 返回幻灯片URL return `https://docs.google.com/presentation/d/${copyFile.getId()}/edit`; } function getOrCreateFolder(folderName) { const folders = DriveApp.getFoldersByName(folderName); if (folders.hasNext()) { return folders.next(); } else { return DriveApp.createFolder(folderName); } } function onOpen() { SpreadsheetApp.getUi().createMenu("⚙️ 创建证书") .addItem("批量生成幻灯片", "mailMergeSlidesBatch") .addToUi(); } // 可选:创建时间驱动触发器,自动分批处理 function createTimeDrivenTrigger() { // 先删除已有的同名触发器 const existingTriggers = ScriptApp.getProjectTriggers(); existingTriggers.forEach(trigger => { if (trigger.getHandlerFunction() === "mailMergeSlidesBatch") { ScriptApp.deleteTrigger(trigger); } }); // 创建新触发器:每10分钟运行一次 ScriptApp.newTrigger("mailMergeSlidesBatch") .timeBased() .everyMinutes(10) .create(); SpreadsheetApp.getUi().alert("自动触发器已创建,将每10分钟运行一次批量处理任务。"); }
使用说明
- 配置调整:根据实际需求修改
CONFIG对象中的参数(批次大小、模板ID、状态列索引等) - 首次运行:点击工作表菜单「⚙️ 创建证书」→「批量生成幻灯片」,脚本会自动创建「Certificates」文件夹并开始处理
- 自动处理:如需自动完成所有任务,运行
createTimeDrivenTrigger函数创建时间驱动触发器,脚本会每隔10分钟处理一批数据,直到全部完成 - 状态标记:第15列(索引14)为空的行会被视为未处理,生成后会填入幻灯片链接
内容的提问来源于stack exchange,提问作者Pavlos
相关产品推荐
相关产品推荐

