问题
In our team we have the following scenario: we're using a google spreadsheet with some protected areas (mainly formulas that must not be overridden - only the "admin", in our case it's me, can edit them). The other input fields are unprotected. Every team member can enter their data. At some point in time (end of the sprint), our project managers need to report the numbers from the spreadsheet. To ensure that the numbers do not get changed afterward, they want to look at the entire sheet. For the next sprint, we create a new spreadsheet. I added an app script (code below) and assigned this to a button that they can click to lock the sheets (or at least the important ranges where people enter their data).
If I click the button everything works fine. But if they do that, they get an exception: "Exception: You are trying to edit a protected cell or object. Please contact the spreadsheet owner to remove protection if you need to edit."
I tried various options, setting range protections, sheet protection, removing me as an editor, adding them as an editor to protection, etc. But in all cases, as soon as a function on the protection is called (e.g. addEditor()), this exception appears.
Any idea how to make it possible, so that basically everybody can click the button and so lock the entire sheet?
Below my function. this example uses the sheet.protect(), but I also tried the ranged protections, just to make it easier to understand what I'm talking about ;)
function lockSheet() {
var me = Session.getEffectiveUser();
var as = SpreadsheetApp.getActiveSpreadsheet();
as.getSheets().map(function(sheet) {
var protection = sheet.protect().setDescription('The sprint has been closed. No further editing possible.');
// Ensure the current user is an editor before removing others. Otherwise, if the user's edit
// permission comes from a group, the script throws an exception upon removing the group.
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
});
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Sheet is now locked. The only editor now is: ' + me);
}
回答1:
I believe your situation and goal as follows.
- Users, who logged in Google account, run the script by clicking a button on Google Spreadsheet.
- In your issue, when users click the button, an error of
Exception: You are trying to edit a protected cell or object. Please contact the spreadsheet owner to remove protection if you need to edit.
occurs. - You want to lock the sheets in Google Spreadsheet when the users click the button.
Issue and workaround:
I think that in your case, when the users click the button, the script is run by each user. But the sheet has already been locked by other users. By this, such error occurs. In order to avoid this, as a workaround, I would like to propose to lock the sheets by an user (in this case, it's the owner.). The flow of this workaround is as follows.
- When a button is clicked, the script requests to the Web Apps. In this case, the email address of the user is sent to Web Apps.
- At Web Apps, the sheets are locked by the owner.
- When the lock is done,
ui.alert
is run.
Usage:
1. Prepare script.
Please copy and paste the following script to the script editor and save it.
const key = "sampleKey";
function doGet(e) {
if (e.parameter.key == key) {
var me = e.parameter.me;
// Below script is your script.
as.getSheets().map(function(sheet) {
var protection = sheet.protect().setDescription('The sprint has been closed. No further editing possible.');
// Ensure the current user is an editor before removing others. Otherwise, if the user's edit
// permission comes from a group, the script throws an exception upon removing the group.
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
});
} else {
throw new Error("Wrong key.");
}
return ContentService.createTextOutput();
}
function lockSheet() {
var lock = LockService.getDocumentLock();
if (lock.tryLock(10000)) {
try {
var me = Session.getEffectiveUser();
var as = SpreadsheetApp.getActiveSpreadsheet();
var url = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps.
url += `?me=${me}&key=${key}`;
try {
var res = UrlFetchApp.fetch(url);
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Sheet is now locked. The only editor now is: ' + me);
} catch(er) {
throw new Error(er.message);
}
} catch(e) {
throw new Error(e);
} finally {
lock.releaseLock();
}
}
}
2. Deploy Web Apps.
On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
Select "Me" for "Execute the app as:".
- By this, the script is run as the owner.
Select "Anyone, even anonymous" for "Who has access to the app:".
- In this case, no access token is required to be request. I think that I recommend this setting for testing this workaround. But in this script, the key for running the script is used.
- Of course, you can also use the access token. But, in this case, when the access token is used, this sample script cannot be directly used as the custom function. So in this answer, I proposed to use the key for running the Web Apps script. But if you want to use the access token, I think that it will be achieved using PropertiesService.
Click "Deploy" button as new "Project version".
Automatically open a dialog box of "Authorization required".
- Click "Review Permissions".
- Select own account.
- Click "Advanced" at "This app isn't verified".
- Click "Go to ### project name ###(unsafe)"
- Click "Allow" button.
Click "OK".
Copy the URL of Web Apps. It's like
https://script.google.com/macros/s/###/exec
.- When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
Please set the URL of
https://script.google.com/macros/s/###/exec
tourl
of above script. And please redeploy Web Apps. By this, the latest script is reflected to the Web Apps. So please be careful this.
4. Test this workaround.
Please click the button assigned with lockSheet
. By this, the script for locking sheets are run by the owner.
Note:
- When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
- Please use this script with enabling V8.
References:
- Custom Functions in Google Sheets
- Web Apps
- Taking advantage of Web Apps with Google Apps Script
来源:https://stackoverflow.com/questions/64086095/how-to-enable-not-authorized-users-to-protect-the-spreadsheet