我的会计软件将最新数据导出到电子表格中,其中包含大量数据,如果不进行分组就很难分析。
我想根据与上面的行的相似性对行进行分组(或者可能基于缩进,但这可能更困难)。
例如,有一个折扣和促销部分,其中有多个子项目(有时可能会添加一个项目,因此在下面的示例中,在某个随机点可能有 4 行子内容,而不是 3 行)。底部是该部分的总计。
总计行始终具有相同的标题,并在前面附加“总计”一词。
Discounts & promotions
Discounts & promotions - Facebook (via Shopify)
Discounts & promotions - Shopify - name
Discounts & promotions - Shopify - name - gift card giveaways
Total Discounts & promotions
这里是一些示例数据的链接。
是否有一个脚本可以遍历整个工作表并按逻辑对各个部分进行分组 - 如果该行与另一行具有相同的确切内容+前面的“总计”一词,则将它们分组。
(首先我需要脚本来删除所有组 - 这是有效的,最后我需要脚本来折叠所有组,这也是有效的)
这是我尝试过的代码。电子表格中的数据没有发生任何变化。
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();
}
}
使用
Array.findIndex()
,如下所示:
function groupRows(keyRange = SpreadsheetApp.getActive().getRange('Daily!A5:A')) {
const sheet = keyRange.getSheet();
removeAllGroups_(sheet);
const rowStart = keyRange.getRow();
const keys = keyRange.offset(0, 0, sheet.getLastRow() - rowStart + 1).getDisplayValues().flat().map(k => k.trim());
const groups = [];
keys.forEach((key, startIndex) => {
const endIndex = keys.findIndex(k => k === `Total ${key}`);
if (endIndex !== -1) groups.push([rowStart + startIndex + 1, endIndex - startIndex]);
});
groups.forEach(([start, numRows]) => sheet.getRange(start, 1, numRows).shiftRowGroupDepth(1).collapseGroups());
}
function removeAllGroups_(sheet) {
sheet.getDataRange().getValues().forEach((_, index) => {
const depth = sheet.getRowGroupDepth(index + 1);
if (depth) sheet.getRowGroup(index + 1, depth).remove();
});
}