Предотвращение или удаление нескольких экземпляров защищенных ячеек одного и того же диапазона

У меня есть две отдельные таблицы: одна для администратора и одна для пользователя. Администратор может заблокировать или разблокировать определенные диапазоны для пятницы, субботы, воскресенья или праздников с помощью триггера onEdit (т. е. Fridaycheck(). Когда флажок снят, те же самые диапазоны удаляются. Проблема в том, что администратор отмечает все флажки сразу и перед любыми отдельных сценариев могут быть завершены. Когда они наконец завершаются, для каждого дня существует несколько экземпляров защиты. Когда администратор проверяет один день и скрипту разрешено завершиться, все работает нормально. Пытаюсь предотвратить запуск нескольких экземпляров защиты. вставлены ИЛИ удалите все экземпляры, когда галочка снята. Вот сценарии для проверки, блокировки и разблокировки Fri onEdit. Мы будем очень признательны за любые предложения. Спасибо, Пол .

function fridaycheck() {
  let admincheck = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Admin")
  let activeCell = admincheck.getRange("AE9")
  let reference = activeCell.getA1Notation()
  let sheetName = activeCell.getSheet().getName()
  let activeValue = activeCell.getValue()
  if (reference == "AE9" && sheetName == "Admin" && activeValue == true)
    LockFriday();
  else 
    UnlockFriday();
  }

function LockFriday() {
  var protectRange = 'C8:D60';
  var description = 'AA Lock Friday Cells';
  var spreadsheet = 
SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxx');
  spreadsheet.getRange(protectRange).activate();
  spreadsheet.setCurrentCell(spreadsheet.getRange('D60'));
  var p = spreadsheet.getProtections(SpreadsheetApp.ProtectionType.RANGE).find(e => 
e.getRange().getA1Notation() == protectRange && e.getDescription() == description);
  if (p) return;
  var protection = spreadsheet.getRange(protectRange).protect();
  var all = protection.getEditors();
  protection.setDescription(description).removeEditors(all);
  protection.setDescription(description).addEditor('[email protected]');
  protection.setDescription(description).addEditor('[email protected]');
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if (checkbox==false){
    ss.getRange("AE9").setValue("true");
  } 
} 

function UnlockFriday() {
  var spreadsheet = SpreadsheetApp.openById('XXXXXXXXXXXXX');
  spreadsheet.getRange('C8:D60').activate();
  var allProtections = 
spreadsheet.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.RANGE);
  var matchingProtection1 = allProtections.find(existingProtection => existingProtection.getRange().getA1Notation() == 'C8:D60');
  if (!matchingProtection1) return;
  matchingProtection1.remove();
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if (checkbox==true){
    ss.getRange("AE9").setValue("false");
  } 
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

ПРЕДПОЛОЖЕНИЕ

Судя по вашему сообщению, я понимаю, что вы хотите обеспечить отсутствие дубликатов описаний защищенного диапазона, а сохранить только один уникальный защищенный диапазон.

Я предлагаю вам использовать расширенную службу Google для API Google Sheet, поскольку расширенные службы обычно оптимизированы по производительности, что может привести к сокращению времени выполнения.

Я подправил ваш скрипт и добавил, как вы можете добавить пример функции checkDupes. Вот пример измененного скрипта:

function fridaycheck() {
  let admincheck = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Admin")
  let activeCell = admincheck.getRange("AE9")
  let reference = activeCell.getA1Notation()
  let sheetName = activeCell.getSheet().getName()
  let activeValue = activeCell.getValue()
  if (reference == "AE9" && sheetName == "Admin" && activeValue == true)
    LockFriday();
  else
    UnlockFriday();
}

function LockFriday() {
  var protectRange = 'C8:D60';
  var description = 'AA Lock Friday Cells';
  var userSheetID = "XXXXXXXXXXXXXXXXXXX"; //[UPDATED], placed the Sheet ID you are using in this 'userSheetID' variable for your 'LockFriday' function.
  var spreadsheet =
    SpreadsheetApp.openById(userSheetID); //[UPDATED], placed the 'userSheetID' variable to where it is needed
  spreadsheet.getRange(protectRange).activate();
  spreadsheet.setCurrentCell(spreadsheet.getRange('D60'));
  var p = spreadsheet.getProtections(SpreadsheetApp.ProtectionType.RANGE).find(e =>
    e.getRange().getA1Notation() == protectRange && e.getDescription() == description);
  if (p) return;
  var protection = spreadsheet.getRange(protectRange).protect();
  var all = protection.getEditors();
  protection.setDescription(description).removeEditors(all);
  protection.setDescription(description).addEditor('[email protected]');
  protection.setDescription(description).addEditor('[email protected]');
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if (checkbox == false) {
    ss.getRange("AE9").setValue("true");
  }

  checkDupes(userSheetID); //[UPDATED], added this function with the idea that every time a new protection is added, regardless of whether it is another duplicate, this function runs to make sure they are deleted.
}

function checkDupes(userSheetID) {
  var spreadsheetData = Sheets.Spreadsheets.get(userSheetID); //Get data from the user spreadsheet via sheet ID
  var columns = Array.from({ length: 26 }, (_, i) => String.fromCharCode(97 + i).toUpperCase());

  //Function to trasnform result function into readable A1 notation range with description.
  let getReadableRanges = (p) => {
    return p.protectedRanges.map(r =>
      [r.protectedRangeId, r.description, `${columns.filter((_, i) => r.range.startColumnIndex == i)}${r.range.startRowIndex + 1}:${columns.filter((_, i) => (r.range.endColumnIndex - 1) == i)}${r.range.endRowIndex}`]);
  }

  let cleanDupeProtectedRange = (p, userSheetID) => {
    let protectedRangeIds = p.map(x => `{"deleteProtectedRange": {"protectedRangeId":${x[0]}}}`)
    let requestbuilder = `{"requests": [${protectedRangeIds.join(',')}]}`
    return Sheets.Spreadsheets.batchUpdate(requestbuilder, userSheetID);
  }

  let pullExistingProtectedRanges = spreadsheetData.sheets.map(p => getReadableRanges(p));

  let protectRange = pullExistingProtectedRanges.flat().reduce((accumulator, currentValue) => {
    const existingItem = accumulator.find(item => item[1] === currentValue[1]);
    if (!existingItem) {
      accumulator.push(currentValue);
    }
    return accumulator;
  }, []);

  var rangeToRemoved = pullExistingProtectedRanges.flat().filter(y => !protectRange.join('*').match(y[0]));

  try {
    cleanDupeProtectedRange(rangeToRemoved, userSheetID)
  } catch {
    console.info('No duplicate found')
  }

}

function UnlockFriday() {
  var spreadsheet = SpreadsheetApp.openById('XXXXXXXXXXXXX');
  spreadsheet.getRange('C8:D60').activate();
  var allProtections =
    spreadsheet.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.RANGE);
  var matchingProtection1 = allProtections.find(existingProtection => existingProtection.getRange().getA1Notation() == 'C8:D60');
  if (!matchingProtection1) return;
  matchingProtection1.remove();
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if (checkbox == true) {
    ss.getRange("AE9").setValue("false");
  }
}

Узнайте, как использовать расширенный сервис Sheet API:

  1. Добавьте службу Google Sheet API Advance:

Демо

Пример листа пользователя с повторяющимися защищенными диапазонами

После запуска функции checkDupes

Рекомендации

Включите Advances Google Service для Sheets API

Именованные и защищенные диапазоны Sheets API

Спасибо за ваш ответ. Очень хочется попробовать! Пожалуйста, знайте, что я не программист, но знаю достаточно, чтобы обойтись. Я ввел идентификатор своего листа во вторую строку. а потом попробуй сохранить. Синтаксическая ошибка: неожиданный токен '{', строка 8. Кроме того, в строке 14 после построителя запроса следует заменить тот же идентификатор листа, что и в строке 2?

PT109 30.04.2024 04:28

@ PT109 PT109 Я обновил свой ответ, в котором изменил ваш реальный сценарий, чтобы показать вам, как вы можете использовать образец функции checkDupes.

Serenity 30.04.2024 17:05

Работает отлично!! Ты мужчина!! Огромное спасибо, я много узнал о расширенном сервисе Google для Google Sheet API. Определенно гораздо быстрее.

PT109 30.04.2024 18:35

Кроме того, ваше решение вообще предотвращает дублирование. Второй ответ удаляет дубликаты на бэкэнде. Ваш намного лучше и эффективнее. Еще раз спасибо.

PT109 30.04.2024 20:32

Удалось собрать воедино ответ, который работает. Все несколько экземпляров защищенных ячеек одного диапазона удаляются. Флажок изменен с «истина» на «ложь».

function UnlockFriday() {
  var spreadsheet = SpreadsheetApp.openById('xxxxxxxxxxxxxx');
  var protections = spreadsheet.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.RANGE);
  spreadsheet.getRange('C8:D60').activate();
  for (var i = 0; i < protections.length; i++) {
    if (protections[i].getDescription() == 'AA Lock Friday Cells') {
protections[i].remove();
    }
    }  
  var ss = SpreadsheetApp.getActive();
  var checkbox = ss.getRange("AE9").getValue();
  if (checkbox==true){
    ss.getRange("AE9").setValue("false");
    }
 } 

Другие вопросы по теме