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.
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
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 :
- fichier origine
- onglet origine
- fichier destination
- onglet destination
- nom donné au pdf
- 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) ?