J'ai une feuille de modèle pour la saisie de données de groupe. La plupart de la feuille est en entrée libre, mais il y a des lignes de titre que je ne veux pas modifier, donc je les ai protégées. Nous avons un de ces onglets pour chaque jour du mois et une nouvelle feuille pour chaque mois.

Je veux copier le modèle 30-31 fois selon le mois et faire en sorte que le titre de la feuille soit la date correspondante (MM.dd.yy soit : 11.02.20). J'ai la Date définie en A2 (c'est-à-dire : 11/01/2020).

Jusqu'à présent, j'ai essayé de combiner une protection et un changement de date, mais j'obtiens toujours des erreurs variables et parfois cela crée des feuilles en double (comme le 11.06.20 puis s'arrête).

C'est le code que j'ai essayé (et édité et déplacé plusieurs fois).

function duplicateSheetWithProtections() {
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var s = ss.getActiveSheet();
  var dateCell = "A2";
  sheet = ss.getSheetByName('Template.01.20');
  sheet2 = sheet.copyTo(ss).setName('11..20'); 
  var N = 30;
  var startDate = new Date(s.getRange(dateCell).getValue());
  var day = startDate.getDate();
  var month = startDate.getMonth();
  var year = startDate.getFullYear();
  for (var i = 0; i < N; i++) {
    var asn = s.copyTo(ss);
    var thisSheetDate = new Date(year, month, day+(i+1));
    asn.getRange(dateCell).setValue(thisSheetDate);
    asn.setName(Utilities.formatDate(thisSheetDate, "GMT-08:00", "MM.dd.yy"));
  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());
   }
  }
 }
}

Toute aide serait grandement appréciée. Aussi, nouveau dans ce domaine et si vous ne pouviez pas le dire, une sorte de noob. Donc, toutes les références pour aider à grandir seraient géniales. Merci!

0
J M 13 nov. 2020 à 09:12

1 réponse

Meilleure réponse

Problème:

Vous utilisez la même variable (i) pour deux boucles for différentes, l'une imbriquée dans l'autre. Cela perturbe vos dates, ce qui provoque l'erreur que vous obtenez.

Solution:

Modifiez le nom de variable de la boucle interne (par exemple, en j) :

  for (var j = 0; j < protections.length; j++) {
    var p = protections[j];

Autres problèmes :

  • Vous définissez des protections sur sheet2, ce qui correspond à la feuille copiée portant le nom 11..20, mais pas au reste des feuilles (en fait, je ne sais pas à quoi ça sert de faire cette copie, alors je Je supprimerais simplement la ligne sheet2 = sheet.copyTo(ss).setName('11..20');). Afin de définir les protections sur chaque feuille copiée, vous devez utiliser asn à la place :
var p2 = asn.getRange(rangeNotation).protect();
  • Puisque vous voulez copier le fichier nommé Template.01.20, il ne sert à rien d'obtenir la feuille active et de la stocker dans s. Je voudrais juste changer les mentions de s en sheet (et supprimer la ligne var s = ss.getActiveSheet();, car ce n'est pas nécessaire):
var startDate = new Date(sheet.getRange(dateCell).getValue());
// ...
var asn = sheet.copyTo(ss);
  • Étant donné que le nombre de feuilles à copier dépend du nombre de jours du mois, je vous suggère de trouver ce nombre de manière dynamique. Vous pouvez le faire en utilisant la fonction suivante, par exemple (crédits à Juan Mendes) :
function getDaysInMonth(year, month, day) {
  var date = new Date(year, month, day);
  var days = [];
  while (date.getMonth() === month) {
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  }
  return days;
}

Que vous pourriez ensuite appeler dans votre fonction principale :

  var dates = getDaysInMonth(year, month, day + 1);
  for (var i = 0; i < dates.length; i++) {
    var asn = sheet.copyTo(ss);
    var thisSheetDate = dates[i];

Échantillon de code:

Par conséquent, votre code pourrait plutôt ressembler à ceci :

function duplicateSheetWithProtections() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var dateCell = "A2";
  var sheet = ss.getSheetByName('Template.01.20');
  var startDate = new Date(sheet.getRange(dateCell).getValue());
  var day = startDate.getDate();
  var month = startDate.getMonth();
  var year = startDate.getFullYear();
  var dates = getDaysInMonth(year, month, day + 1);
  for (var i = 0; i < dates.length; i++) {
    var asn = sheet.copyTo(ss);
    var thisSheetDate = dates[i];
    asn.getRange(dateCell).setValue(thisSheetDate);
    asn.setName(Utilities.formatDate(thisSheetDate, "GMT-08:00", "MM.dd.yy"));
    var protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
    for (var j = 0; j < protections.length; j++) {
      var p = protections[j];
      var rangeNotation = p.getRange().getA1Notation();
      var p2 = asn.getRange(rangeNotation).protect();
      p2.setDescription(p.getDescription());
      p2.setWarningOnly(p.isWarningOnly());
      if (!p.isWarningOnly()) {
        p2.removeEditors(p2.getEditors());
        p2.addEditors(p.getEditors());
      }
    }
  }
}

function getDaysInMonth(year, month, day) {
  var date = new Date(year, month, day);
  var days = [];
  while (date.getMonth() === month) {
    days.push(new Date(date));
    date.setDate(date.getDate() + 1);
  }
  return days;
}
0
Iamblichus 16 nov. 2020 à 13:54