将HTML动态表格多行数据保存到Google Sheet的教程


将HTML动态表格多行数据保存到Google Sheet的教程

本教程旨在解决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 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”字段的值,导致只有一行数据被处理。

修正后的 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()
  }
}

代码解析:

PHP的使用技巧集 PHP的使用技巧集

PHP 独特的语法混合了 C、J*a、Perl 以及 PHP 自创新的语法。它可以比 CGI或者Perl更快速的执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML文档中去执行,执行效率比完全生成HTML标记的CGI要高许多。下面介绍了十个PHP高级应用技巧。 1, 使用 ip2long() 和 long2ip() 函数来把 IP 地址转化成整型存储到数据库里

PHP的使用技巧集 440 查看详情 PHP的使用技巧集
  1. 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']]。
  2. 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']]。
  3. 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属性。例如:

<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会收集所有这些同名输入框的值,并将其作为数组提供。

注意事项与部署

  1. Google Sheet 表头一致性: 确保您的Google Sheet第一行表头与HTML表单中input元素的name属性严格匹配。
  2. 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的教程的详细内容,更多请关注其它相关文章!


# 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

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.