'Lock a row when cell is checked in Google Sheets
I have a Google Sheets spreadsheet with a group of friends where each person enters a bet on their own designated tab. After they finish editing columns A-E, they have to check the box in column F to "submit" their bet. Once the box is checked, I want to lock that row to prevent someone from altering a bet. I would also like to change the background color in columns A-F from orange to gray to signify a submission.
https://docs.google.com/spreadsheets/d/12M1F69a_DgEW3yU154Bm6kVpi5dZ1tdJksvKzNBgJek/edit?usp=sharing
Solution 1:[1]
I haven't checked if it's possible to lock rows this way. But, just in case, as another options or a possible workaround I'd propose to copy the 'locked' values on a locked or/and hidden sheet and compare the values every time when spreadsheet is modified. The script could compare the sheets and copy the 'locked' (submitted) values from the locked sheet back on user's sheet if there are differences.
Probably, as an extremely vandal proof solution you can store the bets as script properties:
https://developers.google.com/apps-script/guides/properties
Update
It's turned out that you can't restrict current user from editing any cell on the sheet: How to lock a sheet for current user with Google script
Neither the owner of the spreadsheet nor the current user can be removed.
There is the workaround with additional 'helper' sheets: https://support.google.com/docs/forum/AAAABuH1jm0gnrD6_XtZT0/?hl=en&gpf=%23!topic%2Fdocs%2FgnrD6_XtZT0
Just for educational purposes, here is my try. It changes backgrounds by click on the checkboxes (to gray and back to orange) but it doesn't protect the cells:
function onEdit(e) {
const col = e.range.columnStart;
// e.source.toast(col); // <-- to debug
if (col != 6) return;
const row = e.range.rowStart;
// e.source.toast(row);
const sheet = e.source.getActiveSheet();
const range = sheet.getRange(row, 1, 1, 6);
// e.source.toast(range.getValues());
const value = e.range.getValue();
// e.source.toast(value);
if (!value) {
// set orange backgrounds <-- it works fine
range.setBackgrounds([range.getBackgrounds()[0].map(x => x = '#fce5cd')]);
return;
}
// set gray backgrounds <-- it works fine
range.setBackgrounds([range.getBackgrounds()[0].map(x => x = '#cccccc')]);
const protection = range.protect();
protection.removeEditors(protection.getEditors()); // <-- it doesn't work
const user = Session.getEffectiveUser();
// e.source.toast(user);
protection.removeEditors(user); // <-- it doesn't work as well
}
Solution 2:[2]
There is a workaround - you need to register the script as installable trigger: https://developers.google.com/apps-script/guides/triggers/installable
It helps when users (not the owner) need to be restricted.
One hint: if you register the function as installable triger and the function is e.g. onEdit, and the installable trigger will be set as onEdit, then the function will fire twice. In this case name your funtion e.g. "myfunction" and it will be fired once.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Damian.K |
