google app scripts protections going away when copying sheet - google-apps-script

I have a google sheet that has many protected ranges/cells. It is currently set up so that myself and two others have full edit access to the workbook/protected ranges/cells. All others accessing the sheet can then only edit certain cells. It works exactly how I expect.
However, when I use a script to copy that sheet and insert data, the protections for the other two full editors goes away. I do not remove protections in my code at all just add data to the sheet.
Any thoughts on why this would happen or how to fix it? Again, these two other users can access the sheet they just can no longer edit any cell/range.

Try this (sheetname should be the name of your sheet to copy):
function duplicateSheetWithProtections() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheet = ss.getSheetByName('sheetname');
sheet2 = sheet.copyTo(ss).setName('My Copy');
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var p = protections[i];
var rangeNotation = p.getRange().getA1Notation();
var p2 = sheet2.getRange(rangeNotation).protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
if (!p.isWarningOnly()) {
p2.removeEditors(p2.getEditors());
p2.addEditors(p.getEditors());
// p2.setDomainEdit(p.canDomainEdit()); // only if using an Apps domain
}
}
}

Related

How to directly open the new google sheet created from script?

I have been using the following code (after some edits and help from the community here) to create a duplicate sheet from a template sheet. However, the number of sheets have increased now. Is there a way to make some edits in this code such that the newly created sheet shows up directly so I can right away edit without horizontally scrolling through to find the new sheet that was created from the script? .
Edited question for giving better clarity on the issue.
function duplicateSheetWithProtections() {
var ui = SpreadsheetApp.getUi();
var oldSheetName = ui.prompt('Sheet to Copy?');
var newSheetName = ui.prompt('New Sheet Name?');
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheet = ss.getSheetByName(oldSheetName.getResponseText());
sheet2 = sheet.copyTo(ss).setName(newSheetName.getResponseText());
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var p = protections[i];
var rangeNotation = p.getRange().getA1Notation();
var p2 = sheet2.getRange(rangeNotation).protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
if (!p.isWarningOnly()) {
p2.removeEditors(p2.getEditors());
p2.addEditors(p.getEditors());
// p2.setDomainEdit(p.canDomainEdit()); // only if using an Apps domain
/* Make the new sheet active */
ss.setActiveSheet(sheet);
}
}
}
Try
sheet2.moveActiveSheet(0)
this will be the simplest and most effective solution

Google sheet conditional formatting and lock cell [duplicate]

I am trying to implement a script that locks a certain range of cells when a condition is true. Here is the link to my document:
https://docs.google.com/spreadsheets/d/1XShGxlz2fA2w2omth-TvYc7cK0nXvVMrhwRKafzVjOA/edit?usp=sharing
Basically I am sharing this document with a group of people so they fill their mail addresses in column B and put a number 1 in column C so it increments my counters for each slot. What I am trying to do is to lock each slot when it is full so other people can no more edit these slots but the problem is with my if statement if (cell1 == 10). The range is always locked even if the if condition is not realized. Here is my code :
function onOpen() {
var ss = SpreadsheetApp.getActive();
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var cell=60;
var cell1 = source.getRange("G2").getValue();
if (cell1 == 10){
// Protect range B2:B11, then remove all other users from the list of editors.
var ss = SpreadsheetApp.getActive();
var range = ss.getRange('B2:B11');
var protection = range.protect().setDescription('Sample protected range');
// Ensure the current user is an editor before removing others. Otherwise, if the user's edit
// permission comes from a group, the script will throw an exception upon removing the group.
var me = Session.getEffectiveUser();
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
}
As Andy says in the comments, you need to explicitly remove the protection if cell G2 does not equal 10. (This code removes all protections).
Reading the Protection Class page, where you got the snippets from, I couldn't get a handle on the way editor privileges would factor into your needs, so this script will work if others are editors. If you don't want them to be editors, you'll have to add the relevant code.
function onOpen() {
var ss = SpreadsheetApp.getActive();
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var cell = source.getRange("G2").getValue();
var range = ss.getRange('B2:B11');
if (cell == 10) {
// Protect range B2:B11 if cell 'G2' = 10
var protection = range.protect().setDescription('Sample protected range');
Logger.log
} else {
// Remove protection if cell 'G2' is anything other than 10
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
protection.remove();
}
}
}

Looking for a script to save protections on sheets when copied

I am creating workbooks for teachers to monitor students progress on a specific skill. We have a workbook with various templates they may need to copy the sheets/graphs they need for each child. These sheets are protected without the exception of the cells the teachers need to access in order to input student data. Right now when we use the COPY TO a new spreadsheet, we lose those protections. (Most of our K-2 teachers are not tech-savvy enough to have full access to a sheet with a graph.) There has to be a way to create some type of protection that carries over to copied files that is foolproof. Thanks to anyone who knows how to do this.
I tried using this code and it does copy my sheet and keep it protected, BUT how can I get it to stay protected when the COPY TO is used to another existing workbook?
function duplicateProtectedSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheet = ss.getSheetByName("B - General Info");
sheet2 = sheet.copyTo(ss).setName("My Copy1");
var p = sheet.getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
var p2 = sheet2.protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
if (!p.isWarningOnly()) {
p2.removeEditors(p2.getEditors());
p2.addEditors(p.getEditors());
// p2.setDomainEdit(p.canDomainEdit()); // only if using an Apps domain
}
var ranges = p.getUnprotectedRanges();
var newRanges = [];
for (var i = 0; i < ranges.length; i++) {
newRanges.push(sheet2.getRange(ranges[i].getA1Notation()));
}
p2.setUnprotectedRanges(newRanges);
}
Here is an example of my current workbook with the templates teachers will be copied to their own workbooks.
https://docs.google.com/spreadsheets/d/1JB95bdu4Qatx7uMZrQFP7GkiKBuuB47PCV8ZjyQWmHo/edit?usp=sharing
try this:
function test(){
var ss = SpreadsheetApp.getActiveSheet();
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
var newSheet = ss.copyTo(SpreadsheetApp.getActive());
var prot;
var p;
var editors;
for (var i = 0; i < protections.length; i++){
prot = protections[i];
p = newSheet.getRange(prot.getRange().getA1Notation()).protect();
p.setDescription(prot.getDescription());
editors = prot.getEditors();
for (var j = 0; j < editors.length; j++){
p.addEditor(editors[i]);
}
}
}
This code copies the sheet and stores the original's protections, then it set the same protections in the newly-created sheet. for you it would be a matter of setting ss and newSheet to the ones you intend to use.

Duplicate sheet but keep protected range with exact same user as only editor?

Soooo close on this one thanks to stackoverflow help :)
The following code duplicates a sheet based on a template, and copies over the protected range permissions from the template sheet to the new sheet.
However, the permission range is now there in the new sheet, but not with the same user.
The template sheet has only one user that can edit, but for the new sheet, while the same range is restricted, all users from the entire spreadsheet can edit the new sheet.
Anyone happen to know if I can make it be just the exact same user as the template? And not like the user that initiates the script but only the same user as the template. Here's the code:
function newSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("New Sheet Template");
var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
var dateI = Browser.inputBox('Enter Date: ','(DD/MM/YYYY)', Browser.Buttons.OK_CANCEL);
var nameSheet= "Sheet - "+dateI
if (dateI == "cancel" ) {
}
else {
ss.insertSheet(nameSheet, {template: sheet});
ss.getRange('B4').setValue(dateI);
for (var i = 0; i < protections.length; i++) {
var sheet2 = ss.getSheetByName("Sheet - "+dateI);
var p = protections[i];
var rangeNotation = p.getRange().getA1Notation();
var p2 = sheet2.getRange(rangeNotation).protect();
p2.setDescription(p.getDescription());
p2.setWarningOnly(p.isWarningOnly());
}
}
}
Thanks in advance! :)

Google Script Lock Cells

I am trying to implement a script that locks a certain range of cells when a condition is true. Here is the link to my document:
https://docs.google.com/spreadsheets/d/1XShGxlz2fA2w2omth-TvYc7cK0nXvVMrhwRKafzVjOA/edit?usp=sharing
Basically I am sharing this document with a group of people so they fill their mail addresses in column B and put a number 1 in column C so it increments my counters for each slot. What I am trying to do is to lock each slot when it is full so other people can no more edit these slots but the problem is with my if statement if (cell1 == 10). The range is always locked even if the if condition is not realized. Here is my code :
function onOpen() {
var ss = SpreadsheetApp.getActive();
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var cell=60;
var cell1 = source.getRange("G2").getValue();
if (cell1 == 10){
// Protect range B2:B11, then remove all other users from the list of editors.
var ss = SpreadsheetApp.getActive();
var range = ss.getRange('B2:B11');
var protection = range.protect().setDescription('Sample protected range');
// Ensure the current user is an editor before removing others. Otherwise, if the user's edit
// permission comes from a group, the script will throw an exception upon removing the group.
var me = Session.getEffectiveUser();
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
}
As Andy says in the comments, you need to explicitly remove the protection if cell G2 does not equal 10. (This code removes all protections).
Reading the Protection Class page, where you got the snippets from, I couldn't get a handle on the way editor privileges would factor into your needs, so this script will work if others are editors. If you don't want them to be editors, you'll have to add the relevant code.
function onOpen() {
var ss = SpreadsheetApp.getActive();
var source = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var cell = source.getRange("G2").getValue();
var range = ss.getRange('B2:B11');
if (cell == 10) {
// Protect range B2:B11 if cell 'G2' = 10
var protection = range.protect().setDescription('Sample protected range');
Logger.log
} else {
// Remove protection if cell 'G2' is anything other than 10
var protections = ss.getProtections(SpreadsheetApp.ProtectionType.RANGE);
for (var i = 0; i < protections.length; i++) {
var protection = protections[i];
protection.remove();
}
}
}