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

如何用Google Apps Script合并Sheet标签并追加未知长度数据到新表

问题描述

我是编程新手,对Google Apps Script完全陌生。目前我通过API拉取数据并解析为数组,存入Sheet中——列数固定,但行数随响应结果变化。我用for循环遍历调用列表,每个调用创建一个新Sheet标签,想保留这种方式区分不同响应数据。现在需要把每个Sheet的数据合并到一个总Sheet里,保留表头,但不知道怎么获取要合并的范围(行数未知),自己尝试时要么数据覆盖要么不完整,搜到的都是预定义范围的方案。

原示例代码:

//call the API for each meeting
function callAPI(tokenKey) 
{
  //declare the set of meeting IDs as an array
  var meetingIDSets = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
  var meetingNames = ["Name1", "Name2", "Name3", "Name4", "Name5", "Name6", "Name7", "Name8", "Name9", "Name10", "Name11"];

  //run through each meeting ID and make an API call to generate the attendance report
  for (var i = 0; i < meetingIDSets.length; i++)
  {
    //get the current sheet to place data into
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    //create the new sheet to place data into
    var currentSheet = ss.insertSheet();
    //rename sheet name to match the meeting owner
    currentSheet.setName(meetingNames[i]);

    //call the API to get attendance report for each given meeting ID using the provided access token
    getAttendanceReport(meetingIDSets[i], tokenKey, currentSheet, meetingNames);
  }
  // 调用合并函数
  mergeSheets();
}

//call the API to pull the attendance report
function getAttendanceReport(meetingID, token, sheet, hosts) 
{
  //declare participant join and leave time variables
  var joinTime = "";
  var leaveTime = "";

  //declare duration of participant attendance
  var duration = 0;
  //declare the name of the participant
  var name = "";
  //declare the email of the participant
  var email = "";

  //set the API URL to be called
  var URL_STRING = "https://apiwebsite.com/meetings/" + meetingID + "/participants?page_size=300";

  //access the response and parse it into a json file
  const authHead = { 'method' : 'GET', 'headers' : {'Authorization' : 'Bearer ' + token}, muteHttpExceptions: true};
  var response = UrlFetchApp.fetch(URL_STRING, authHead);
  var json = response.getContentText();
  var data = JSON.parse(json);

  // 直接赋值participantArray,不用循环
  var participantArray = data.participants || [];

  //title the columns in the sheet
  const headers = ["Host", "Name", "Join Time", "Leave Time", "Duration", "Email"];
  sheet.getRange(1, 1, 1, headers.length).setValues([headers]);

  //using a for loop, assign each response data point to its respective variable, then assign that value to the intended cell
  var rows = [];
  for (var i = 0; i < participantArray.length; i++) 
  {
    // 通过数组索引匹配hostName,替代switch更简洁
    var hostIndex = meetingIDSets.indexOf(meetingID);
    var hostName = hostIndex !== -1 ? meetingNames[hostIndex] : "unknown";

    //assign the current index variables
    name = participantArray[i].name;
    joinTime = participantArray[i].join_time;
    leaveTime = participantArray[i].leave_time;
    email = participantArray[i].user_email;
    duration = participantArray[i].duration;

    // 把数据存入数组,最后一次性写入,提升性能
    rows.push([hostName, name, joinTime, leaveTime, duration, email]);
  }

  // 批量写入数据,比逐个setValue高效
  if (rows.length > 0) {
    sheet.getRange(2, 1, rows.length, rows[0].length).setValues(rows);
  }
}
解决方案:新增合并函数

在现有代码基础上添加以下函数,它会自动处理动态数据范围的合并需求:

// 合并所有数据Sheet到总Sheet的函数
function mergeSheets() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var mergedSheetName = "合并数据";
  var mergedSheet = ss.getSheetByName(mergedSheetName);

  // 如果合并Sheet不存在,创建它并写入表头
  if (!mergedSheet) {
    mergedSheet = ss.insertSheet(mergedSheetName);
    // 从第一个数据Sheet获取表头(跳过合并Sheet本身)
    var firstDataSheet = ss.getSheets().find(sheet => sheet.getName() !== mergedSheetName);
    if (firstDataSheet) {
      var headerRange = firstDataSheet.getRange(1, 1, 1, 6);
      headerRange.copyTo(mergedSheet.getRange(1, 1), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
    }
  }

  var startRow = mergedSheet.getLastRow() + 1; // 定位合并Sheet的下一个空行

  // 遍历所有Sheet,跳过合并Sheet
  ss.getSheets().forEach(function(sheet) {
    var sheetName = sheet.getName();
    if (sheetName === mergedSheetName) return;

    // 自动获取当前Sheet的有效数据范围(包含所有有数据的行和列)
    var dataRange = sheet.getDataRange();
    var dataValues = dataRange.getValues();

    // 跳过表头,只取数据行(从第2行开始)
    var dataRows = dataValues.slice(1);
    if (dataRows.length === 0) return;

    // 批量写入到合并Sheet的对应位置
    mergedSheet.getRange(startRow, 1, dataRows.length, dataRows[0].length).setValues(dataRows);
    // 更新下一个空行的位置
    startRow += dataRows.length;
  });
}
关键说明
  • 自动获取数据范围:getDataRange()方法会自动识别Sheet内所有包含数据的区域,无需预先指定行数或列数,完美适配动态数据量的场景。
  • 批量写入优化:将原代码中逐个单元格setValue()的操作改为先把数据存入二维数组,再用setValues()一次性写入,能显著提升脚本执行效率,避免因频繁操作单元格导致的超时问题。
  • 表头唯一处理:合并时仅在总Sheet的第一行写入一次表头,后续所有数据Sheet只粘贴内容行,确保总Sheet表头不重复。
  • 动态空行定位:通过getLastRow()获取总Sheet最后一行有数据的位置,加1即为下一个可写入的空行,彻底解决数据覆盖或遗漏的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 20:41:07