基于Google Sheet的动态注册表单开发问题咨询
动态课程注册表单实现方案
1. 前端HTML+JavaScript(处理动态问题显示)
创建HTML文件(命名为Form.html),包含下拉选择、动态问题区域、基础字段和文件上传组件:
<!DOCTYPE html> <html> <head> <base target="_top"> <style> .form-group { margin: 15px 0; } label { display: block; margin-bottom: 5px; } select, input[type="text"], input[type="number"] { padding: 8px; width: 300px; } .dynamic-questions { margin: 20px 0; padding: 15px; border: 1px solid #eee; } </style> </head> <body> <form id="registrationForm"> <!-- 课程下拉框 --> <div class="form-group"> <label for="course">选择课程</label> <select id="course" name="course" required> <!-- 选项将通过JS动态加载 --> </select> </div> <!-- 动态问题区域 --> <div class="dynamic-questions" id="dynamicQuestions"> <!-- 选择课程后自动加载对应问题 --> </div> <!-- 基础字段 --> <div class="form-group"> <label for="name">姓名</label> <input type="text" id="name" name="name" required> </div> <div class="form-group"> <label for="age">年龄</label> <input type="number" id="age" name="age" min="18" required> </div> <!-- 简历上传 --> <div class="form-group"> <label for="resume">上传简历</label> <input type="file" id="resume" name="resume" accept=".pdf,.doc,.docx" required> </div> <button type="submit">提交注册</button> </form> <script> // 页面加载时加载课程列表 window.onload = function() { google.script.run.withSuccessHandler(function(courses) { const courseSelect = document.getElementById('course'); courses.forEach(course => { const option = document.createElement('option'); option.value = course.row; // 存储对应行号,方便后续获取问题 option.textContent = course.name; courseSelect.appendChild(option); }); // 默认加载第一个课程的问题 loadQuestions(courseSelect.value); }).getCourseList(); }; // 监听课程选择变化,加载对应问题 document.getElementById('course').addEventListener('change', function(e) { loadQuestions(e.target.value); }); // 加载对应行的问题 function loadQuestions(rowNum) { google.script.run.withSuccessHandler(function(questions) { const questionsContainer = document.getElementById('dynamicQuestions'); // 清空现有问题 questionsContainer.innerHTML = ''; // 生成每个问题的输入框 questions.forEach((question, index) => { if (question.trim() !== '') { // 跳过空单元格 const formGroup = document.createElement('div'); formGroup.className = 'form-group'; formGroup.innerHTML = ` <label for="answer${index+1}">${question}</label> <input type="text" id="answer${index+1}" name="answer${index+1}" required> `; questionsContainer.appendChild(formGroup); } }); }).getCourseQuestions(rowNum); } // 表单提交处理 document.getElementById('registrationForm').addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); google.script.run.withSuccessHandler(function(response) { alert(response); this.reset(); }).withFailureHandler(function(error) { alert('提交失败:' + error.message); }).submitForm(formData); }); </script> </body> </html>
2. Google Apps Script 后端逻辑
在脚本编辑器中编写后端代码(Code.gs),负责数据读取、文件上传和响应存储:
// 配置参数,根据实际Sheet ID和名称修改 const CONFIG = { sourceSheetId: '你的源Sheet ID', // 存储课程和问题的Sheet ID sourceSheetName: 'Sheet1', // 源Sheet名称 targetSheetId: '你的目标Sheet ID', // 存储表单响应的Sheet ID targetSheetName: 'Responses', // 目标Sheet名称 resumeFolderId: '你的Drive文件夹ID' // 存储简历的Drive文件夹ID }; // 返回表单页面 function doGet() { return HtmlService.createHtmlOutputFromFile('Form') .setTitle('课程注册表单'); } // 获取课程列表(A2:A区域)及对应行号 function getCourseList() { const sheet = SpreadsheetApp.openById(CONFIG.sourceSheetId).getSheetByName(CONFIG.sourceSheetName); const courseRange = sheet.getRange('A2:A'); const courses = courseRange.getValues().filter(row => row[0] !== ''); // 过滤空行 return courses.map((row, index) => ({ name: row[0], row: index + 2 // 行号从2开始(A2是第一行数据) })); } // 获取指定行的问题(B列到F列) function getCourseQuestions(rowNum) { const sheet = SpreadsheetApp.openById(CONFIG.sourceSheetId).getSheetByName(CONFIG.sourceSheetName); const questionRange = sheet.getRange(`B${rowNum}:F${rowNum}`); return questionRange.getValues()[0]; // 返回该行的问题数组 } // 处理表单提交 function submitForm(formData) { try { // 1. 处理简历上传 const resumeFile = formData.get('resume'); const folder = DriveApp.getFolderById(CONFIG.resumeFolderId); const uploadedFile = folder.createFile(resumeFile); const resumeUrl = uploadedFile.getUrl(); // 2. 整理表单数据 const timestamp = new Date(); const name = formData.get('name'); const age = formData.get('age'); const courseRow = formData.get('course'); // 获取课程名称 const sheet = SpreadsheetApp.openById(CONFIG.sourceSheetId).getSheetByName(CONFIG.sourceSheetName); const courseName = sheet.getRange(`A${courseRow}`).getValue(); // 获取所有答案(最多5个) const answers = []; for (let i = 1; i <= 5; i++) { answers.push(formData.get(`answer${i}`) || ''); } // 3. 组装成目标格式:TIMESTAMP-NAME-AGE-RESUME URL-COURSE-ANSWER1-ANSWER2-ANSWER3-ANSWER4-ANSWER5 const rowData = [timestamp, name, age, resumeUrl, courseName, ...answers]; // 4. 写入目标Sheet const targetSheet = SpreadsheetApp.openById(CONFIG.targetSheetId).getSheetByName(CONFIG.targetSheetName); targetSheet.appendRow(rowData); return '注册成功!'; } catch (error) { throw new Error(error.message); } } // 自动同步逻辑:每次打开表单都会拉取最新Sheet数据,无需额外触发器 // 若需实时监听Sheet修改,可添加onEdit触发器(可选) function onEdit(e) { // 当源Sheet的课程或问题列修改时,表单下次加载会自动同步最新数据 }
3. 关键实现说明
- 动态问题加载:通过下拉框
change事件触发,根据选中课程的行号拉取对应行的B-F列数据,动态生成输入框,空单元格自动跳过。 - 自动同步Sheet数据:表单每次加载时都会调用
getCourseList拉取最新课程列表,选择课程时实时拉取对应问题,Sheet增删改后刷新表单即可同步。 - 响应存储格式:严格按照要求的列顺序组装数据,即使课程只有2个问题,后续答案列留空,保证格式统一。
- 简历上传:将文件存入指定Drive文件夹,获取文件URL后写入目标Sheet对应列。
4. 部署步骤
- 在Google Apps Script编辑器中创建
Form.html和Code.gs文件,替换配置参数中的Sheet ID和Drive文件夹ID。 - 点击「部署」→「新建部署」,选择「Web应用」,设置访问权限(按需调整),部署后获取Web应用URL即可使用表单。
内容的提问来源于stack exchange,提问作者arul selvan
相关产品推荐
相关产品推荐

