【问题标题】:How to format UnprotectedRanges?如何格式化受保护的范围?
【发布时间】:2019-03-29 13:51:40
【问题描述】:

我想在电子表格中的每个单元格周围放置一个红色边框,该电子表格没有为单元格或单元格范围分配任何保护。我知道如何设置边框,但如何访问未受保护范围的格式?

function wtf() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var protection = sheet.protect();
var unprotected = protection.getUnprotectedRanges();  
  for (var i = 0; i < unprotected.length; i++) {
  ui.alert('this cell is unprotected');
  } 
}

【问题讨论】:

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


【解决方案1】:

问题:

有两种类型的保护1:

  • RANGE - 仅保护某些范围。
  • SHEET - 保护整个工作表,但有例外。

如果您使用工作表保护,您还可以使用 UI 从工作表保护(所谓的未受保护范围)中排除(除外)某些范围。然后可以使用protection.getUnprotectedRanges()2 检索这些不受保护的范围。工作表保护更适合您想要做的事情,answer 充分解释了这一点。但是,无法轻松检索工作表中未受保护的范围,其中某些范围使用“范围保护”进行保护。

可能的解决方案:

  • 仅在受保护的范围内为整个工作表着色并清除格式/恢复格式。

片段:

function colorUnprotectedRangesRed() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheets()[0]; //first sheet
  const prots = sh.getProtections(SpreadsheetApp.ProtectionType.RANGE); //get onlyRangeProtections
  const rngList = prots.map(function(pro) {
    return pro.getRange().getA1Notation();
  });
  sh.getRange('1:' + sh.getMaxRows()).setBorder(
    true,
    true,
    true,
    true,
    true,
    true,
    'red',
    SpreadsheetApp.BorderStyle.SOLID
  );
  //SpreadsheetApp.flush(); //flush the changes first before clearing format, if you have issues
  sh.getRangeList(rngList).clearFormat();
}

【讨论】:

    【解决方案2】:

    由于您声明要以相同的方式处理所有未受保护的Ranges,我建议您从可能不相交的Ranges 构造一个RangeList,然后对Range#setBorder 进行一次调用:

    function mark_non_protected() {
      const wb = SpreadsheetApp.getActive();
      wb.getSheets().forEach(function (sheet) {
        var pr = sheet.protect();
        var upr = pr.getUnprotectedRanges().map(function (rg) { return rg.getA1Notation(); });
        // Since some sheets may not have any unprotected ranges, don't try to create an empty RangeList:
        if (!upr.length)
          return;
    
        var rgl = sheet.getRangeList(upr);
        rgl.setBorder(
          true, // top
          true, // left
          true, // bottom
          true, // right
          true, // internal vertical
          true, // internal horizontal
          "red", // color name or CSS hex
          /* optional borderstyle like SpreadsheetApp.BorderStyle.DOTTED */
        );
        /** do other stuff with the unprotected ranges as a whole unit */
      });
    }
    

    另一种方法是为每个范围直接调用setBorder和其他方法:

    ...
    pr.getUnprotectedRanges().forEach(function (rg) {
      rg.setBorder(...);
      rg.someOtherMethod(...);
      ...
    });
    ...
    

    如果您需要对每个范围进行不同的格式化,这种方法可能会很有用。

    参考

    【讨论】:

    • 我设置工作表的方式可能有问题。我尝试创建一个新工作表并添加了各种范围,但我总是收到以下错误。范围必须至少有一个范围。 (第 6 行,文件“代码”)function mark_non_protected() { const wb = SpreadsheetApp.getActive(); wb.getSheets().forEach(function (sheet) { var pr = sheet.protect(); var upr = pr.getUnprotectedRanges().map(function (rg) { return rg.getA1Notation(); }); var rgl = sheet.getRangeList(upr); rgl.setBorder(true, null, null, null, null, null, "red", SpreadsheetApp.BorderStyle.SOLID_MEDIUM); }); }
    • @user 是的,我的回答中有一个隐含的假设,即当工作表受到保护时,每张工作表都至少有一个不受保护的范围。作为开发人员,您有责任了解并调整此代码以适应您的特定场景,包括添加错误检查。如果您无法解决错误,那么您应该提出一个经过充分研究的新问题。作为第二个提示,请考虑如何在创建 RangeList 之前首先检查是否有任何未受保护的范围
    • 在下拉菜单中的数据下,有一个菜单项“受保护的范围和工作表”,它提供了“受保护”范围的列表。没有显示“不受保护”范围的菜单项。我的工作表有一些受保护的范围和一些没有任何保护的范围。作为开发人员,我理解这一点。我仍然得到错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    相关资源
    最近更新 更多