Script pour ajouter une nouvelle ligne toujours en première position

Bonjour à toutes et tous !

Je découvre depuis quelques jours la possibilité de passer par un script pour aller plus loin sur Google Sheet.

Dans un premier temps, j'ai créé un bouton (lié à mon premier script), qui me permet d'ajouter une ligne (à la suite des autres lignées déjà créées).

Ça fonctionne bien et ça garde même mes 3 checkbox et mes listes déroulantes. C'est top !

function addRow() {

  const activeRow = sheet.getLastRow();
  const newRow = activeRow;
  const newRange = sheet.getRange('A' + newRow + ':N' + newRow);
  newRange.activate();
  sheet.insertRowAfter(activeRow);
}

Maintenant, je me rends compte qu'il serait mieux que chaque nouvelle ligne créée se positionne toujours en première position (en décalant les lignes déjà existantes vers le bas). J'avoue que je sèche un peu et que la doc en anglais me bloque un peu.

En pseudo code ça donnerait :

- récupère la dernière ligne créée (avec mes checkbox / listes)

- génère une nouvelle ligne sur ce modèle

- insère là avant la dernière ligne créée

Si vous avez une piste, c'est bien volontiers !

Merci à vous

Bonjour,

pour insérer une ligne juste après la première ligne dans la première feuille

var doc = SpreadsheetApp.getActiveSpreadsheet();
var feuille = doc.getSheets()[0];
feuille.insertRowAfter(1);

as-tu un lien vers un fichier témoin ?

Bonjour Steelson !

Merci pour ta réponse, j'ai essayé ce bout de code, mais je n'ai réussi pas à avoir le résultat attendu... peut-être que je l'ai mal inséré/modifié ?

Je te laisse le lien du fichier en question, ça sera sans doute plus simple pour comprendre ce que je cherche à faire. J'ai mis une TODO dans mon script, tu auras les différents points sur lesquels je bloque depuis pas mal de temps.

https://docs.google.com/spreadsheets/d/12qyOVKmyys4A2HJjuCOe0itT_m3o09rfuh_tsatT4Ro/edit?usp=sharing

Merci beaucoup pour ton aide !

je t'ai fait une demande d'accès

C'est bon, j'ai validé la demande ;)

Voici ... MAIS

// Ajout d'une nouvelle ligne - function assignée au bouton vert
function addRow() {

  var doc = SpreadsheetApp.getActiveSpreadsheet();
  var feuille = SpreadsheetApp.getActive();
  feuille.insertRowAfter(3);

}

en effet j'avais une erreur !

MAIS le problème est que cette ligne va hériter des propriétés de la ligne 3 !! ce n'est pas top

je me suis créé une copie pour ne pas t'embêter, je vais regarder les différents points ce soir, cela n'empêche pas d'autres de regarder aussi !

[] Insérer la nouvelle ligne toujours en première position (décaler les lignes déjà créées vers le bas)

[] A chaque fois que la nouvelle ligne est créée, auto remplir la première case avec la date du jour

[] Lorsque la case "Archive" est cochée -> déplacer la ligne vers l'onglet Archive

[] Permettre un retour dans l'onglet Biomédical si la case "Archivé" est décochée dans Archive

question : pourquoi mettre en premier ? on peut trouver d'autres solutions selon ton objectif.

Solution

function addRow() {
  var doc = SpreadsheetApp.getActiveSpreadsheet();
  var feuille = SpreadsheetApp.getActive();
  feuille.insertRowAfter(3);
  var plage = feuille.getRange('A' + feuille.getLastRow() + ':N' + feuille.getLastRow()); 
  plage.copyTo(feuille.getRange('A4'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
  feuille.getRange("A4").setValue(new Date());
}

mais il ne faut pas dans ce cas avoir une ligne 3 tassée, le mieux serait de la supprimer

[x] Insérer la nouvelle ligne toujours en première position (décaler les lignes déjà créées vers le bas)

[x] A chaque fois que la nouvelle ligne est créée, auto remplir la première case avec la date du jour

Bonjour,

je peux vous proposer ceci.

function inRowDevant() {
 var classeur = SpreadsheetApp.getActiveSpreadsheet(); 
 var feuille = classeur.getSheetByName("journal"); //à modifier suivant demande
 var cell = feuille.getRange(3,1).activate();  
 var x = 3;                               

   feuille.insertRowBefore(x);

}

@ plus

Gilbert

C'est super ! Merci à vous deux !

En me servant de vos bouts de code, j'ai réussi à créer une ligne nouvelle créée à chaque fois au dessus la première.

Voici le code :

function addRow() {
   var classeur = SpreadsheetApp.getActiveSpreadsheet(); 
   var feuille = classeur.getSheetByName("Biomedical"); //à modifier suivant demande
   var cell = feuille.getRange(3,1).activate();  
   var x = 4;                               

   feuille.insertRowBefore(x);
   feuille.getRange("A4").setValue(new Date());
}

Pour résoudre le problème de ligne tassée, comme le précise Steelson, j'ai simplement changé la variable x en 4 (pour cibler la ligne 4).

Concernant ta question Steelson :

question : pourquoi mettre en premier ? on peut trouver d'autres solutions selon ton objectif.

Ce fichier va servir à une équipe pour notifier des mouvements de matériels, l'idée étant qu'il est plus simple que chaque nouvelle ligne apparaissent en premier (pour avoir la date la plus récente en premier).

Du coup, et grâce à votre aide, la nouvelle ligne apparait à chaque fois en premier (avec la date du jour automatiquement remplie dans la première case) !

--

Maintenant, pour pouvoir déplacer la ligne, uniquement si la case "archivé" est cochée, vers un autre onglet (Archive), je suppose que cela correspond à ce bout de code Steelson :

var plage = feuille.getRange('A' + feuille.getLastRow() + ':N' + feuille.getLastRow()); 
plage.copyTo(feuille.getRange('A4'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);

Je ne saisi pas trop comment cela fonctionne, dans mon idée, c'est que si la case est cochée, la ligne est déplacée vers l'onglet Archive, si jamais la case est décochée dans Archive, elle retourne automatique dans l'onglet d'origine.

En réalité je me demande si cette fonction est possible ?

PS : Le lien que je t'ai partagé est une copie du fichier original, tu peux aisément le modifier si tu préfères, je viens d'y ajouter le bout de code fonctionnel cité tout en haut de cette réponse.

je suis de retour ...

Maintenant, pour pouvoir déplacer la ligne, uniquement si la case "archivé" est cochée, vers un autre onglet (Archive), je suppose que cela correspond à ce bout de code Steelson :

var plage = feuille.getRange('A' + feuille.getLastRow() + ':N' + feuille.getLastRow()); 
plage.copyTo(feuille.getRange('A4'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);

Je ne saisi pas trop comment cela fonctionne, dans mon idée, c'est que si la case est cochée, la ligne est déplacée vers l'onglet Archive, si jamais la case est décochée dans Archive, elle retourne automatique dans l'onglet d'origine.

En réalité je me demande si cette fonction est possible ?

il faudra mettre en place un "trigger" ou déclencheur sur une fonction qui s'activera quand tu cliqueras sur la case à cocher ... je te le fais ...

je propose ceci

function addRow() {
  var classeur = SpreadsheetApp.getActiveSpreadsheet(); 
  var feuille = classeur.getSheetByName("Biomedical");
  var x = 4;                               
  feuille.insertRowBefore(x);
  var cell = feuille.getRange(4,1).activate();
  cell.setValue(new Date());
}

function archive(){
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var feuille = classeur.getSheetByName("Biomedical");
var archive = classeur.getSheetByName("Archive");
var lg = feuille.getLastRow();
var a = archive.getLastRow()+1;
for (var i= 1;i<lg+1;i++){ 
var plage = feuille.getRange('A' + i + ':N' + i); 
var coche = feuille.getRange('N' + i).getValue();
//Browser.msgBox(coche);
if (coche === true){plage.copyTo(archive.getRange('A'+ a), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false)
a++;
}
};
}

et une fois archivée on peut supprimer la ligne qui a été archivée de la feuille "Biomedical"

ah ben voir réponse ci-dessus (j'ai la même chose à l'écriture près)

edit : quoique la différence est que j'archive au moment du clic avec un déclencheur - j'ai laissé ton fichier modifié en l'état sans enlever le test que j'avais fait

edit2 : pour la suppression ajoute

feuille.deleteRow(i);

ou ceci ;-)))))

function archive(){
var classeur = SpreadsheetApp.getActiveSpreadsheet();
var feuille = classeur.getSheetByName("Biomedical");
var archive = classeur.getSheetByName("Archive");
var lg = feuille.getLastRow();
var a = archive.getLastRow()+1;
for (var i= 1;i<lg+1;i++){ 
var plage = feuille.getRange('A' + i + ':N' + i); 
var coche = feuille.getRange('N' + i).getValue();
//Browser.msgBox(coche);
if (coche === true){plage.copyTo(archive.getRange('A'+ a), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false)
a++;
plage.activate();
classeur.getActiveSheet().deleteRows(classeur.getActiveRange().getRow(), classeur.getActiveRange().getNumRows());
}
};
}

C'est fou, je n'aurai jamais réussi à faire cela solo !

Néanmoins deux questions :

- Est-il possible, de créer une nouvelle ligne à chaque ajout sur Archive ? (actuellement c'est bloqué à 7 lignes, il faut rajouter des lignes supplémentaires à la main) ?

J'aurai aimé que cela fasse comme la génération d'une nouvelle ligne comme sur Biomedical.

- Tout comme sur Biomedical, est-il possible de faire en sorte que l'archive se fasse dans le même ordre ? la dernière ligne archivée se positionne en haut du fichier Archive ?

Mille merci pour votre aide

Une version double archivage/ré-activation uniquement sur le clic du check-box

Les lignes sont insérées en tête.

// on déclenche sur une modification >> cliquer sur horloge et définir le déclencheur
function transfert(){ 
  var feuille = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var r = SpreadsheetApp.getActiveSpreadsheet().getActiveRange();
  if (r.getColumn() == 14 && feuille.getName() == 'Biomedical'){ 
    if(r.getValue() == 1){ 
      var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Archive");
      destination.insertRowBefore(2);
      var plage = feuille.getRange('A' + r.getRow() + ':N' +  r.getRow()); 
      plage.copyTo(destination.getRange('A2'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);  
      Browser.msgBox("Ligne " + r.getRow() + " archivée !");
      feuille.deleteRow(r.getRow());
    }
  } 
  if (r.getColumn() == 14 && feuille.getName() == 'Archive'){ 
    if(!r.getValue()){ 
      var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Biomedical");
      destination.insertRowBefore(4);
      var plage = feuille.getRange('A' + r.getRow() + ':N' +  r.getRow()); 
      plage.copyTo(destination.getRange('A4'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);  
      Browser.msgBox("Ligne " + r.getRow() + " ré-activée !");
      feuille.deleteRow(r.getRow());
    }
  }
}

On pourrait faire une macro plus condense mais avec le risque de perte de lisibilité.

Attention : mettre en place le déclencheur

capture d ecran 298

https://docs.google.com/spreadsheets/d/12qyOVKmyys4A2HJjuCOe0itT_m3o09rfuh_tsatT4Ro/edit?usp=sharing

Ça fonctionne parfaitement bien !

Merci pour le temps passé et pour votre aide si précieuse !

Bonsoir !

Une petite question concernant cette function :

function transfert(){ 
  var feuille = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var r = SpreadsheetApp.getActiveSpreadsheet().getActiveRange();
  if (r.getColumn() == 14 && feuille.getName() == 'Biomedical'){ 
    if(r.getValue() == 1){ 
      var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Archive-biomed");
      destination.insertRowBefore(2);
      var plage = feuille.getRange('A' + r.getRow() + ':N' +  r.getRow()); 
      plage.copyTo(destination.getRange('A2'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);  
      Browser.msgBox("Ligne archivée !");
      feuille.deleteRow(r.getRow());
    }
  } 
  if (r.getColumn() == 14 && feuille.getName() == 'Archive-biomed'){ 
    if(!r.getValue()){ 
      var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Biomedical");
      destination.insertRowBefore(4);
      var plage = feuille.getRange('A' + r.getRow() + ':N' +  r.getRow()); 
      plage.copyTo(destination.getRange('A4'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);  
      Browser.msgBox("Ligne ré-activée !");
      feuille.deleteRow(r.getRow());
    }
  }
}

Est-il possible de rajouter une condition dans cette function afin d'empêcher la copie vers l'autre onglet si :

- La case "Retour" est à false (case à cocher) -> pas de déplacement vers l'onglet même si "Archivé" est coché ? (peut-être un Browser.msgBox()/prompt() pour signaler l'obligation de cocher 'Retour' afin d'être clair vis à vis de mes collègues ?)

Je reconnais que c'est un point de détail mais j'aimerai que ce soit clean ;)

Merci par avance !

PS : si jamais vous avez de la documentation/tutos/liens pour apprendre correctement à créer des scripts, je suis preneuse ! (la documentation Google est bien mais ... technique et pauvre en exemple).

C'est assez frustrant de ne pas réussir par moi-même alors que j'ai pas mal de connaissances en JS ! et ça évitera que j'inonde le forum de mes multiples questions sans arrêt ;)

Voici pour une partie du code

// .........................
  if (r.getColumn() == 14 && feuille.getName() == 'Biomedical'){ 
    if(r.getValue() == true){ 
      if(!feuille.getRange("I" + r.getRow()).getValue()){
        Browser.msgBox("Le retour n'est pas coché !");
        r.setValue(false);
      }else{
        var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Archive-biomed");
        destination.insertRowBefore(2);
        var plage = feuille.getRange('A' + r.getRow() + ':N' +  r.getRow()); 
        plage.copyTo(destination.getRange('A2'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);  
        Browser.msgBox("Ligne archivée !");
        feuille.deleteRow(r.getRow());
      }
    }
  }
// .........................

nota : mis dans le fichier toujours disponible en ligne

Merci beaucoup Steelson ! ça fonctionne parfaitement bien !

Rechercher des sujets similaires à "script ajouter nouvelle ligne premiere position"