如何格式化 UnprotectedRanges?

How to format UnprotectedRanges?

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

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

既然你说你想以同样的方式对待所有未受保护的 Range,我建议你构造一个 RangeList from the possibly-disjoint Ranges and then make a single call to 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(...);
  ...
});
...

如果您需要以不同方式设置每个范围的格式,此方法可能很有用。

参考资料

问题:

有两种保护方式1:

  • RANGE - 仅保护特定范围。
  • SHEET - 保护整个 sheet,但有例外。

如果您使用 sheet 保护,您还可以使用 UI 从 sheet 保护中排除(除外)某些范围(所谓的未保护范围)。然后可以使用 protection.getUnprotectedRanges()2. Sheet protection is better for what you want to do and this 充分解释这些未受保护的范围。但是,sheet 中未受保护的范围无法轻易检索到,其中某些范围使用“范围保护”进行了保护。

可能的解决方案:

  • 仅在受保护范围内为整个 sheet 和 clearFormat/restore 格式着色。

片段:

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