
本教程旨在解决html表单动态添加多行数据时,google apps script web app仅保存第一行数据的问题。核心解决方案是利用`e.parameters`(复数)获取所有同名输入字段的值数组,并通过修改apps script的`dopost`函数,将这些数据结构化为多行,一次性写入google sheet,从而实现多行数据的完整保存。
在构建交互式Web应用时,我们经常需要将用户在HTML表单中输入的数据保存到后端存储,例如Google Sheet。当HTML表单包含可动态添加的表格行时,一个常见的问题是:尽管用户输入了多行数据,但通过Google Apps Script部署的Web App却只能保存第一行数据。本文将深入探讨这一问题的原因,并提供详细的解决方案。
在使用Google Apps Script处理POST请求时,e.parameter对象通常用于访问表单提交的单个参数。然而,当HTML表单中存在多个具有相同name属性的输入字段(例如,一个动态表格中的多行Email输入),e.parameter[name]只会返回第一个匹配字段的值。这就是导致只有第一行数据被保存的根本原因。
为了正确处理这种情况,我们需要使用e.parameters(注意是复数),它会返回一个对象,其中每个键对应一个表单字段的name属性,而其值则是一个包含所有同名输入字段值的数组。
假设我们的HTML表单有一个动态表格,包含“Email”和“Name”两列,并且我们希望将这些数据连同提交日期一起保存到Google Sheet。
立即学习“前端免费学习笔记(深入)”;
// Updated for 2021 and ES6 standards
const 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”字段的值,导致只有一行数据被处理。
为了处理多行数据,我们需要修改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()
}
}代码解析:
PHP 独特的语法混合了 C、Java、Perl 以及 PHP 自创新的语法。它可以比 CGI或者Perl更快速的执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML文档中去执行,执行效率比完全生成HTML标记的CGI要高许多。下面介绍了十个PHP高级应用技巧。 1, 使用 ip2long() 和 long2ip() 函数来把 IP 地址转化成整型存储到数据库里
440
如果您的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()
}
}代码解析:
重要提示:
为了让e.parameters能够收集到多行数据,HTML中的输入字段需要具有相同的name属性。例如:
<form method="POST" action="YOUR_WEB_APP_URL">
<table class="proposedWork" width="100%" style="margin-top:20px">
<thead>
<th>Email</th>
<th>Name</th>
<th class="docEdit trAdd">+</th>
</thead>
<tbody>
<tr>
<td contenteditable="true">
<input name="Email" type="email" placeholder="Email" required>
</td>
<td contenteditable="true">
<input name="Name" type="name" placeholder="Name" required>
</td>
<td class="docEdit tdDelete">X</td>
</tr>
<!-- 动态添加的行也会有相同的 name="Email" 和 name="Name" -->
<tr>
<td contenteditable="true">
<input name="Email" type="email" placeholder="Email" required>
</td>
<td contenteditable="true">
<input name="Name" type="name" placeholder="Name" required>
</td>
<td class="docEdit tdDelete">X</td>
</tr>
</tbody>
</table>
<button type="submit">Send</button>
</form>上述HTML代码中的关键在于,每一行中的Email和Name输入框都使用相同的name属性(name="Email"和name="Name")。当表单提交时,e.parameters会收集所有这些同名输入框的值,并将其作为数组提供。
通过将Google Apps Script中的e.parameter替换为e.parameters,并相应地重构数据处理逻辑,我们可以有效地解决HTML动态表格多行数据无法完整保存到Google Sheet的问题。理解e.parameters的工作原理以及如何将其转换为适合setValues方法的多维数组是实现此功能的关键。务必记住在每次代码修改后重新部署Web App以应用更改。
以上就是将HTML动态表格多行数据保存到Google Sheet的教程的详细内容,更多请关注php中文网其它相关文章!
HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号