如何用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
相关产品推荐
相关产品推荐

