Вопрос или проблема
Я пытаюсь настроить Google таблицу, которую будут использовать десятки пользователей, и хочу автоматизировать схемы защиты, так как каждый день создается новая таблица. Я хочу, чтобы заголовки таблиц и определенные столбцы были защищены от всех пользователей (за исключением явных исключений), и когда в ячейку вносится изменение, права редактирования для всех пользователей удаляются. Я пробовал удалять права как с помощью функций onOpen, так и onEdit через setUnprotectedRanges() и обычный range.protect(), как указано в документации. Но каждый раз, когда я пробую onOpen, это нарушает работу другой функции. Я не знаю, как продолжать настраивать это, потому что права нужно удалять для максимального количества пользователей (кроме редактора и владельца). Вот что у меня есть для удаления защиты ячейки после редактирования, что работает:
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var editedCell = e.range;
if (editedCell.getColumn() == 4 && editedCell.getRow() > 1) {
var link = editedCell.getValue();
// Если вставлена ссылка (непустая ячейка)
if (link != "") {
var row = editedCell.getRow();
var currentTime = new Date(); // Получить текущую дату и время
// Установить отметку времени в колонке F
sheet.getRange(row, 6).setValue(currentTime);
// Установить формулу в колонке G для вычисления прошедшего времени
var elapsedTimeFormula="=IF(F" + row + '<>"", NOW() - F' + row + ', "")';
sheet.getRange(row, 7).setFormula(elapsedTimeFormula);
// Защитить конкретную ячейку в колонке D, куда была вставлена ссылка
var cellToProtect = sheet.getRange(row, 4);
var protection = cellToProtect.protect().setDescription('Ячейка заблокирована после добавления ссылки');
//var me = Session.getEffectiveUser();
protection.removeEditors(protection.getEditors());
//if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
//}
}
}
}
Что касается защиты определенных столбцов и строк в onOpen(), история версий меня подвела, но это было что-то вроде:
function onOpen(e) {
var sheet = e.source.getActiveSheet();
var protection = sheet.protect().setDescription('Защищенные заголовки и столбцы по умолчанию');
var unprotectedLeftOfColumns = sheet.getRange('A2:H1000');
var unprotectedRightOfColumns = sheet.getRange('J2:N1000');
protection.setUnprotectedRanges([unprotected]);
// Убедитесь, что текущий пользователь является редактором, прежде чем удалять других. В противном случае, если права редактирования пользователя
// поступают от группы, скрипт вызывает исключение при удалении группы.
//var me = Session.getEffectiveUser(); [Нет никаких причин, почему это не работает для двух пользователей на одном компьютере]
//protection.addEditor(me);
protection.removeEditors(protection.getEditors());
//if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
//}
Используя эти методы, я постоянно получаю ошибки, но не могу найти документацию для них, поэтому действительно сложно отладить это. В данный момент проще просто добавить защиту заголовков и столбцов при копировании таблицы, но я не тот, кто это делает, так что не могу быть уверен, что это сделано. Документация по сценарию защиты начинает выглядеть мрачно, я даже не уверен в других методах, таких как removeEditor(), так как это большая таблица, которой делится по ссылке, и скорость имеет ключевое значение. Любая помощь будет очень ценна, потому что я не могу найти много информации по этим вопросам.
Ответ или решение
Чтобы настроить защиту определённых секций листа Google Sheets при его открытии и в случае редактирования ячеек, вам потребуется реализовать два триггера: onOpen(e)
и onEdit(e)
. Давайте рассмотрим оба сценария более подробно.
Защита при открытии листа (onOpen
)
Целью данной функции является установка защитных настроек для заголовков и определённых колонок. Обратите внимание, что необходимо указывать диапазоны, которые не должны быть защищены.
function onOpen(e) {
var sheet = e.source.getActiveSheet();
// Установим защиту для всего листа
var protection = sheet.protect().setDescription('Защита заголовков и колонок');
// Разрешаем редактирование пользователям, указываем диапазоны, которые не защищены
var unprotectedRanges = [sheet.getRange('A2:H1000'), sheet.getRange('J2:N1000')];
protection.setUnprotectedRanges(unprotectedRanges);
// Удаляем возможность редактирования для всех пользователей, кроме владельца и указанных редакторов
protection.removeEditors(protection.getEditors());
protection.setDomainEdit(false); // Запрещаем редактирование для всей доменной группы
}
Защита после редактирования ячейки (onEdit
)
Эта функция срабатывает каждый раз, когда пользователь редактирует ячейку. Здесь нужно защищать ячейку в колонке D (после вставки ссылки) и фиксировать дату изменения, а также ввести формулу для расчёта времени.
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var editedCell = e.range;
// Проверяем, если редактируется колонка D и не первая строка
if (editedCell.getColumn() == 4 && editedCell.getRow() > 1) {
var link = editedCell.getValue();
// Если ячейка не пустая
if (link != "") {
var row = editedCell.getRow();
var currentTime = new Date(); // Получаем текущее время
// Устанавливаем временную метку в колонке F
sheet.getRange(row, 6).setValue(currentTime);
// Устанавливаем формулу в колонке G для вычисления времени
var elapsedTimeFormula = `=IF(F${row}<>"", NOW()-F${row}, "")`;
sheet.getRange(row, 7).setFormula(elapsedTimeFormula);
// Защищаем ячейку в колонке D
var cellToProtect = sheet.getRange(row, 4);
var protection = cellToProtect.protect().setDescription('Ячейка заблокирована после добавления ссылки');
// Удаляем всех редакторов и запрещаем редактирование для домена
protection.removeEditors(protection.getEditors());
protection.setDomainEdit(false); // Отмена редактирования для всех пользователей
}
}
}
Примечания по работе скриптов
-
Полномочия: Убедитесь, что у вашего скрипта есть необходимые привилегии для удаления редакторов. Зачастую, если у пользователя имеются разрешения на редактирование через группу, это может вызвать ошибку.
-
Ошибки: Если возникают ошибки, попробуйте их отследить, добавив в скрипты логи через Logger.log(), чтобы увидеть, на каком этапе возникает сбой.
-
Эффективность: Защита может занять некоторое время, особенно на больших листах, поэтому учитывайте скорость и производительность.
-
Тестирование: Проведите тщательное тестирование всех изменений с разными пользователями с различными уровнями доступа.
Для оптимизации вашей работы рекомендуется использовать инкапсуляцию защитных функций — создайте дополнительные вспомогательные функции, которые будут обработкой ваших логик, чтобы избежать дублирования кода.
Используя предложенные методы, вы сможете добиться gewünschte защиты при запуске и при редактировании ваших Google Sheets, обеспечив безопасность данных при работе с несколькими пользователями.