Glide vers Sheet vers PDF

Bonjour à tous,

J'ai un fichier Sheet qui se remplie grâce à une application Glide (tous les jours, une nouvelle ligne).

Malheureusement, la mise en page ne correspond pas tout à fait à ce que je recherche.

Aussi, j'aimerais pouvoir faire en sorte que la ligne ajoutée tous les jours soit copiée dans un autre onglet dont la mise en page est travaillée. Et que j'enregistre cet onglet en PDF (Un utilisateur du forum m'avait déjà proposé un script pour l'enregistrer PDF).

Ce "transfert" peut se faire manuellement (peut-être une fois par semaine par exemple), grâce à une action de ma part qui viendrait copier une ligne après l'autre. Et qu'une fois que cela est fait, une case soit cochée dans l'onglet initial par exemple, afin que la copie ne démarre qu'à compter de la case vide.

J'espère avoir été clair dans mes explications. Peut-être existe t-il d'autres solutions.

Je vous remercie par avance de votre aide.

juju

Bonjour juju,

Voici un outil qui te permet de reporter tes valeurs

  • issues de la ligne row
  • de la feuille data
  • dans la liste des cellules listées
  • de la feuille mySheetName
  • en cochant en final la dernière case de la ligne
  • et en sortant une copie pdf dans le dossier folderID

Tu peux créer un déclencheur quotidien qui balaye ta feuille data et active ce script pour les lignes dont la case n'est pas cochée

Il faut activer le service Google Sheets API

function reporterValeurs(row = 2) {

  // lise à jour de la feuille 
  const sheetName = 'mySheetName' // à adapter
  const list = ['C3', 'E3', 'C5', 'E5', 'C7', 'C9', 'E9', 'G9'] // à adapter

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName('data');  // à adapter            

  const ranges = []
  const values = []
  list.forEach((c, i) => {
    ranges.push(`'${sheetName}'!${c}`)
    values.push(`${sh.getRange(row, +i + 1).getValue()}`)
  })

  const data = ranges.map((e, i) => ({ range: e, values: [[values[i]]] }));
  Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" }, ss.getId());
  sh.getRange(row, +list.length + 1).setValue(true)

  // sortie pdf de la feuille
  const folderID = '18akqHAN7PSPMnG3h5HpCskQsMCv4TqCM'  // à adapter
  const filename = sh.getRange(row, 1).getValue() + ".pdf"  // à adapter
  const url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/" 
            + ss.getId() 
            + "/export?exportFormat=pdf&gid=" 
            + ss.getSheetByName(sheetName).getSheetId() 
            + "&access_token=" + ScriptApp.getOAuthToken();
  const blob = UrlFetchApp.fetch(url).getBlob().setName(filename);
  const file = DriveApp.getFolderById(folderID).createFile(blob);
  console.log(file.getUrl())

}

Bonjour Steelson,

Merci pour ton retour (encore une fois :))

Et serait-il possible de couper/coller vers un autre fichier plutôt qu'un autre onglet ? Et c'est mon autre feuille qui fait le travail de transformer cela en PDF grâce au script que tu m'as déjà donné ?

Belle journée,

juju

J'aurais en fait 2 classeurs :

Le premier : https://docs.google.com/spreadsheets/d/1vAmxLhSyI-KH04MYDMnVk5rQVmFmDIoQICShx_6AFU8/edit?usp=sharing qui récupère les infos depuis l'application.

Et qui enverrait au second classeur : https://docs.google.com/spreadsheets/d/1Abl132xxvRE8uRiZYRuMgkQGkCfwxueBJFmvzL_QwPg/edit?usp=sharing qui transformerait cela en PDF et conserverait le GED pour retrouver facilement.

juju

Et serait-il possible de couper/coller vers un autre fichier plutôt qu'un autre onglet ? Et c'est mon autre feuille qui fait le travail de transformer cela en PDF grâce au script que tu m'as déjà donné ?

Dans ce cas, remplace la ligne contenant batchUpdate par

Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" }, '1Abl132xxvRE8uRiZYRuMgkQGkCfwxueBJFmvzL_QwPg' );

et vérifie que le fichier contient bien le nom de la feuille que tu as spécifiée

const sheetName = 'mySheetName'

modifie en conséquence aussi la sortie pdf : remplace ss.getId() par '1Abl132xxvRE8uRiZYRuMgkQGkCfwxueBJFmvzL_QwPg' et ss.getSheetByName(sheetName).getSheetId() par 0 ou directement pas son gid

J'ai essayé pas mal de choses mais rien ne fonctionne.

Dois-je ajouter une fonction dans le menu pour activer le transfert ?

Est-ce que ceci fonctionnait ? https://forum.excel-pratique.com/sheets/glide-vers-sheet-vers-pdf-173264#p1074748

Sinon, quelle est l'erreur ?

Ensuite je regarderai le second point.

as-tu activé ce service ?

Il faut activer le service Google Sheets API

image

J'ai essayé pas mal de choses mais rien ne fonctionne.

Il y a beaucoup d'écarts par rapport aux consignes données

1-

Mettre ici la feuille de destination comme j'avais indiqué et non :

const sheetName = 'Fiche journalière'

2-

Mettre la feuille d'origine des données comme j'avais indiqué et non :

 const sh = ss.getSheetByName('Reprise appli');

3-

Il ne faut mettre que l'identifiant du fichier destination comme j'avais proposé et non

Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" },  'https://docs.google.com/spreadsheets/d/1Abl132xxvRE8uRiZYRuMgkQGkCfwxueBJFmvzL_QwPg/edit?usp=sharing' );

4-

Activer le service Google Sheets API comme demandé

5-

Sans fichier, j'avais indiqué que c'était la dernière case de la ligne qui était cochée

Pour le moment, impossible d'accéder à script :/

capture d ecran 2022 06 25 a 22 29 44

Quelqu'un a déjà eu cet incident ?

J'ai beau rafraichir, fermer, ouvrir, déconnecter, reconnecter ...

Rien à faire :/

Exemple complet à adapter

const ss = SpreadsheetApp.getActiveSpreadsheet();
const source = ss.getSheetByName('BdD');                 // source, à adapter
const destination = 'pour impression pdf'                // destination, à adapter
const rngDest = ['C3', 'E3', 'C5', 'E5', 'C7']           // à adapter (dans la feuille destination)
const folderID = '18akqHAN7PSPMnG3h5HpCskQsMCv4TqCM'     // à adapter

function onOpen() {
  SpreadsheetApp.getUi().createMenu('⇩ M E N U ⇩')
    .addItem('👉 Editer en pdf et stocker', 'editionsPDF')
    .addToUi();
}

function editionsPDF() {
  source.getDataRange().getValues().forEach((r, i) => {
    if (!r[0] && r[1] != '') {
      reporterValeurs(+i + 1)
    }
  })
}

function reporterValeurs(row) {

  const ranges = []
  const values = []
  rngDest.forEach((c, i) => {
    ranges.push(`'${destination}'!${c}`)
    values.push(`${source.getRange(row, +i + 2).getValue()}`)                // on commence à la colonne B
  })

  const data = ranges.map((e, i) => ({ range: e, values: [[values[i]]] }));
  Sheets.Spreadsheets.Values.batchUpdate({ data, valueInputOption: "USER_ENTERED" }, ss.getId());

  SpreadsheetApp.flush()

  // sortie pdf de la feuille
  const filename = source.getRange(row, 2).getValue() + ".pdf"                // à adapter, le nom est pris ici en colonne B
  const url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/"
    + ss.getId()
    + "/export?exportFormat=pdf&gid="
    + ss.getSheetByName(destination).getSheetId()
    + "&access_token=" + ScriptApp.getOAuthToken();
  const blob = UrlFetchApp.fetch(url).getBlob().setName(filename);
  const file = DriveApp.getFolderById(folderID).createFile(blob);
  console.log(file.getUrl())

  source.getRange(row, 1).setValue(true)                                      // indicateur en colonne A

}

https://docs.google.com/spreadsheets/d/1O8I4VS9dlorINbJAbkG6RZjewaOxY3xOnIdT4Gqgfw4/copy

Bonjour Steelson,

J'ai enfin réussi à régler le problème qui m'empêchait d'accéder à Script.

Quelques questions (désolé pour mon novisme).

Ce code doit-il être entré dans mon classeur source ou mon classeur destination ?

Pour le moment, je l'ai intégré dans le classeur source. Et j'ai un soucis avec :

GoogleJsonResponseException: Échec de l'appel d'API vers sheets.spreadsheets.values.batchUpdate avec l'erreur suivante : Invalid data[0]: Unable to parse range: 'Reprise appli'!B2

Autre question. A quoi correspond

const rngSource = ['C3', 'E3', 'C5', 'E5', 'C7']

A quoi doivent correspondre les C3, E3, ... ?

Merci :)

as-tu essayé cet exemple https://forum.excel-pratique.com/sheets/glide-vers-sheet-vers-pdf-173264#p1075298, est-ce qu'il fonctionne chez toi après avoir mis l'id du dossier ici

const folderID = '18akqHAN7PSPMnG3h5HpCskQsMCv4TqCM'     // à adapter

?

['C3', 'E3', 'C5', 'E5', 'C7'] correspondent aux cellules de la feuille de destination ... appelée ici pour impression pdf

j'ai revu le code avec des noms de feuilles plus parlants pour moi ...

C'est bien le code de l'exemple que j'ai utilisé ;)

Mais j'ai une erreur GoogleJsonResponseException: Échec de l'appel d'API vers sheets.spreadsheets.values.batchUpdate avec l'erreur suivante : Invalid data[0]: Unable to parse range: 'Pour impression'!B2

J'ai bien activé l'API dans les 2 fichiers.

L'adresse est la bonne.

Les feuilles sont bien nommées.

peux-tu redonner l'url de ton fichier ?

Va falloir tout reprendre à 0, C'est un vrai mic mac. En plus les noms des fichiers se ressemblent ainsi que les noms d'onglets mai qui ne veulent pas dire la même chose. Les services API ne sont pas activés.

Redis clairement :

  1. fichier origine
  2. onglet origine
  3. fichier destination
  4. onglet destination
  5. nom donné au pdf
  6. liste des cellules de destination

Il y a des scripts résiduels dont on se demande à quoi ils servent.

Les services API sont activés sur mes vrais fichiers :) Ici, il s'agit de copie.

Depuis Glide --> Fichier et onglet d'origine. Cet onglet d'origine, je voudrais que ça coupe et colle dans mon fichier de destination pour vider mon ficher d'origine. Soit automatiquement, soit manuellement, peu importe.
Ensuite, de mon onglet de destination, prendre ligne à ligne, les transformer en pdf via l'onglet de destination 2. Cet onglet, enregistre en pdf et vient en faire une liste dans GED que tu m'avais créé à l'époque.

Quand c'est dans GED, pas besoin que la ligne reste dans onglet de destination 1.

Fichier d'origine : Copie de fiche journalière - appli

Onglet d'origine : Fiche journalière

Fichier de destination : Copie de fiche journalière

Onglet de destination 1 : Pour impression (exactement le même format que fiche journalière --> B2 vers B2, ...).

Puis, depuis 'pour impression' vers 'Fiche journalière PDF' = onglet de destination 2 (qui prend par exemple la cellule B2 pour l'envoyer en C4, E2 en H5, ...).

Ensuite, j'ai le code que tu m'avais rempli pour le transformer et l'enregistrer en PDF, ça c'est OK.

function savePDF()
{
 // SÉLECTIONNER LA FEUILLE A SAUVEGARDER
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var sheet = ss.getActiveSheet();

//URL de SS ?
    var ssUrl = ss.getUrl();
    var sheetId= sheet.getSheetId();

    var url = ssUrl.replace(/\/edit.*$/,'')
      + '/export?exportformat=pdf&format=pdf'
      + '&size=LETTER'
      + '&portrait=true'
      + '&fitw=true'
      + '&top_margin=0.50'              
      + '&bottom_margin=0.50'          
      + '&left_margin=0.50'             
      + '&right_margin=0.50'           
      + '&sheetnames=false'
      + '&printtitle=false'
      + '&pagenum=false'
      + '&gridlines=false'
      + '&fzr=FALSE'
      + '&gid='+sheetId;
// RÉCOLTER LES INFORMATIONS DANS LE SHEET POUR COMPOSER LE NOM DU DOCUMENT
  var docId = sheet.getRange('B2').getValue();
  var docDate = sheet.getRange('C4').getValue();

  //mise en forme de la date : annee-mois-jour
 var docDateYYMMJJ = (docDate.getFullYear()+"-"+(docDate.getMonth()+1)+"-"+(docDate.getDate()+1));

  // Concaténons le tout 
  var docName = docId+"_"+docDateYYMMJJ ;
// CRÉER LE PDF A PARTIR DE L'URL
  var token = ScriptApp.getOAuthToken();
  var docurl = UrlFetchApp.fetch(url, { headers: { 'Authorization': 'Bearer ' +  token } });
  var pdf = docurl.getAs('application/pdf').setName(docName);

  var file = DriveApp.createFile(pdf);

//  DEPLACER LE PDF DANS LE BON DOSSIER  

  var folder = DriveApp.getFolderById("XXXXX"); 
  var finalFile = file.moveTo(folder);

  //RÉCUPÉRER LE LIEN
     var docUrl = finalFile.getUrl();

//ajouter l'urL dans la GED.
    var sheetGed = ss.getSheetByName('GED');
   sheetGed.appendRow([new Date(),docId,docUrl,docName]);

}

J'espère que c'est plus clair.

Merci Steelson.

ok merci

je vais regarder à tête reposée, merci pour ces précisions, je vais t'indiquer les modifications (j'ai mieux compris l'articulation)

J'ai retrouvé où si situaient les infos

Date                    C4
Heure d'ouverture    C5
Heure de fermeture    C6
Météo matin            H5
Météo après-midi    H6
Vent                    H7
Personnel présent    B12:B17
Responsable du jour    H11
Contrôle des installations - pandas [Cheminements]    C21
Contrôle des installations - pandas [Plateformes]    C22
Contrôle des installations - pandas [Ateliers]            C23
Contrôle des installations - pandas [Anti-chutes]    C24
Contrôle des installations - pandas [Tyroliennes]    C25
Contrôle des installations - pandas [Aire d'arrivée tyroliennes]    C26
Contrôle des installations - pandas [Arbres supports]    C27
Contrôle des installations - Verts [Cheminements]    D21
Contrôle des installations - Verts [Plateformes]    D22
Contrôle des installations - Verts [Ateliers]            D23
Contrôle des installations - Verts [Anti-chutes]    D24
Contrôle des installations - Verts [Tyroliennes]    D25
Contrôle des installations - Verts [Aire d'arrivée tyroliennes]    D26
Contrôle des installations - Verts [Arbres supports]    D27
Contrôle des installations - Bleus [Cheminements]    E21
Contrôle des installations - Bleus [Plateformes]    E22
Contrôle des installations - Bleus [Ateliers]            E23
Contrôle des installations - Bleus [Anti-chutes]    E24
Contrôle des installations - Bleus [Tyroliennes]    E25
Contrôle des installations - Bleus [Aire d'arrivée tyroliennes]    E26
Contrôle des installations - Bleus [Arbres supports]    E27
Contrôle des installations - Rouges [Cheminements]    F21
Contrôle des installations - Rouges [Plateformes]    F22
Contrôle des installations - Rouges [Ateliers]            F23
Contrôle des installations - Rouges [Anti-chutes]    F24
Contrôle des installations - Rouges [Tyroliennes]    F25
Contrôle des installations - Rouges [Aire d'arrivée tyroliennes]    F26
Contrôle des installations - Rouges [Arbres supports]    F27
Contrôle des installations - Noir [Cheminements]    G21
Contrôle des installations - Noir [Plateformes]            G22
Contrôle des installations - Noir [Ateliers]            G23
Contrôle des installations - Noir [Anti-chutes]            G24
Contrôle des installations - Noir [Tyroliennes]            G25
Contrôle des installations - Noir [Aire d'arrivée tyroliennes]    G26
Contrôle des installations - Noir [Arbres supports]            G27
Contrôle des installations - Tyrolienne 900m [Cheminements]    H21
Contrôle des installations - Tyrolienne 900m [Plateformes]    H22
Contrôle des installations - Tyrolienne 900m [Ateliers]            H23
Contrôle des installations - Tyrolienne 900m [Anti-chutes]    H24
Contrôle des installations - Tyrolienne 900m [Tyroliennes]    H25
Contrôle des installations - Tyrolienne 900m [Aire d'arrivée tyroliennes]    H26
Contrôle des installations - Tyrolienne 900m [Arbres supports]    H27
Commentaires    B32
Photo            B42
Contrôleur    C46

MAIS ...

1-

si je comprends bien, il peut y avoir des réponses multiples ici ??

Personnel présent    B12:B17
et que veux tu mettre dans les cases à cocher en C12:C17 ?

2-
il n'y a pas de questions sur les espaces défis ?

3-
peut-il y avoir la même codification entre le formulaire et la fiche (d'un côté BON et de l'autre B) ?
Rechercher des sujets similaires à "glide sheet pdf"