En Google Sheets, ¿cómo duplico una hoja junto con su permiso?

10

En una hoja de cálculo de Google llamada Asistencia, hay una hoja llamada Plantilla . El usuario duplica esta hoja, cambia el nombre de la hoja con la fecha actual y la utiliza para marcar la asistencia de los estudiantes. La hoja de plantilla contiene celdas protegidas y la asistencia se marca ingresando el número de identificación del estudiante en el espacio asignado (celdas desprotegidas). Utilizo el siguiente script para duplicar varias hojas y cambiarles el nombre todos los días:

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;
}

Este script me ayuda a crear múltiples copias de hojas desde la Plantilla, pero las copias duplicadas no retienen los permisos de Celda / Rango. ¿Hay alguna manera de agregar una función de bucle que extraiga el permiso de Template y lo aplique cada vez que el bucle template.copyTocree una hoja?

Arvind
fuente
Vea mi publicación relacionada aquí ... stackoverflow.com/questions/40512801/…
phinland

Respuestas:

9

Escenario 1: la plantilla es una hoja protegida con rangos desprotegidos

En el siguiente script, duplico la hoja, obtengo su protección del tipo de Hoja, luego protejo la nueva hoja de la misma manera: misma descripción, mismo tipo. Si la protección no es solo una advertencia, elimine todos los editores y agregue los permitidos para la hoja original. Finalmente, repita los rangos desprotegidos, reasignando cada uno de ellos (vía getA1Notation) a la nueva hoja, y desproteja esos.

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);
}  

Escenario 2: la plantilla es una hoja con rangos protegidos

Usando el sheet.getProtectionsmétodo, puede obtener el conjunto de protecciones en una hoja determinada y recorrerlas, creando sus análogos en la hoja de destino. Esto es algo molesto porque parece no haber un método para simplemente clonar una protección a otro rango. (Se puede cambiar el rango de protección, pero eso lo movería al nuevo rango, en lugar de copiarlo).

Entonces, en la función a continuación hago lo siguiente:

  1. Obtenga la notación A1 de cada rango protegido con p.getRange().getA1Notation();
  2. Proteja el rango correspondiente de la hoja de destino con p2 = sheet2.getRange(rangeNotation).protect();
  3. Establezca las propiedades de la nueva protección p2según las propiedades de la protección original 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 
   }
  }
} 

También es posible tener rangos protegidos dentro de una hoja protegida, en cuyo caso necesitaría combinar las dos funciones (haga todo lo que haga cada una de ellas, excepto que, por supuesto, duplicará la hoja solo una vez).


fuente
Inserté su sugerencia en mi bucle y probé en el Escenario 1, recibí un mensaje de error TypeError: Cannot call method "protect" of null. Recibo este error porque de esta línea var p2 = sheet.protect();.
Arvind
1
Entonces, ¿esa era la línea sheet2.protect();? Entonces significa que sheet2 es nulo, por lo que debe mirar la línea donde está definida.
En mi código, sheet2 se conoce como hoja . Se define comovar sheet = ss.getSheetByName(AttendanceObjects[i]);
Arvind
De todas formas. La depuración de su código es su trabajo, no el mío.