
本教程旨在解决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 2025 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的使用技巧集
PHP 独特的语法混合了 C、J*a、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的教程的详细内容,更多请关注其它相关文章!
# html
# js
# json
# go
# es6
# 第一个
# 足疗店营销推广课程
# 使用技巧
# 面向对象
# 重构
# 迁安市网站建设推广
# 福田门户网站推广服务
# 营销推广图片大全集
# SEO北京酒店拍照
# pc网站建设理论依据
# 营销推广自我总结范文
# 上海SEO学习壁纸高清
# dede网站建设实训
# 品牌seo布局
# 数据结构
# 组中
# 多维
# 您的
# 行数
# 表单
# red
# 表单提交
# html表单
# 邮箱
# google
# ai
# 后端
# app
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
顺丰快递在线查询系统 顺丰快递官方查单入口
b站如何剪辑视频_b站必剪app使用教程
个人所得税办理入口 个人所得税综合所得年度汇算入口
消除网页顶部意外空白线:CSS布局常见问题与解决方案
C++ switch case字符串_C++如何实现字符串switch匹配
苹果官网国补入口在哪
Golang如何使用crypto/md5生成哈希_Golang MD5哈希生成方法
微信网页版在线登录 微信网页版在线使用入口
《宝可梦大集结》S4冠军之路开始时间介绍
C++中std::thread和std::async的区别_C++并发编程与线程与异步任务比较
精通VS Code多光标编辑以实现闪电般快速的修改
背部总是隐隐作痛怎么回事 背痛如何改善
韩剧圈正版官网入口_韩剧圈官方指定登录
谷歌邮箱怎么换绑定邮箱Gmail安全备份邮箱修改方法
如何解决Casbin日志与应用日志不统一的问题,使用casbin/psr3-bridge实现无缝集成
Sublime怎么自动添加CSS前缀_Sublime安装Autoprefixer插件
《磁力猫》最好用的磁官网
Win10截图远程协助 Win10远程桌面截屏法【场景应用】
《edge浏览器》关闭翻译功能方法
《大周列国志》皇帝律令功能介绍
TikTok视频播放中断怎么办 TikTok播放异常修复方法
感染了幽门螺杆菌一定会导致胃癌吗?蚂蚁庄园今日答案最新11.30
钉钉任务无法提醒如何处理 钉钉任务提醒优化方法
composer 提示 "requires ext-soap" 缺少 SOAP 扩展怎么办?
解决Flex容器横向滚动内容截断与偏移问题
excel怎么计算平均值 excel平均函数*ERAGE使用教学
win11怎么设置默认终端为Windows Terminal Win11替代CMD和PowerShell【技巧】
动漫岛汉化官网网 动漫岛官方动漫汉化地址
在J*a中如何实现在线问答与评分系统_问答评分项目开发方法说明
《雷电模拟器》自动点击设置方法
《绝区零》2.3前瞻|直播|内容介绍
PHP与SQL实践:高效实现数据复制与特定列值修改
使用Python和GBGB API高效抓取指定日期范围和赛道比赛结果教程
b站怎么设置动态仅粉丝可见_b站动态粉丝可见设置方法
c++如何实现一个简单的RPC框架_c++远程过程调用原理与实践
Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题
iphone16系列配置参数介绍
12306售票时间最新规定 | 网上订票和车站窗口时间一样吗
《火影忍者:木叶高手》快速升级攻略
《U校园》学生登录入口2025
Dagster资产间数据传递与用户配置管理教程
mysql中外键约束如何使用_mysql FOREIGN KEY操作
Go App Engine 项目结构与包管理深度指南
win11关机几秒又自己开机 Win11关机自动重启问题修复
sublime如何撤销关闭的标签页_sublime重新打开已关闭文件技巧
CSS如何在页面中引入重置样式_使用Normalize.css或Reset.css统一浏览器默认样式
mail.qq.com登录入口 QQ邮箱网页版直达
如何在mysql中比较InnoDB和MyISAM区别
实时数据流中高效查找最小值与最大值
J*aScript与HTML元素交互:图片点击事件与链接处理教程
2025-12-01
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。