Google Sheets+Apps Script:多表数据合并无法保留源表顺序问题
在Google Sheets中按源表顺序合并多工作表数据并追加新数据
需求说明
你需要实现以下目标:
- 将多个工作表(如Assessor 1至Assessor 6)的数据合并到名为
Approver的汇总表中 - 保持源工作表的先后顺序,同一源表的所有条目必须集中在一起
- 每日新增数据(标记为
AB)需追加到汇总表现有数据的下方 - 当前编写的Apps Script无法维持源表顺序,导致同一源表的条目被拆分
现有代码问题分析
你的代码在遍历源表时,将所有源表的A标记数据存入prevData,所有AB标记数据存入newData,最终会导致所有A记录先按源表顺序出现,然后所有AB记录再按源表顺序出现——这就把同一源表的A和AB数据拆分开了,违背了“同一源表条目集中”的核心要求。
解决方案
方案1:每日追加新增数据(仅AB标记,按源表顺序)
此方案会按源表顺序遍历,提取每个表的新增数据(AB标记),并依次追加到汇总表末尾,保证同一源表的新增数据集中,整体符合源表顺序。
function appendNewDataBySourceOrder() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const destSheet = ss.getSheetByName("Approver"); const sourceSheetNames = ["Assessor 1", "Assessor 2", "Assessor 3", "Assessor 4", "Assessor 5", "Assessor 6"]; // 获取汇总表最后一行,用于定位追加位置 let destLastRow = destSheet.getLastRow(); // 按预设顺序遍历每个源表 sourceSheetNames.forEach(sheetName => { const sourceSheet = ss.getSheetByName(sheetName); if (!sourceSheet) return; // 跳过不存在的工作表 if (sourceSheet.getLastRow() < 2) return; // 跳过无数据的工作表 // 提取指定范围的数据(第2行开始,第19列起,共30列) const dataRange = sourceSheet.getRange(2, 19, sourceSheet.getLastRow() - 1, 30); const dataValues = dataRange.getValues(); // 筛选当前源表的新增数据 const newDataFromSource = dataValues.filter(row => row[0] === "AB"); // 追加当前源表的新增数据到汇总表 if (newDataFromSource.length > 0) { destSheet.getRange(destLastRow + 1, 1, newDataFromSource.length, newDataFromSource[0].length).setValues(newDataFromSource); destLastRow += newDataFromSource.length; // 更新汇总表最后一行位置 } }); }
方案2:全量合并所有数据(按源表顺序,同一源表条目集中)
如果需要重新生成完整的汇总表,保证每个源表的所有有效数据(A和AB标记)集中在一起,按源表顺序排列:
function fullMergeBySourceOrder() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const destSheet = ss.getSheetByName("Approver"); const sourceSheetNames = ["Assessor 1", "Assessor 2", "Assessor 3", "Assessor 4", "Assessor 5", "Assessor 6"]; // 清空汇总表现有数据(保留第1行表头) if (destSheet.getLastRow() > 1) { destSheet.getRange(2, 1, destSheet.getLastRow() - 1, destSheet.getLastColumn()).clearContent(); } let mergedData = []; // 按预设顺序遍历源表,收集有效数据 sourceSheetNames.forEach(sheetName => { const sourceSheet = ss.getSheetByName(sheetName); if (!sourceSheet) return; if (sourceSheet.getLastRow() < 2) return; const dataRange = sourceSheet.getRange(2, 19, sourceSheet.getLastRow() - 1, 30); const dataValues = dataRange.getValues(); // 筛选当前源表的有效数据(可根据需求调整筛选条件) const validDataFromSource = dataValues.filter(row => row[0] === "A" || row[0] === "AB"); // 将当前源表数据加入合并数组,保证同一源表数据集中 mergedData = mergedData.concat(validDataFromSource); }); // 将合并后的数据写入汇总表 if (mergedData.length > 0) { destSheet.getRange(2, 1, mergedData.length, mergedData[0].length).setValues(mergedData); } }
关键说明
- 维持源表顺序:通过
forEach按sourceSheetNames数组的固定顺序遍历源表,确保先处理的源表数据先写入汇总表 - 同一源表条目集中:每个源表的目标数据在遍历过程中被集中收集或直接追加,不会与其他源表的数据混合
- 性能优化:方案2先将所有数据收集到数组再一次性写入,减少Spreadsheet API调用次数,提升运行效率
内容的提问来源于stack exchange,提问作者Dae-voo Kim
相关产品推荐
相关产品推荐

