Reputation: 23
I would like to group rows automatically on a google sheet based on a set of rows which changes daily as well as their length (depth of the groups). If you see the pictures below, I would like all the rows with a * in column A to be grouped together.
Here is my code where I first remove the groups that were previously there, find all the "group headers" and place them in a list called index, then I attempt to group the rows using (index, l). However the only group created is between line 4 and 5.
function GroupRows() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getSheetByName('Roadmap Live')
var range = sheet.getDataRange()
var source = sheet.getDataRange().getDisplayValues()
var vs = range.getValues()
var index = []
// remove groups before creating new ones
source.forEach((r,i)=> {
let d = sheet.getRowGroupDepth(i+1)
if (d>=1){
sheet.getRowGroup(i+1,d).remove()
}
})
//Find rows to group
for (var i = 1; i<source.length; i++){
if (source[i][0] == "-"){
// Logger.log(source[i][0])
index.push(i+1) //this collects all the rows that has * in them
}
}
Logger.log(index)
//Group rows
for(var i = 0;i<index.length-1;i++){
var rangetomodify = sheet.getRange(index[i],1)
var l = index[i+1]-index[i]-1
var k = index[i]
rangetomodify.shiftRowGroupDepth(1)
sheet.getRowGroup(index,l)
}
}
I suppose there must be some map function I should use but I'm not sure how to implement it?
Upvotes: 0
Views: 1386
Reputation: 201428
I believe your goal is as follows.
*
.In your script, it seems that index
of sheet.getRowGroup(index, l)
is an array. So, I think that an error occurs there. And also, in your script, it seems that the value of *
is not checked. I think that the reason for your current issue of However the only group created is between lines 4 and 5.
might be due to this.
In this case, how about the following sample script?
function GroupRows() {
const sheetName = "Roadmap Live"; // This is from your script.
const spreadsheet = SpreadsheetApp.getActive();
const sheet = spreadsheet.getSheetByName(sheetName);
const lastRow = sheet.getLastRow();
const values = sheet.getRange("A4:A" + lastRow).getDisplayValues();
for (let i = 4; i <= lastRow; i++) {
const d = sheet.getRowGroupDepth(i);
if (d > 0) sheet.getRowGroup(i, d).remove();
}
values.forEach(([a], i) => {
if (a == "*") {
sheet.getRange(i + 4, 1).shiftRowGroupDepth(1);
}
});
sheet.collapseAllRowGroups();
}
*
are grouped.I thought that in the current stage when the above script is run, the process cost might be a bit high. So, as another approach, in order to reduce the process cost, I would like to propose using Sheets API. The sample script is as follows.
In this case, please enable Sheets API at Advanced Google services.
function sample2() {
const sheetName = "Roadmap Live"; // This is from your script.
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName(sheetName);
const ssId = ss.getId();
const sheetId = sheet.getSheetId();
sheet.expandAllRowGroups();
const n = Sheets.Spreadsheets.get(ssId, { ranges: [sheetName] }).sheets[0].rowGroups.reduce((n, { depth }) => n < depth ? depth : n, 0);
const requests1 = Array(n).fill("").map(_ => ({ deleteDimensionGroup: { range: { sheetId, dimension: "ROWS" } } }));
const values = sheet.getRange("A4:A" + sheet.getLastRow()).getDisplayValues();
const requests2 = values.flatMap(([a], i) => a == "*" ? { addDimensionGroup: { range: { sheetId, startIndex: i + 3, endIndex: i + 4, dimension: "ROWS" } } } : []);
Sheets.Spreadsheets.batchUpdate({ requests: [...requests1, ...requests2] }, ssId);
sheet.collapseAllRowGroups();
}
Upvotes: 1