You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Apps Script批量获取Google Drive多份表单响应并写入Spreadsheet

需求可行性结论

该需求完全可以通过Google Apps Script实现,无需额外接入第三方服务。

现有代码失效原因

appendRow(form.getItemResponses()) 无法正常写入数据的核心问题有两点:

  • 方法调用层级错误:getItemResponses() 是单条提交响应(FormResponse对象)的内置方法,直接在Form表单实例上调用会直接抛出「方法不存在」的错误,无法获取有效数据。
  • 传入参数类型不符合要求:appendRow() 仅接收一维基础类型数组,数组中每个元素对应新行的一列,仅支持字符串、数字、时间、布尔值这类可直接写入单元格的基础类型。即使你从单条响应对象上取到getItemResponses()的返回值,它也是一组ItemResponse类的实例对象,封装了题目ID、题型、响应值等结构化属性,不是可直接写入的纯值,直接传入只会写入无意义的对象标识或空值。
正确实现方案

你的场景里每份副本表单都预设了不可编辑的单选项作为唯一标识,不需要从用户提交内容里提取该字段,直接从表单题目配置中读取即可,避免不同表单响应混淆。完整实现逻辑如下:

  • 提前配置结果表格地址、已收集的表单ID列表
  • 遍历每个表单ID,通过Form服务打开表单(Drive服务仅能读取文件元数据,无法获取表单响应结构,必须配合FormApp使用)
  • 读取当前表单预设的唯一标识字段值
  • 拉取当前表单所有提交记录,将每条记录处理为基础值组成的一维数组,再调用appendRow()写入表格

可直接参考以下可运行代码,替换对应配置项即可:

function syncAllFormResponsesToSheet() {
  // 配置项 - 替换为你自己的资源信息
  const TARGET_SPREADSHEET_ID = '替换为存储结果的Google表格ID';
  const TARGET_SHEET_NAME = '表单响应汇总';
  const ID_FIELD_TITLE = '替换为你设置的表单ID字段的题目标题';
  // 替换为你已经收集完成的所有副本表单ID数组
  const formIdList = ['表单ID1', '表单ID2', '表单ID3' /* 补全剩余200+表单ID */];

  const sheet = SpreadsheetApp.openById(TARGET_SPREADSHEET_ID).getSheetByName(TARGET_SHEET_NAME);
  // 首次运行写入表头,表头顺序和后续写入的内容顺序保持一致即可,已写入表头可注释掉下一行
  if (sheet.getLastRow() === 0) {
    sheet.appendRow(['表单唯一标识', '提交时间', '题目1', '题目2', '题目3' /* 按实际表单题目补全 */]);
  }

  // 遍历所有表单拉取响应
  formIdList.forEach(formId => {
    try {
      const form = FormApp.openById(formId);
      // 直接从表单题目配置中读取预设的唯一标识值,无需依赖用户提交
      const idFieldItem = form.getItems(FormApp.ItemType.MULTIPLE_CHOICE)
        .find(item => item.getTitle() === ID_FIELD_TITLE)
        .asMultipleChoiceItem();
      const formIdentifier = idFieldItem.getChoices()[0].getValue();

      // 拉取当前表单所有提交记录
      const allResponses = form.getResponses();
      allResponses.forEach(response => {
        // 初始化行数据,先放入表单标识、提交时间
        const rowData = [formIdentifier, response.getTimestamp()];
        // 遍历单条提交的所有题目响应,提取实际值
        response.getItemResponses().forEach(itemRes => {
          // 跳过ID字段,避免重复写入
          if (itemRes.getItem().getTitle() === ID_FIELD_TITLE) return;
          // 调用getResponse()拿到用户提交的实际内容,推入行数据数组
          rowData.push(itemRes.getResponse());
        });
        // 此时rowData是符合要求的基础值一维数组,可正常写入
        sheet.appendRow(rowData);
      })
    } catch (err) {
      // 单个表单读取失败时打印日志,不中断整体遍历流程
      console.log(`表单[ID:${formId}]读取失败:${err.message}`);
    }
  })
}
优化注意事项
  • 如果表单包含多选题,getResponse()会返回选项组成的数组,直接写入单元格会自动用逗号拼接,需要拆分多列展示可单独加逻辑处理。
  • 200+表单如果累计提交量较大,单次执行可能触发Apps Script 6分钟执行时长限制,可以给脚本设置定时触发器,同时记录已同步的响应ID,避免重复写入。
  • 如果副本表单是通过脚本批量生成的,可以在生成环节直接把表单ID、对应标识值提前写入结果表,省去后续遍历表单读取标识的步骤,执行效率更高。

内容的提问来源于stack exchange,提问作者kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 18:39:34