首页 > web前端 > js教程 > 正文

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

心靈之曲
发布: 2025-12-01 14:51:01
原创
687人浏览过

将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 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”字段的值,导致只有一行数据被处理。

修正后的 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、Java、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的教程的详细内容,更多请关注php中文网其它相关文章!

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号