【问题标题】:Remove all grouped rows / columns in a spreadsheet删除电子表格中的所有分组行/列
【发布时间】:2018-09-24 13:19:36
【问题描述】:

我有一个使用脚本进行动态分组的 Google 表格。我正在寻找一个能够再次摆脱工作表中所有Groups 的函数。

类似于expandAllColumnGroups,我想要一个名为removeAllColumnGroups 的函数 - 但似乎没有这样的函数可用。

我目前的方法非常缓慢且繁琐。我做了相当多的研究,但什至找不到一种方法来获取所有 columnGroups 或至少是工作表中的起始列 ID,所以我遍历每一列并从字面上 try 删除如果有一个组,则该组,因为无法判断一个组是否退出。不幸的是,对于大约 90 列,这需要很长时间(实际上是几分钟)...

  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);
    }
  }

任何想法都将不胜感激。提前致谢!

【问题讨论】:

  • 使用 Sheets API - 您可以轻松访问可用组并将其删除。
  • 感谢 cmets。你能再具体一点吗?我有点迷失在 API 文档中......这是进一步调查的正确位置吗? developers.google.com/sheets/api/reference/rest
  • @i 这对于没有公式的工作表来说是一个很好的解决方案,除非其他工作表将其用于​​公式,因为它们会出现参考错误

标签: google-apps-script google-sheets google-sheets-api


【解决方案1】:

扩展我的评论:使用 Google 表格 REST API 访问和修改行/列分组:

行/列组是与Sheet 资源关联的元数据,因此可以通过对spreadsheets.get 的单个HTTP 请求以及适当的fields 规范来获取工作簿中的所有工作表:

GET https://sheets.googleapis.com/v4/spreadsheets/{YOUR_SPREADSHEET_ID}?fields=sheets(columnGroups%2Cproperties(sheetId%2Ctitle)%2CrowGroups)&key={YOUR_API_KEY}

Demo link

上述请求返回一个具有sheets 属性的对象,该对象是一个对象数组(电子表格中的每个工作表1 个),具有3 个属性:rowGroupscolumnGroupsproperties。组属性是 DimensionGroup 对象的数组,而 properties 对象包含工作表的 gridId/sheetId,您需要在各种 API 请求中识别工作表及其名称(这可能对您自己的脚本逻辑有用) .

要删除每个行/列组,您需要发出与查询组中返回的最大depth 一样多的DeleteDimensionGroupRequests。如果您未在请求中指定 DimensionRange 的索引,则会将其解释为电子表格的整个范围(所有行/所有列,取决于方向)。

一个示例请求(需要 OAuth 身份验证,而不仅仅是 API 密钥):

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

每个删除请求都有一个reply response,该响应与您从初始查询中获得的行/列组的初始响应非常相似。如果您事先知道 gridId,则可以放弃初始查询并使用 while 循环在响应包含维度组时继续发送删除请求。


要将这些方法与 Google Apps 脚本一起使用,您可以将 UrlFetchApp 与原始 URL 资源一起使用,或者利用可用的 "advanced service" 客户端库 Sheets(必须首先启用)。这两种方法都要求您从脚本的 Google Cloud Platform project 页面启用 Sheets API。

使用启用的客户端库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;
  }
}

资源:

【讨论】:

  • 哇,非常感谢您的详细解释!赞一个!
【解决方案2】:

这是一个简单的解决方案。

function removeAllGroupsFromSheet() {
  let sheet = SpreadsheetApp.getActiveSheet();
  let lastRow = sheet.getDataRange().getLastRow();
  
  for (let row = 1; row < lastRow; row++) {
    let depth = sheet.getRowGroupDepth(row);
    if (depth < 1) continue;
    sheet.getRowGroup(row, depth).remove();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    相关资源
    最近更新 更多