新闻中心

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

2025-12-01
浏览次数:
返回列表

将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  # 第一个  # 数据结构  # 组中  # 如何实现  # 多维  # 您的  # 递归  # 行数  # 表单  # red  # html表单  # 邮箱  # google  # ai  # 后端  # app  # go  # json  # js  # es6  # 表单提交  # seo换词大屏  # seo模板同质化  # seo究竟要做些什么  # 甘泉全网营销推广中心  # 怀化长沙seo优化团队  # 房山网站建设和优化  # 渠道关键词排名规则  # 来源中国博客seo  # 石排网站推广公司  # seo爬虫怎么爬  # 使用技巧 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: Angular中单选按钮的正确使用与常见陷阱解析  企业名称高精度匹配:N-gram方法在结构相似性分析中的应用  微博网页版首页入口 微博电脑端官网登录链接  手机屏幕碎了但能正常使用怎么办 手机外屏碎裂的修复建议  b站怎么取消点赞_b站点赞取消操作方法  《刺客信条:影》PS5 Pro和Switch 2画面对比  漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站  蛙漫安全无毒 官方认证的绿色入口  win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  Mac怎么查看崩溃日志_Mac控制台错误报告分析  HTML空白字符处理机制:渲染、DOM与编码实践  Win10自动更新怎么关闭 Win10永久关闭系统更新的两种方法【终极版】  GemBox Document HTML转PDF垂直文本渲染问题及解决方案  如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension  C#中解析不规范的HTML为XML 常见的坑与解决办法  Fabric模组开发:自定义物品与物品组的现代管理方法  漫蛙漫画官方主页入口 漫蛙MANWA网页直达访问链接  漫蛙Manwa2官网入口地址分享 漫蛙漫画PC版永久访问通道  html怎么在cmd下运行php文件_cmd运行html中php文件方法【教程】  outlook中文官网入口地址 outlook官方中文版直达首页链接  印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】  电脑IP地址怎么查 查看本机IP地址的几种方法  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  多闪网页版在线观看免费入口_多闪官网访问入口  在哪找SublimeJ远程工具_SFTP插件配置教程  win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】  向日葵客户端怎么进行远程CentOS控制_向日葵客户端远程CentOS控制操作教程  俄罗斯方块最新版入口 俄罗斯方块在线玩官网入口  C++如何实现异步操作_C++11使用std::future和std::async进行异步编程  Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖  Django通过AJAX异步上传图片并保存至模型的完整指南  零跑汽车11月交付量达70327台 实现连续9个月正增长  Eclipse怎么运行工程_Eclipse工程运行配置说明  解决Django多数据库/多Schema环境下外键迁移问题  Tabulator表格中精确实现日期时间排序的指南  将HTML动态表格多行数据保存到Google Sheet的教程  sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置  Python实时数据流中的动态最值查找策略  海量存储:机器视觉智能化的核心基石  蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台  深入理解J*a编译器的兼容性选项:从-source到--release  4399网页游戏电脑版全新入口 4399电脑端在线玩指南  顺丰快件物流信息 官方网站查询入口  AngularJS $http POST请求数据传递与Go后端接收实践  在FastAPI中利用lifespan与依赖注入高效管理Redis连接池  J*aScript数组对象转换:按指定键分组与值收集  J*aScript打印功能_j*ascript输出控制  Yandex免登录网页版地址 Yandex搜索引擎官方访问入口  EMS快递官网app_中国邮政速递物流手机客户端 

搜索