使用App Script动态更新Google Form多选题选项的实现咨询
课程注册满额自动下架选项实现方案
你现有代码跑不通的核心问题有4个:
FormApp.openById()传入的是电子表格ID,不是Google表单的ID,接口调用对象本身错误- 遍历可选课程的for循环是空实现,没有做人数统计、满额判断的核心逻辑
- 没有按Block时段匹配对应表单题目,默认只修改第一个下拉题,覆盖不了多时段需求
- 读取提交数据时没有过滤空行、没有定位每个时段对应的列,人数统计结果会出错
你的formMaker工作表结构可以优化为三列:A列存时段名、B列存对应时段的课程名、C列存课程最大容量,后续新增时段、调整课程容量直接改表格就行,不用动代码。
前置配置
- 确认表单里Block1/Block2/Block3的题目类型是下拉选择或者单选题,记好题目的准确标题,不要随意改动
- 打开Google表单编辑页,从URL里提取表单ID:URL中
/d/和/edit之间的字符串就是,后续替换到代码对应位置 - 脚本部署完成后,在Apps Script编辑器新增触发器:触发源选电子表格,触发事件选「表单提交时」,每次学生提交后会自动更新选项,无需手动运行
完整可运行代码
// 配置项,按自己的实际情况修改 const CONFIG = { FORM_ID: "替换为你的Google表单ID", COURSE_SHEET_NAME: "formMaker", RESPONSE_SHEET_NAME: "Form Responses 6", BLOCK_NAMES: ["Block 1", "Block 2", "Block 3"] // *和表单里三个时段的标题完全一致* }; function updateForm() { const form = FormApp.openById(CONFIG.FORM_ID); const ss = SpreadsheetApp.getActiveSpreadsheet(); // 读取课程配置,按时段分组存储 const courseSheet = ss.getSheetByName(CONFIG.COURSE_SHEET_NAME); const courseRows = courseSheet.getDataRange().getValues().slice(1); // 跳过表头行 const courseMap = {}; courseRows.forEach(row => { const [blockName, courseName, capacity] = row; if (!blockName || !courseName) return; if (!courseMap[blockName]) courseMap[blockName] = {}; courseMap[blockName][courseName] = Number(capacity) || 30; // 容量为空默认30,可自行调整 }); // 统计各课程已选人数 const respSheet = ss.getSheetByName(CONFIG.RESPONSE_SHEET_NAME); const [respHeader, ...respRows] = respSheet.getDataRange().getValues(); const countMap = {}; const colIndexMap = {}; // 先定位每个时段在响应表的列位置 CONFIG.BLOCK_NAMES.forEach(block => { colIndexMap[block] = respHeader.indexOf(block); countMap[block] = {}; }); // 逐行计数 respRows.forEach(row => { CONFIG.BLOCK_NAMES.forEach(block => { const col = colIndexMap[block]; if (col === -1) return; const selected = row[col]; if (!selected) return; countMap[block][selected] = (countMap[block][selected] || 0) + 1; }); }); // 更新每个时段的可选选项 const allFormItems = form.getItems(); CONFIG.BLOCK_NAMES.forEach(block => { const targetItem = allFormItems.find(item => item.getTitle() === block); if (!targetItem) return; // 筛选未满额的课程 const availableOptions = Object.keys(courseMap[block] || {}).filter(course => { const maxNum = courseMap[block][course]; const currentNum = countMap[block][course] || 0; return currentNum < maxNum; }); // 适配下拉题、单选题两种题型 switch(targetItem.getType()) { case FormApp.ItemType.LIST: targetItem.asListItem().setChoiceValues(availableOptions); break; case FormApp.ItemType.MULTIPLE_CHOICE: targetItem.asMultipleChoiceItem().setChoiceValues(availableOptions); break; } }); }
使用说明
- 第一次运行脚本时会弹出权限申请,全部同意即可正常运行,首次部署建议手动执行一次
updateForm确认选项加载正常 - 如果需要调整课程容量、新增课程/时段,直接在
formMaker工作表新增对应行即可,无需修改代码 - 如果有学生退选,删除响应表中对应的提交记录,下次脚本运行时,未满额的课程会自动恢复到可选列表中
- 不要随意修改表单里三个时段题目的标题,否则脚本会匹配不到对应题目,导致更新失败
内容的提问来源于stack exchange,提问作者teachercoder
相关产品推荐
相关产品推荐

