Работа с защищенными листами и диапазонами в режиме «Только просмотр»

#google-apps-script #google-sheets

#google-apps-script #google-sheets

Вопрос:

Просто хочу спросить, есть ли способ для пользователя использовать кнопку со сценарием блокировки или разблокировки, даже если разрешение на защищенные листы и диапазоны находится в режиме «Только для просмотра«? Будет ли работать веб-приложение или это все еще невозможно?

Ответ №1:

Проблема:

Скрипт не может защитить / снять защиту с листа или диапазона, если пользователь, выполняющий его, не имеет edit access доступа к защищенному листу / диапазону.

Попытка сделать это приводит к появлению сообщения типа:

Вы пытаетесь отредактировать защищенную ячейку или объект. Пожалуйста, свяжитесь с владельцем электронной таблицы, чтобы снять защиту, если вам нужно отредактировать.

Чтобы избежать того, чтобы скрипт выдавал это исключение, полезно сначала проверить, есть ли у пользователя доступ к редактированию, используя Protection.CanEdit() .

Использование веб-приложения:

При развертывании сценария как веб-приложения можно настроить выполнение приложения как: Me (то есть пользователя, развертывающего веб-приложение). Если у этого пользователя есть доступ для редактирования к защищенному листу / диапазону, веб-приложение сможет снять защиту с листа / диапазона, даже если к нему обращается пользователь, у которого нет доступа для редактирования.

Например, предположим, что у вас есть электронная таблица с именем листа Sheet1 , которая защищена и может быть отредактирована только пользователем # 1. В этом случае у вас может быть следующая doGet функция для снятия защиты:

 function doGet(e) {
  const sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
  const protection = sheet.getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
  if (protection amp;amp; protection.canEdit()) {
    protection.remove();
  }
  return ContentService.createTextOutput("Sheet unprotected!");
}
 

А затем, войдя в систему с пользователем # 1, разверните веб-приложение следующим образом:

  • Нажмите Publish > Deploy as web app... .
  • Установить Execute the app as: Me .
  • Установите Who has access to the app: аудиторию, в которую будут входить другие пользователи, которые должны иметь доступ к этому.
  • Нажмите Deploy .
  • Копировать Current web app URL: .

Наконец, получите доступ к этому URL-адресу с помощью пользователя # 2 (у которого нет доступа к редактированию защищенного листа). Лист станет незащищенным.

Обновить:

Вы могли бы написать другую функцию для доступа к этому URL программно через UrlFetch. Смотрите, например:

 function unprotect() {
  const url = "WEB_APP_URL";
  const options = {
    headers: { Authorization: "Bearer "   ScriptApp.getOAuthToken() }
  }
  UrlFetchApp.fetch(url, options);
}
 

Доступ к этому URL-адресу через UrlFetch может потребовать явной настройки областей в файле манифеста скрипта:

 "oauthScopes": [
  "https://www.googleapis.com/auth/script.external_request", 
  "https://www.googleapis.com/auth/drive", 
  "https://www.googleapis.com/auth/spreadsheets"
]
 

Комментарии:

1. Будет ли это работать с этой ошибкой: Exception: You are trying to edit a protected cell or object. Please contact the spreadsheet owner to remove protection if you need to edit. ?

2. @cjvdg Это будет работать успешно, если вы будете следовать предоставленному мной руководству. Особенно примите во внимание: (1) развертывание веб-приложения при входе в систему с пользователем, который может редактировать защищенный диапазон / лист , (2) установка Execute the app as: Me , (3) снятие защиты с листа / диапазона путем доступа к URL веб-приложения, а не путем doGet прямого выполнения. Конечно, вы могли бы создать в своем скрипте другую функцию для доступа к этому URL программно, используя UrlFetch . Я отредактировал свой ответ, чтобы показать вам, как это можно сделать. Смотрите Раздел Update в моем ответе.

3. Я попробовал ваше решение, но в настоящее время получаю эту ошибку TypeError: Cannot read property 'getProtections' of null at doGet(Code:12:28) . В чем, по-видимому, проблема?

4. @cjvdg Это означает, что у вас нет вызванного листа Sheet1 , поэтому getSheetByName возвращает null . Вы должны изменить Sheett1 в фрагменте кода название вашего листа. И в целом, вы адаптируете этот фрагмент кода к своей ситуации (я не уверен, есть ли у вас защищенный лист, или диапазоны, или что у вас есть).

5. Хорошо. Я перепроверю это еще раз. Спасибо!