В Google Sheets как мне продублировать лист вместе с его разрешением

10

В электронной таблице Google под названием « Посещаемость» есть лист « Шаблон» . Пользователь дублирует этот лист, переименовывает лист с текущей датой и использует этот лист, чтобы отметить посещаемость для студентов. Лист шаблона содержит защищенные ячейки, и посещаемость отмечается путем ввода идентификационного номера учащегося в указанное место (незащищенные ячейки). Я использую следующий скрипт для дублирования нескольких листов и переименования их каждый день:

function createDailyAttendance() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var refss = ss.getSheetByName("DataPointers");

    // Get the range Row and Column information.
  var dataRangeRow = refss.getRange("K2").getValue();
  //var dataRangeCol = ss.getRangeByName(ColName).getValue();


   // Get the range of cells that store Duplicate sheet name.
  var AttendanceDataRange = refss.getRange(dataRangeRow);

  var AttendanceObjects = AttendanceDataRange.getValues();

  var template = ss.getSheetByName('Template');

  for (var i=0; i < AttendanceObjects.length; i++) {

     // Put the sheet you want to create in a variable
     var sheet = ss.getSheetByName(AttendanceObjects[i]);

      // Check if the sheet you want to create already exists. If so,
      // log this and loop back. If not, create the new sheet.
        if (sheet) {
           Logger.log("Sheet " + AttendanceObjects[i] + "already exists");
        } else {
           template.copyTo(ss).setName(AttendanceObjects[i]);
           }
        }
  return;
}

Этот скрипт помогает мне создавать несколько копий листов из шаблона, но дубликаты не сохраняют разрешения Cell / Range. Есть ли способ добавить функцию цикла, которая извлекает разрешение из шаблона и применяет его каждый раз, когда цикл template.copyToсоздает лист?

Эрвинд
источник
Пожалуйста , смотрите мою соответствующую должность здесь ... stackoverflow.com/questions/40512801/...
phinland

Ответы:

9

Сценарий 1: шаблон представляет собой защищенный лист с незащищенными диапазонами

В приведенном ниже сценарии я дублирую лист, получаю его защиту типа «Лист», затем защищаю новый лист таким же образом: то же описание, тот же тип. Если защита - это не просто предупреждение, удалите все редакторы и добавьте те, которые разрешены для исходного листа. Наконец, зациклите незащищенные диапазоны, переназначив каждый из них (через getA1Notation) на новый лист, и снимите защиту с них.

function duplicateProtectedSheet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  sheet = ss.getSheetByName("Sheet1");
  sheet2 = sheet.copyTo(ss).setName("My Copy"); 
  var p = sheet.getProtections(SpreadsheetApp.ProtectionType.SHEET)[0];
  var p2 = sheet2.protect();
  p2.setDescription(p.getDescription());
  p2.setWarningOnly(p.isWarningOnly());  
  if (!p.isWarningOnly()) {
    p2.removeEditors(p2.getEditors());
    p2.addEditors(p.getEditors());
    // p2.setDomainEdit(p.canDomainEdit()); //  only if using an Apps domain 
  }
  var ranges = p.getUnprotectedRanges();
  var newRanges = [];
  for (var i = 0; i < ranges.length; i++) {
    newRanges.push(sheet2.getRange(ranges[i].getA1Notation()));
  } 
  p2.setUnprotectedRanges(newRanges);
}  

Сценарий 2: шаблон представляет собой лист с защищенными диапазонами

Используя sheet.getProtectionsметод, вы можете получить массив защит на заданном листе и зациклить их, создавая их аналоги на целевом листе. Это несколько раздражает, потому что, похоже, нет способа просто клонировать защиту в другой диапазон. (Можно изменить диапазон защиты, но это переместит его на новый диапазон вместо копирования.)

Итак, в функции ниже я делаю следующее:

  1. Получить обозначение A1 каждого защищенного диапазона с помощью p.getRange().getA1Notation();
  2. Защитите соответствующий диапазон целевого листа с помощью p2 = sheet2.getRange(rangeNotation).protect();
  3. Установите свойства новой защиты в p2соответствии со свойствами исходной защиты p.
function duplicateSheetWithProtections() {
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  sheet = ss.getSheetByName('Template');
  sheet2 = sheet.copyTo(ss).setName('My Copy'); 
  var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
  for (var i = 0; i < protections.length; i++) {
    var p = protections[i];
    var rangeNotation = p.getRange().getA1Notation();
    var p2 = sheet2.getRange(rangeNotation).protect();
    p2.setDescription(p.getDescription());
    p2.setWarningOnly(p.isWarningOnly());
    if (!p.isWarningOnly()) {
      p2.removeEditors(p2.getEditors());
      p2.addEditors(p.getEditors());
      // p2.setDomainEdit(p.canDomainEdit()); //  only if using an Apps domain 
   }
  }
} 

Также возможно иметь защищенные диапазоны на защищенном листе, и в этом случае вам нужно будет объединить две функции (делайте все, что делает каждая из них, за исключением того, что вы будете дублировать лист только один раз).


источник
Я вставил ваше предложение в свой цикл и протестировал в Сценарии 1, я получил сообщение об ошибке TypeError: Cannot call method "protect" of null. Я получаю эту ошибку, потому что из этой строки var p2 = sheet.protect();.
Арвинд
1
Итак, что за черта sheet2.protect();? Тогда это означает, что sheet2 равен нулю, поэтому вы должны посмотреть на строку, где он определен.
В моем коде sheet2 упоминается как лист . Это определяется какvar sheet = ss.getSheetByName(AttendanceObjects[i]);
Арвинд
Тем не мение. Отладка вашего кода - это ваша работа, а не моя.