Protecting Cells Based on Contents of Other Cells

2019-03-05 23:41发布

I have a single worksheet that contains user entered responses in Columns C & D, Rows 3 - 20. The responses are time dependent and look at Column E Rows 3-20 to see if it is "Locked" or "Open".

Using protection, I lock the entire sheet for editing with the exception of C3:D20. The sheet is set to calculate every minute.

I am trying to write a script that checks the column E to see if it is set for locked or open. If it is set for locked, I would like to lock (protect) columns C&D in that row for editing from everyone but myself. I run the script every 5 minutes and I have the for loop and if statement handled, but when I go to use the RemoveEditors function it does 2 things:

  1. Creates a new protected range (so after 5 minutes I have 1 additional protected range, 10 minutes, I have 2 additional, etc.)
  2. Does not remove the other editors from those able to edit the cells.

I tried using Google's example code, but their code adds the current user as an editor, which is what I'm trying to avoid doing since then that editor can just remove the protection that the code is putting in place.

Any help you could provide would be appreciated.

Current Code is below:

function Lock_Cells() {
var sheet = SpreadsheetApp.getActive();
for (var i = 3; i <= 20; i++)
{
  var Check_Cell = "E" + i;
  var Temp = sheet.getRange(Check_Cell).getValue();
  if (Temp == "Locked")
  {
     var Lock_Range = "C" + (i + 2) + ":D" + "i";
     var protection = sheet.getRange(Lock_Range).protect();
     var description = "Row " + i;                 
     protection.setDescription(description);
     var eds = protection.getEditors();
     protection.removeEditors(eds);
  }
}  
}

1条回答
迷人小祖宗
2楼-- · 2019-03-06 00:31

To avoid creating a new set of protected ranges, you can add logic to check which rows are already locked. With that information you just need to skip those rows:

note: there was a mistake in this line: var Lock_Range = "C" + (i + 2) + ":D" + "i"; the variable i should not have quotation.

function Lock_Cells() {
var sheet = SpreadsheetApp.getActive();
var rows = get_protected_Rows();

for (var i =3; i <= 20; i++)
{
  var Check_Cell = "E" + i;
  var cell = sheet.getRange(Check_Cell);
  var Temp = sheet.getRange(Check_Cell).getValue();
  if (Temp == "Locked" &&  rows.indexOf(i) <0)
  {
      var Lock_Range = "C" + i + ":D" + i; //In this line you put "i" 
  .....
...
}
function get_protected_Rows()
{
  var ss = SpreadsheetApp.getActive();
  var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
  var rows = [];
  for (var i = 0; i < protections.length; i++) {
   var protection = protections[i];
   var anotation =   protection.getRange().getRow();
   rows.push(anotation);
  }

  return rows
}

You are right, when the code is executed by one of the users, the protection gives that user the ability to edit those rows. I would recommend that as the owner of the file, you also run a task to remove every other editor from those rows. The function would be very similar to the previous. And I know is not the best but it may help you with your use case.

function remove_editors()
{
  var ss = SpreadsheetApp.getActive();
  var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
  for (var i = 0; i < protections.length; i++) {
   var protection = protections[i];
   var anotation =   protection.getRange().getA1Notation();
      var eds = protection.getEditors();
      protection.removeEditors(eds);
   }      
}

By doing that i was able to restrict the permission to other users. Hope it helps.

查看更多
登录 后发表回答