问题
I have a Google Sheet that does dynamic grouping with a script. I am looking for a function that gets rid of all those Groups in the sheet again.
Similar to expandAllColumnGroups, I would like to have a function called removeAllColumnGroups
- but it seems there is no such function available.
My current approach is very slow and cumbersome. I did quite some research but could not even find a way to get all the columnGroups
or at least the start-column-IDs in a sheet, so I iterate over every column and literally try to remove the group if there is one, as there is no way to tell if a group exits. Unfortunately for about 90 columns this takes ages (minutes, really)...
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
//remove all column-groups
var group = null;
var maxCol = sh.getMaxColumns();
for(var c = 1; c <= maxCol; c++) {
try {
group = sh.getColumnGroup(c, 1); // Try to get group
group.remove(); // Remove the group
} catch (e) {
//Logger.log("No Group at ColIndex "+c);
}
}
Any ideas would be really appreciated. Thanks in advance!
回答1:
Expanding on my comment re: use of the Google Sheets REST API to access and modify row/column groupings:
Row/Column groups are metadata associated with a Sheet
resource, and as such can be obtained for all sheets in a workbook with a single HTTP request to spreadsheets.get, with the appropriate fields
specification:
GET https://sheets.googleapis.com/v4/spreadsheets/{YOUR_SPREADSHEET_ID}?fields=sheets(columnGroups%2Cproperties(sheetId%2Ctitle)%2CrowGroups)&key={YOUR_API_KEY}
Demo link
The above request returns an object with a sheets
property, which is an array of objects (1 per sheet in the spreadsheet) having 3 properties: rowGroups
, columnGroups
, and properties
. The group properties are arrays of DimensionGroup objects, while the properties
object contains the sheet's gridId/sheetId, which you need for identifying the sheet in various API requests, and its name (which may be useful for your own script logic).
To delete every row/column group, you need to issue as many DeleteDimensionGroupRequests to do so as the maximum depth
returned in your query's groups. If you do not specify the indices of the DimensionRange in your request, this is interpreted as the whole range of the spreadsheet (all rows / all columns, depending on direction).
An example request (requires OAuth authentication, not just API key):
POST https://sheets.googleapis.com/v4/spreadsheets/{YOUR SPREADSHEET ID}:batchUpdate?fields=replies%2FdeleteDimensionGroup
{
"requests": [
{
"deleteDimensionGroup": {
"range": {
"sheetId": "{SHEET 1 ID}",
"dimension": "COLUMNS"
}
}
},
{
"deleteDimensionGroup": {
"range": {
"sheetId": "{SHEET 2 ID}"
"dimension": "COLUMNS",
}
}
},
...
]
}
Demo link
Each delete request has a reply response, and that response will be very similar to the initial response you got for the row/column groups from the initial query. If you knew the gridIds beforehand, you could forgo the initial query and use a while loop to keep sending delete requests while the response contains a dimension group.
To use these methods with Google Apps Script, you can either use UrlFetchApp
with raw URL resources, or take advantage of the available "advanced service" client library Sheets (which must first be enabled). Both methods require you to enable use of the Sheets API from your script's Google Cloud Platform project page.
An example using the enabled client library Sheets
:
function removeAllGroups() {
const wb = SpreadsheetApp.getActive(),
wbId = wb.getId();
const initial = Sheets.Spreadsheets.get(wbId, {
fields: "sheets(columnGroups,properties(sheetId,title),rowGroups)"
});
// Determine the maximum depth of row & column groups on each sheet in the workbook.
const maxDepths = {row: {}, col: {}};
initial.sheets.forEach(function (s) {
// if (s.properties.title ... (could write logic to do this only for certain sheets)
var sId = s.properties.sheetId;
if (s.columnGroups && s.columnGroups.length)
maxDepths.col[sId] = s.columnGroups.reduce(dgMaxDepth_, 0);
if (s.rowGroups && s.rowGroups.length)
maxDepths.row[sId] = s.rowGroups.reduce(dgMaxDepth_, 0);
});
// Add all delete requests to an array
const rqs = [];
for (var rqType in maxDepths) {
for (var sheetId in maxDepths[rqType]) {
addDeleteDGRequests_(rqs, rqType, sheetId, maxDepths[rqType][sheetId]);
}
}
// Send all requests.
if (rqs.length) {
const replies = Sheets.Spreadsheets.batchUpdate({requests: rqs}, wbId);
console.log({message: "Batch response", response: replies});
}
}
// Callback for Array#reduce
function dgMaxDepth_(val, dg, i, allDGs) {
return Math.max(val, dg.depth);
}
function addDeleteDGRequests_(requests, rqType, sheetId, num) {
const dim = rqType === "col" ? "COLUMNS" : "ROWS";
while (num > 0) {
var rq = {
deleteDimensionGroup: {
range: { sheetId: sheetId,
dimension: dim }
}
};
requests.push(rq);
--num;
}
}
Resources:
- Google APIs Explorer - Sheets API
- Google Sheets REST API
- Enable Advanced Services
- Array#reduce
- Array#forEach
来源:https://stackoverflow.com/questions/52480395/remove-all-grouped-rows-columns-in-a-spreadsheet