解决Google Apps Script自定义菜单调用带参函数的‘函数未找到’错误
问题根源
Google Apps Script的自定义菜单(DocumentApp.getUi().createMenu())不支持直接在addItem的回调参数中传递带参数的函数调用(比如generateDocument("Mickeys Bakery", "Tennis"))。系统会把整个字符串当作函数名去查找,自然找不到对应的函数,因此抛出"Script function not found"错误。
解决步骤
1. 修改菜单创建逻辑,用无参包装函数传递参数
不能直接在菜单中调用带参函数,需要为每个菜单项生成唯一的无参包装函数,在包装函数内部调用目标带参函数并传入对应参数。修改sponsorButton函数中的菜单项添加逻辑:
// Function to create a sponsor selection menu in the UI function sponsorButton() { const ui = DocumentApp.getUi(); const sponsorsMenu = ui.createMenu('Select A Sponsor'); // Add submenus for each sponsor SPONSORS.forEach(function(sponsorData) { const sponsor = sponsorData.sponsor; const sponsoredProgrammes = sponsorData.sponsoredProgrammes; const sponsorSubMenu = ui.createMenu(sponsor); // Add submenu items for each sponsored programme sponsoredProgrammes.forEach(function(programme) { // 生成唯一的无参函数名(替换空格为下划线,避免函数名非法) const wrapperFuncName = `generateDoc_${sponsor.replace(/\s+/g, '_')}_${programme.replace(/\s+/g, '_')}`; // 动态创建包装函数 this[wrapperFuncName] = function() { generateDocument(sponsor, programme); }; // 将包装函数绑定到菜单项 sponsorSubMenu.addItem(programme, wrapperFuncName); }); sponsorsMenu.addSubMenu(sponsorSubMenu); }); // Add the sponsor menu to the UI sponsorsMenu.addToUi(); }
2. 修复generateDocument函数的缺失变量
原函数中body变量未定义,会导致执行报错,需要先复制模板文档并获取文档主体:
// Function to generate a document based on the selected sponsor and program function generateDocument(sponsorName, programName) { try { // 复制模板文档并打开 const copiedFile = DriveApp.getFileById(TEMPLATE_DOC_ID).makeCopy(`${sponsorName} - ${programName}`); const doc = DocumentApp.openById(copiedFile.getId()); const body = doc.getBody(); // 初始化body变量 // Get data from the first row of Flagged Students sheet var data = flaggedStudentsSheet.getRange(2, 1, 1, flaggedStudentsSheet.getLastColumn()).getValues()[0]; // Sponsor Details body.replaceText('{{s}}', sponsorName); // Sponsor name body.replaceText('{{p}}', programName); // Programme name // Student Details(修正原代码中占位符的语法错误) body.replaceText('{{name}}', data[1]); // Student Name body.replaceText('{{team_coach}}', data[2]); body.replaceText('{{sport}}', data[18]); // 修正{{sport}为{{sport}} body.replaceText('{{team_performance}}', data[15]); body.replaceText('{{attendance}}', data[14]); // 保存并关闭文档 doc.saveAndClose(); Logger.log('Document created successfully.'); } catch (e) { Logger.log('Error: ' + e.toString()); } }
3. 其他注意事项
- 确保
TEMPLATE_DOC_ID和SPREADSHEET_ID已替换为实际的文件ID - 重新部署脚本后,刷新文档即可看到更新后的菜单
内容的提问来源于stack exchange,提问作者Gee
相关产品推荐
相关产品推荐

