使用脚本根据另一个单元格的值取消保护范围

时间:2021-01-25 21:42:02

标签: google-apps-script google-sheets

我正在尝试为员工制定一个时间表,以将约会添加到代表日历中。目标是每天一次有 5 个约会,它会被涂黑并锁定。我曾使用过数据验证,但后来我们决定将员工姓名添加到每个单元格中的下拉列表中。由于每个单元格只能有一个数据验证规则(据我所知),我不得不使用脚本来保护/取消保护单元格。我几乎让一切正常,但我的功能似乎只保护给定的范围。当我添加 else 子句来取消保护给定 <5 个约会的范围时,它运行没有失败,但实际上并没有改变任何东西。 (我怀疑它会保护,然后立即取消保护范围。)目前,该功能仅在星期一 (B5:B27) 有效。

我使用的代码是:

function onEdit() {
  var ss = SpreadsheetApp.getActive();
  var maxAppointments = ss.getRange('G3')

  if (countMon >= maxAppointments) {
    var countMon = ss.getRange('B3').getValue();
    var mon = ss.getRange('B5:B27');
    var protectMon = mon.protect().setDescription('Protect Monday').setRangeName('monday');
    protectMon.removeEditors(protectMon.getEditors());
    protectMon.addEditors(['mgr1@domain.com', 'mgr2@domain.com', 'mgr3@domain.com']);
    if (protectMon.canDomainEdit()) {
      protectMon.setDomainEdit(false);
    }
  }
   else {
   var monProtections = ss.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.RANGE);
    for (var i = 0; i < monProtections.length; i++) {
      if ( monProtections[i].getRangeName() == 'monday') {
         monProtections[i].remove();
      }
    }
   }
};

我还创建了一个删除个人信息的 simplified example sheet

1 个答案:

答案 0 :(得分:0)

您可以使用此示例代码:(这应该适用于周一至周五的列)

function onEdit(e) {
  var ss = e.source; // get spreadsheet
  var sheet = ss.getActiveSheet();
  var cell = e.range; // get edited range
  
  if(sheet.getName() != "Rep1"){
    return;
  }
  
  var maxAppointments = sheet.getRange('G3').getValue();
  var row = cell.getRow();
  var col = cell.getColumn();
  
  //Check if edited cell is within B5:F27
  if(row>=5 && row<=27 && col>=2 && col<=6){
    
    //Get current date user count
    var count = sheet.getRange(3,col).getValue();
    if(count>=maxAppointments){
      //Select Row 5 to Row 27
      var range = sheet.getRange(5,col,23);

      // Protect range
      var protection = range.protect();
      var name = 'Column'+col;
      protection.setDescription(name); 

      Logger.log(protection.getEditors());
      protection.removeEditors(protection.getEditors());
      var me = Session.getEffectiveUser();
      protection.addEditor(me);
      Logger.log(protection.getEditors());
      if (protection.canDomainEdit()) {
        protection.setDomainEdit(false);
      }
    }else{
      var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
      Logger.log("Length"+protections.length);
      for (var i = 0; i < protections.length; i++) {
      
        var protection = protections[i];
        Logger.log(protection.getDescription());
        if (protection.getDescription() == 'Column'+col) {
          Logger.log("remove");
          protection.remove();
        }
      }
    }
  }
}
<块引用>

我在您当前的 onEdit() 中添加了一些保护,例如修改后的单元格应在工作表“Rep1”中,修改后的单元格应在 B5:F27 内(通过检查行和列索引完成)

它有什么作用?

  1. 通过使用 Sheet.getName() 获取其工作表名称,使用 Range.getRow()/Range.getColumn() 获取其工作表名称,检查修改后的单元格是否在工作表 Rep1 和 B5:F27 中

  2. 如果特定日期的当前用户数 >= 允许的最大用户数,则使用 Sheet.getRange(row, column, numRows)Range.protect() 保护从第 5 行到第 27 行的特定列。将说明设置为 "Column"+column index

  3. 如果特定日期的当前用户数小于允许的最大用户数,则取消保护(如果有)。移除的保护将根据步骤 2 中设置的保护描述

示例输出:

enter image description here

enter image description here

-> 这是保护后非编辑用户的视图。请注意,B 列和 D 列不可编辑(数据验证下拉列表已隐藏)

注意:

在示例代码中,我只是在删除其他编辑器后将我的主要用户设置为编辑器。您可以在有多个编辑器的原始代码中应用您的配置。

我也没有修改您将单元格背景设置为黑色的条件格式,也许您可​​以重新访问它,因为它总是更改 B-D 列的单元格背景,即使并非所有列都被锁定。查看示例输出,其中 B 列和 D 列被锁定,但 C 列未锁定