1

Every day create 2-3 sheets but a minimum of one these ranges are protecting ["B3:U27", "W3:AP27", "B29:U33", "W29:AP33"]

I reduced the 42 ranges to these 4 ranges to make it faster but still in 1 minute it can protect about 8 files the problem is that in a few months it can grow more then 100 files which would take me up to the 6 minute timeout limit and that would interrupt the script.

This is the script I am currently using. I wonder if it could be modified in some way to ignore the already protected sheets?

function main(){ //Main function to run
  var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
  var disregard = ["List", "Data", "Template"]; //ADD SHEET NAMES HERE THAT YOU WANT TO BE DISREGARDED

  for(var x=0; x<sheets.length; x++){
    if(disregard.some(data => sheets[x].getName().includes(data))){ 
      //E.g. Disregard any sheet names added on the "disregard" array
    }else{
      unlockCertainRanges(sheets[x]);
    }
  }
}

function unlockCertainRanges(currentSheet){ //Function to unlock certain ranges on your spreadsheet
  var sheet = currentSheet;
  // Remove all range protections in the spreadsheet
  var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
  for (var i = 0; i < protections.length; i++) {
    var protection = protections[i];
    protection.remove();
  }

  var protection = sheet.protect();
  //restrict editors to owner
  protection.getRange().getA1Notation();
  var eds = protection.getEditors();
  protection.removeEditors(eds);

  //set unprotected ranges
  var ranges = protection.getUnprotectedRanges();
  var data = ["B3:U27", "W3:AP27", "B29:U33", "W29:AP33"]; // ADD YOUR RANGES HERE
  data.forEach(res => { //LOOPS INTO EVERY ARRAY CONTAINING SPECIFIC RANGES
    ranges.push(sheet.getRange(res));
    protection.setUnprotectedRanges(ranges); //REMOVES THE PROTECTION ON THE RANGE
  });
}

Can it be something that has already been protected or have a padlock on them not to be touched?
I tried to find a way to retrieve the names of the already protected sheets.
I mean something like getSheetName() but for the protected ones.

Or maybe put it in the exceptions if there is already such protection on this description?

setDescription('Already protected');

I don't have much experience in coding; I found a very similar question but I didn't understand much of the code

Does anyone have an idea?

TheMaster
  • 45,448
  • 6
  • 62
  • 85
  • 2
    You can look at `Sheet.getProtections()` – Cooper May 14 '21 at 21:06
  • @MetaMan if this is what you mean, deleting this section will also rescan `// Remove all range protections in the spreadsheet var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE); for (var i = 0; i < protections.length; i++) { var protection = protections[i]; protection.remove(); }` – Ádám Hegedüs May 14 '21 at 22:03
  • 2
    Your question is "How to Ignore already protected sheets with script? " You can look to see if each sheet has protections and only return the names of the sheets that don't have protection. – Cooper May 14 '21 at 22:17

1 Answers1

0

I believe what @MetaMan simply means is that, you need to check first if the sheet does contain a protected range. See code below.

Code:

function main() {
  var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
  // Get list of sheets protected
  var protections = SpreadsheetApp.getActiveSpreadsheet().getProtections(SpreadsheetApp.ProtectionType.SHEET);
  var protectedSheets;
  // If protections isn't set, initialize as empty array
  if (protections)
    protectedSheets = protections.map(protection => protection.getDescription());
  else
    protectedSheets = [];

  var disregard = ["List", "Data", "Template"]; //ADD SHEET NAMES HERE THAT YOU WANT TO BE DISREGARDED

  for (var x = 0; x < sheets.length; x++) {
    if (disregard.some(data => sheets[x].getName().includes(data))) {
      //E.g. Disregard any sheet names added on the "disregard" array
    } else {
      // If protectedSheets doesn't include the name, process the sheet
      if (!protectedSheets.includes(sheets[x].getName()))
        unlockCertainRanges(sheets[x]);
    }
  }
}

function unlockCertainRanges(currentSheet) {
  Logger.log("\"" + currentSheet.getName() + "\" is being processed");
  var sheet = currentSheet;
  var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);

  for (var i = 0; i < protections.length; i++) {
    var protection = protections[i];
    protection.remove();
  }

  // set names of sheets as description for future checks
  var protection = sheet.protect().setDescription(currentSheet.getName());
  //restrict editors to owner
  protection.getRange().getA1Notation();
  var eds = protection.getEditors();
  protection.removeEditors(eds);

  //set unprotected ranges
  var ranges = protection.getUnprotectedRanges();
  var data = ["B3:U27", "W3:AP27", "B29:U33", "W29:AP33"]; // ADD YOUR RANGES HERE
  data.forEach(res => { //LOOPS INTO EVERY ARRAY CONTAINING SPECIFIC RANGES
    ranges.push(sheet.getRange(res));
    protection.setUnprotectedRanges(ranges); //REMOVES THE PROTECTION ON THE RANGE
  });
}

// function to delete all existing protections
function deleteAllProtections() {
  var protections = SpreadsheetApp.getActiveSpreadsheet().getProtections(SpreadsheetApp.ProtectionType.SHEET);
  protections.forEach(protection => protection.remove());
}

Note:

  • Note that the first run will need to run deleteAllProtections() so all sheets will have no protections for the first time. Succeeding runs will now skip those sheet with protections.

Reference:

NightEye
  • 10,634
  • 2
  • 5
  • 24
  • what you've written, runs through everything and adds the protection. Nothing is skipped. – Ádám Hegedüs May 15 '21 at 08:07
  • 1
    Hi @ÁdámHegedüs, I apologize as I misunderstood your intentions. See edited answer above. I used ScriptProperties to store the names of the sheets. then check if the sheet name is there before calling the function. If the name is there, then it will skip the sheet. Note that the first run will need to initialize the property so it needs to go into all sheets for the first time. – NightEye May 15 '21 at 21:50
  • Hi @NaziA no problem english is not my first language so the translation is a problem for me. You write // set ranges to protect... but for me it is exactly these ranges that should be release from protection (first protects the sheet, then releases the protection for the specified ranges) could you please include in your edit how it would look like if I should release from protection these ranges? "B3:U27", "W3:AP27", "B29:U33", "W29:AP33" – Ádám Hegedüs May 15 '21 at 23:50
  • Hi @ÁdámHegedüs, I have modified the EDIT section. note that I just added your code in between. After the protection was released, it was to be expected that these sheets are not to be visited again. Sorry if i misunderstood since the post is not actually what the code says. Idea is the same, after processing a sheet, that sheet won't be processed on the next succeeding runs. – NightEye May 17 '21 at 15:50
  • for me it just runs for about 1 second and does nothing – Ádám Hegedüs May 17 '21 at 15:58
  • Did you log the variables during your run? what does it say? kindly debug. maybe the properties were already saved and thus your sheets were already skipped. @ÁdámHegedüs – NightEye May 17 '21 at 16:00
  • if it is not set I don't know how to debug variables now the log is empty here I have explained a bit more what I wanted [link](https://stackoverflow.com/questions/67568212/protect-sheets-and-release-domains-from-protection-and-skip-them-if-there-is-alr) – Ádám Hegedüs May 17 '21 at 16:06
  • Try this. ```function checkProperties() { var protectedSheets = ScriptProperties.getProperty('protectedSheets'); Logger.log(protectedSheets); }``` @ÁdámHegedüs – NightEye May 17 '21 at 16:09
  • this is my whole sheets list log. including padlocked ones – Ádám Hegedüs May 17 '21 at 16:16
  • I assume you are trying to attach an image? you can't do that in the comments @ÁdámHegedüs. – NightEye May 17 '21 at 16:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232525/discussion-between-nazia-and-adam-hegedus). – NightEye May 17 '21 at 16:30