将Google表格标签锁定到位

时间:2019-01-15 11:54:18

标签: google-apps-script google-sheets

是否可以为用户提供对Google工作表的编辑访问权限,但阻止他们更改底部工作表标签的顺序?

致谢

1 个答案:

答案 0 :(得分:4)

您不能阻止工作表被编辑者重新排序,但是您当然可以将它们重新排序。如果有人查看available Spreadsheet events,则可能会认为“更改时”事件将触发重新排序的工作表。截至2019年1月,情况并非如此。但是,您仍然可以使用已安装的触发器绑定多个事件(即“更改”,“编辑”和“打开”),并通过使用Spreadsheet Service或{{3 }},即advanced service Sheets

最有效的重新排序是通过Sheets API完成的,而无需修改用户的活动工作表,但是如果您每个API调用对单个工作表的重新排序次数超过一个,则它会出现UI刷新错误(重新排序发生在Google端,而浏览器用户界面未更新)。每个API调用平均可以在大约100-230毫秒内完成重新排序。

以下示例代码并不是API效率最高的示例,目的是更易于理解和实现:

function enforceOrder(eventObject) {
  const requiredSheetOrder = ['name of first sheet', 'name of second sheet' ....];
  // Get the workbook ID for the Sheets REST API.
  const id = (eventObject ? eventObject.source : SpreadsheetApp.getActive()).getId();
  // You must enable the advanced service prior to using this code.
  // https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services
  const state = Sheets.Spreadsheets.get(id, {fields: "sheets/properties(title,sheetId,index)"});

  // Collect the requests to be made.
  const batchRequests = [];
  requiredSheetOrder.forEach(function (title, i) {
    var rq = {
      fields: "index",
      properties: { index: i }
    };
    var matched = state.sheets.filter(function (s) { return s.properties.title === title; })[0];
    if (matched)
    {
      rq.properties.sheetId = matched.properties.sheetId;
      // If any preceding sheets are being reordered, or this sheet
      // is not in the right position, we must set this sheet's index.
      if (batchRequests.length || i !== matched.properties.index)
        batchRequests.push({ updateSheetProperties: rq });
    }
    else
      console.warn("No sheet found with required name '" + title + "'");
  });

  // Send updates, if there were any to send.
  if (batchRequests.length)
  {
    // Sheets.Spreadsheets.batchUpdate({ requests: batchRequests }, id);
    // The above wholly-batch line induces the mentioned UI bug.
    // The below one-by-one update does not:
    batchRequests.forEach(function (r) {
      Sheets.Spreadsheets.batchUpdate({ requests: [r] }, id);
    });
    console.log("Reordered " + batchRequests.length + " sheets");
  }
  else
    console.log({message: "No-op", desired: requiredSheetOrder, current: state.sheets });
}

可以通过比较当前工作表状态和所需结果状态,并计算最小索引规格来确定工作表顺序的API效率(即,考虑将工作表放置在索引{{1}上) }将当前位于索引i的工作表移至i)。

PS:使用电子表格服务时,表格的位置/电子表格索引基于1。当使用高级服务/ REST API时,工作表的位置索引始终为0基。