求可按内容匹配自动分组行的Google Sheets脚本(现有分组代码无效)
解决Google Sheets分组脚本无效问题
需求说明
- 会计软件导出的电子表格数据量大,需按规则分组:找到标题为
Total [原板块标题]的行,将原标题行到Total行之间的所有子项行分组到原标题行下 - 示例数据结构:
Discounts & promotions Discounts & promotions - Facebook (via Shopify) Discounts & promotions - Shopify - name Discounts & promotions - Shopify - name - gift card giveaways Total Discounts & promotions
现有问题
已实现removeAllGroups1(移除所有分组)和collapse(折叠所有分组)函数,但groupRows函数无法按规则完成分组。
现有代码
function removeAllGroups1() { const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName("Daily"); const rg = sh.getDataRange(); const vs = rg.getValues(); vs.forEach((r, i) => { let d = sh.getRowGroupDepth(i + 1); if (d >= 1) { sh.getRowGroup(i + 1, d).remove() } }); } function groupRows() { const sheet = SpreadsheetApp.getActiveSheet(); const range = sheet.getRange("A1:A" + sheet.getLastRow()); const values = range.getValues(); let previousValue = ""; let groupStartRow = 1; for (let i = 0; i < values.length; i++) { const currentValue = values[i][0]; // Check if the current value is a "Total" version of the previous value if (currentValue.startsWith("Total ") && currentValue.substring(6) === previousValue) { // Group the current row with the previous row sheet.getRange(i + 1, 1).shiftRowGroupDepth(1); } else { // Reset the group start row groupStartRow = i + 1; } previousValue = currentValue; } } function collapse() { const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName('Daily'); let lastRow = sh.getDataRange().getLastRow(); for (let row = 1; row < lastRow; row++) { let depth = sh.getRowGroupDepth(row); if (depth < 1) continue; sh.getRowGroup(row, depth).collapse(); } }
问题原因与修复后脚本
原groupRows函数的核心问题:
- 仅判断Total行与前一行的匹配,未定位到板块的起始标题行
- 仅调整Total行的分组深度,未处理中间的子项行
修复后的groupRows脚本:
function groupRows() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Daily"); const lastRow = sheet.getLastRow(); const values = sheet.getRange("A1:A" + lastRow).getValues().flat(); // 记录所有板块的起始行与对应Total行的位置 const sectionMap = new Map(); for (let i = 0; i < values.length; i++) { const cellValue = values[i].trim(); if (cellValue.startsWith("Total ")) { const originalTitle = cellValue.substring(6).trim(); // 向上查找匹配的原标题行 for (let j = i - 1; j >= 0; j--) { if (values[j].trim() === originalTitle) { sectionMap.set(j + 1, i + 1); // 存储行号(从1开始计数) break; } } } } // 为每个板块的子项行设置分组 sectionMap.forEach((endRow, startRow) => { // 将起始行之后、Total行之前的所有子项行归为一组 for (let row = startRow + 1; row < endRow; row++) { sheet.getRow(row).shiftRowGroupDepth(1); } }); }
使用步骤
- 运行
removeAllGroups1清空现有分组,避免干扰 - 运行
groupRows完成分组 - 运行
collapse折叠所有分组,方便查看
内容的提问来源于stack exchange,提问作者Shawna Gwin Krasts
相关产品推荐
相关产品推荐

