
本教程旨在解决html表单动态添加多行数据时,google apps script web app仅保存第一行数据的问题。核心解决方案是利用`e.parameters`(复数)获取所有同名输入字段的值数组,并通过修改apps script的`dopost`函数,将这些数据结构化为多行,一次性写入google sheet,从而实现多行数据的完整保存。
在构建交互式Web应用时,我们经常需要将用户在HTML表单中输入的数据保存到后端存储,例如Google Sheet。当HTML表单包含可动态添加的表格行时,一个常见的问题是:尽管用户输入了多行数据,但通过Google Apps Script部署的Web App却只能保存第一行数据。本文将深入探讨这一问题的原因,并提供详细的解决方案。
问题分析:e.parameter与多行数据
在使用Google Apps Script处理POST请求时,e.parameter对象通常用于访问表单提交的单个参数。然而,当HTML表单中存在多个具有相同name属性的输入字段(例如,一个动态表格中的多行Email输入),e.parameter[name]只会返回第一个匹配字段的值。这就是导致只有第一行数据被保存的根本原因。
为了正确处理这种情况,我们需要使用e.parameters(注意是复数),它会返回一个对象,其中每个键对应一个表单字段的name属性,而其值则是一个包含所有同名输入字段值的数组。
解决方案:修改Google Apps Script doPost 函数
假设我们的HTML表单有一个动态表格,包含“Email”和“Name”两列,并且我们希望将这些数据连同提交日期一起保存到Google Sheet。
立即学习“前端免费学习笔记(深入)”;
原始 doPost 函数(仅处理单行数据)
// Updated for 2021 and ES6 standardsconst sheetName = 'Sheet1'const scriptProp = PropertiesService.getScriptProperties()function initialSetup () { const activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet() scriptProp.setProperty('key', activeSpreadsheet.getId())}function doPost (e) { const lock = LockService.getScriptLock() lock.tryLock(10000) try { const doc = SpreadsheetApp.openById(scriptProp.getProperty('key')) const sheet = doc.getSheetByName(sheetName) const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0] const nextRow = sheet.getLastRow() + 1 // 这一行是问题的根源,e.parameter[header] 仅获取第一个值 const newRow = headers.map(function(header) { return header === 'Date' ? new Date() : e.parameter[header] }) sheet.getRange(nextRow, 1, 1, newRow.length).setValues([newRow]) return ContentService .createTextOutput(JSON.stringify({ 'result': 'success', 'row': nextRow })) .setMimeType(ContentService.MimeType.JSON) } catch (e) { return ContentService .createTextOutput(JSON.stringify({ 'result': 'error', 'error': e })) .setMimeType(ContentService.MimeType.JSON) } finally { lock.releaseLock() }}
在上述代码中,e.parameter[header]只会获取到第一个“Email”和“Name”字段的值,导致只有一行数据被处理。
修正后的 doPost 函数(处理多行固定列数据)
为了处理多行数据,我们需要修改newRow的构建方式,利用e.parameters获取所有值,并将其重组为适合setValues方法的多维数组。假设Google Sheet的表头顺序为“Date”、“Email”、“Name”。
function doPost (e) { const lock = LockService.getScriptLock() lock.tryLock(10000) try { const doc = SpreadsheetApp.openById(scriptProp.getProperty('key')) const sheet = doc.getSheetByName(sheetName) const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0] const nextRow = sheet.getLastRow() + 1 // 使用 e.parameters 获取所有同名字段的值数组 // temp 将是一个数组,例如:[new Date(), ['email1', 'email2'], ['name1', 'name2']] const temp = headers.map(header => header === 'Date' ? new Date() : e.parameters[header]); // 重构数据为多行多列的数组,适合 setValues // 假设 Email 是 temp[1],Name 是 temp[2] const newRows = temp[1].map((emailValue, i) => { // 每一行的数据结构:[日期, 邮箱, 姓名] return [temp[0], emailValue, temp[2][i]]; }); // 使用 newRows.length 写入多行数据 sheet.getRange(nextRow, 1, newRows.length, newRows[0].length).setValues(newRows); return ContentService .createTextOutput(JSON.stringify({ 'result': 'success', 'row': nextRow })) .setMimeType(ContentService.MimeType.JSON) } catch (e) { return ContentService .createTextOutput(JSON.stringify({ 'result': 'error', 'error': e })) .setMimeType(ContentService.MimeType.JSON) } finally { lock.releaseLock() }}
代码解析:
const temp = headers.map(header => header === ‘Date’ ? new Date() : e.parameters[header]);这行代码根据Google Sheet的headers,为每个表头收集对应的数据。如果表头是“Date”,则生成当前的Date对象。否则,从e.parameters中获取对应表头(即HTML输入字段的name)的所有值,这将是一个数组。例如,如果headers是[‘Date’, ‘Email’, ‘Name’],temp可能会是[Date_object, [’email1′, ’email2′], [‘name1’, ‘name2′]]。const newRows = temp[1].map((emailValue, i) => { … });我们以temp数组中第一个包含多行数据的字段(在本例中是Email,对应temp[1])作为迭代基准。map函数会遍历Email数组的每个元素emailValue及其索引i。在每次迭代中,我们构建一个代表Google Sheet中一行的数组:[temp[0], emailValue, temp[2][i]]。temp[0]是日期对象(所有行共享)。emailValue是当前行的邮箱。temp[2][i]是当前行对应的姓名(通过索引i从Name数组temp[2]中获取)。最终newRows将是一个二维数组,例如[[Date_object, ’email1′, ‘name1′], [Date_object, ’email2′, ‘name2’]]。sheet.getRange(nextRow, 1, newRows.length, newRows[0].length).setValues(newRows);setValues方法被调用,它现在接收一个二维数组,其中newRows.length指定要写入的行数,newRows[0].length指定要写入的列数。这样就能一次性写入所有行数据。
修正后的 doPost 函数(处理多行动态列数据)
如果您的HTML表单和Google Sheet可能包含除了“Date”、“Email”、“Name”之外的更多动态列,并且您希望这些列也能被正确捕获,可以进一步优化doPost函数。
function doPost (e) { const lock = LockService.getScriptLock() lock.tryLock(10000) try { const doc = SpreadsheetApp.openById(scriptProp.getProperty('key')) const sheet = doc.getSheetByName(sheetName) const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0] const nextRow = sheet.getLastRow() + 1 const temp = headers.map(header => header === 'Date' ? new Date() : e.parameters[header]); // 动态处理更多列 // 假设 Email 仍然是 temp[1] const newRows = temp[1].map((emailValue, i) => { // 构建当前行的基础数据:[日期, 邮箱] const rowData = [temp[0], emailValue]; // 动态添加后续列的数据 // temp.slice(2) 获取 temp 数组中索引为 2 及以后的元素(即除 Date 和 Email 之外的所有列的数据数组) // map(f => f[i]) 从每个列的数据数组中取出当前行 (i) 的值 // ... 展开运算符将这些值添加到 rowData 中 return [...rowData, ...temp.slice(2).map(f => f[i])]; }); sheet.getRange(nextRow, 1, newRows.length, newRows[0].length).setValues(newRows); return ContentService .createTextOutput(JSON.stringify({ 'result': 'success', 'row': nextRow })) .setMimeType(ContentService.MimeType.JSON) } catch (e) { return ContentService .createTextOutput(JSON.stringify({ 'result': 'error', 'error': e })) .setMimeType(ContentService.MimeType.JSON) } finally { lock.releaseLock() }}
代码解析:
const rowData = [temp[0], emailValue];:首先构建包含日期和Email的基础行数据。…temp.slice(2).map(f => f[i]):temp.slice(2):从temp数组中截取从第三个元素(索引为2)开始的所有元素。这些元素应该都是对应其他列的数据数组(例如[‘name1’, ‘name2’], [‘col3_row1’, ‘col3_row2’])。.map(f => f[i]):遍历这些数据数组f,并取出每个数组中索引为i的元素。这样就得到了当前行所有额外列的值。…:展开运算符将这些值添加到rowData数组中,形成完整的当前行数据。
重要提示:
此修改假设您的HTML表单和Google Sheet的表头已同步更新以包含所有新增列。Google Sheet的表头行必须与HTML表单的name属性保持一致,才能正确映射数据。
示例 HTML 结构
为了让e.parameters能够收集到多行数据,HTML中的输入字段需要具有相同的name属性。例如:
| Name | + | |
|---|---|---|
| X | ||
| X |
上述HTML代码中的关键在于,每一行中的Email和Name输入框都使用相同的name属性(name=”Email”和name=”Name”)。当表单提交时,e.parameters会收集所有这些同名输入框的值,并将其作为数组提供。
注意事项与部署
Google Sheet 表头一致性: 确保您的Google Sheet第一行表头与HTML表单中input元素的name属性严格匹配。Web App 重新部署: 每当您修改了Google Apps Script代码后,必须将Web App部署为新版本。否则,您的更改将不会生效。在Apps Script编辑器中,点击“部署” -> “管理部署”。选择您的Web App部署,点击铅笔图标编辑。在“版本”下拉菜单中选择“新建版本”,然后点击“部署”。
总结
通过将Google Apps Script中的e.parameter替换为e.parameters,并相应地重构数据处理逻辑,我们可以有效地解决HTML动态表格多行数据无法完整保存到Google Sheet的问题。理解e.parameters的工作原理以及如何将其转换为适合setValues方法的多维数组是实现此功能的关键。务必记住在每次代码修改后重新部署Web App以应用更改。
以上就是将HTML动态表格多行数据保存到Google Sheet的教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1539458.html
微信扫一扫
支付宝扫一扫