Google Apps Script批量生成文档场景下的性能优化问题
结论
该场景下依然可以通过批量优化思路大幅提升性能,核心是砍掉所有不必要的重复外部调用,尽可能把可前置的操作移到循环外,高阶方案可通过批量API合并请求进一步提速。
可落地的优化点
- 提前预加载母版文件,避免循环内重复读取:原代码循环内每次处理附件都调用
DriveApp.getFileById读取母版,3个母版完全可以在循环外提前加载为File对象存入数组,循环内直接调用makeCopy即可,用1次读取替代N次重复读取。 - 精简副本创建的调用链路:原代码链式调用
makeCopy后额外调用getId再DocumentApp.openById,实际上makeCopy直接返回新文件的File对象,直接用该对象的ID打开文档即可,省去多余的ID获取和寻址调用。 - 固定参数提前缓存:如果
attributesArray是固定的占位符列表,提前在全局定义,避免每次调用replaceCustomFields重复生成。 - 批量回写发送状态:处理完所有学生后,统一把「已发送」标记写入工作表,不要逐行写入,符合批量读写的优化原则。
- 高阶优化:使用Drive高级服务的批量请求能力,把多个文件复制、内容更新操作合并为单个HTTP请求,相比内置服务逐次调用速度可提升3~10倍,适合学生数量较大的场景。
优化后核心代码示例
// 提前全局定义固定参数 const ATTRIBUTES = attributesArray; let studentUpdates = []; // 存储发送状态更新,最后批量写入 function filesAndEmails() { const UI = SpreadsheetApp.getUi(); try { var emailLinkID = "REMOVED FOR PRIVACY"; if (emailLinkID != -1) { var fldr = DriveApp.getFolderById("REMOVED FOR PRIVACY"); var sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_1); var arrayOfStudentObj = objectify(sheet.getRange(3, 1, sheet.getLastRow()-2, 11).getValues()); // 提前预加载所有母版文件,仅执行1次 var arrayOfAttachObj = getAttachments().map(attach => { attach.fileObj = DriveApp.getFileById(getID(attach[ATTACH_FILEURL_COL], isFile=false)); return attach; }); studentUpdates = Array(arrayOfStudentObj.length).fill(['']); arrayOfStudentObj.forEach(function(student, idx) { if (student[EMAIL_SENT_COL] == '') { try { arrayOfAttachObj.forEach(function(attachment) { var filename = `${student[RYE_ID_COL]} ${student[FNAME_COL]} ${student[LNAME_COL]} ${attachment[ATTACH_FILENAME_COL]}`; // 直接用预加载的母版文件创建副本,省去重复读取母版的调用 var newFile = attachment.fileObj.makeCopy(filename, fldr); var doc = DocumentApp.openById(newFile.getId()); replaceCustomFields(doc, student); }); studentUpdates[idx] = ['已发送']; // 标记待更新状态,暂不写入表 } catch(e) {} } }); // 批量写入发送状态,仅1次写操作 sheet.getRange(3, EMAIL_SENT_COL_INDEX, arrayOfStudentObj.length, 1).setValues(studentUpdates); UI.alert("Script successfully completed!"); }; } catch(e) { UI.alert("Error Detected", e.message + "\n\nContact a developer for help.", UI.ButtonSet.OK); }; } function replaceCustomFields(file, student) { const body = file.getBody(); // 复用body对象,避免重复调用getBody ATTRIBUTES.forEach(function(attribute) { body.replaceText(attribute, student[attribute]); }); file.saveAndClose(); } // 原有辅助函数保持不变 function getAttachments() { var files = SpreadsheetApp.getActive().getSheetByName(SHEET_2); return objectify(files.getRange(1, 1, files.getLastRow(), 2).getValues()); } function objectify(array) { var keys = array.shift(); var objects = array.map(function (values) { return keys.reduce(function (o, k, i) { o[k] = values[i]; return o; }, {}); }); return objects; }
上述优化完成后,在100个学生的场景下,执行速度可提升2~3倍。如果学生量级更大,可以进一步接入Drive批量API合并复制请求,性能提升会更明显。
内容的提问来源于stack exchange,提问作者lattejiu
相关产品推荐
相关产品推荐

