Overwrite existing file in a specific Google Drive folder - google-apps-script

I need the var file = dir.createFile(blob).setContent('Stores_Month.pdf'); to every time, overwrite the existing Stores_Month.pdf file in the specified Google Drive folder.
function runCBUEBUquarterly() {
var file = DriveApp.getFilesByName("Data_Stores_Quarter.csv").next();
var csvData = Utilities.parseCsv(file.getBlob().getDataAsString());
var sheet = SpreadsheetApp.getActive().getSheetByName('Data_Month');
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
/* Highlight all sort range and sort by AS - Okanagan */
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActive().getSheetByName('Stores_Month');
var range = sheet.getRange("A5:AS10");
// Sorts by the values in column (AS)
range.sort({column: 45, ascending: false});
/* Highlight all sort range and sort by AS - LM & Whistler */
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActive().getSheetByName('Stores_Month');
var range = sheet.getRange("A13:AS24");
// Sorts by the values in column (AS)
range.sort({column: 45, ascending: false});
/* Save as PDF to Google Drive */
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActive().getSheetByName('Stores_Month');
var url = ss.getUrl();
//remove the trailing 'edit' from the url
url = url.replace(/edit$/,'');
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' + //export as pdf
//below parameters are optional...
'&size=letter' + //paper size
'&portrait=false' + //orientation, false for landscape
'&fitw=false' + //fit to width, false for actual size
'&pagenumbers=true' + //fit to width, false for actual size
'&sheetnames=false&printtitle=false' + //hide optional headers and footers
'&gridlines=false' + //hide gridlines
'&fzr=true' + //do not repeat row headers (frozen rows) on each page
'&gid=' + sheet.getSheetId(); //the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var blob = response.getBlob().setName(sheet.getName() + '.pdf');
//from here you should be able to use and manipulate the blob to send and email or create a file per usual.
//In this example, I save the pdf to drive
var dir = DriveApp.getFoldersByName('CBU & EBU - Quarterly Tracker').next();
var file = dir.createFile(blob).setContent('Stores_Month.pdf');
}

You'll probably need to use something like the following code. I haven't tested it, but try it out, and see what happens:
var dir, file, newContent;
//dir = DriveApp.getFoldersByName('CBU & EBU - Quarterly Tracker').next();
dir = DriveApp.getFolderById('put the folder ID here');//Get folder by ID
file = dir.getFilesByName('Stores_Month.pdf').next();
if (file) {//There is an existing file by that name
newContent = blob.getDataAsString();
Logger.log('blob: ' + blob);
Logger.log('blob.getDataAsString(): ' + blob.getDataAsString());
file.setContent(newContent);//The new content must be a string
} else {//no file by that name was found
file = dir.createFile(blob).setName('Stores_Month.pdf');
}

Related

Google Sheets to pdf - combine to one pdf instead of splitting into multiple pdfs

I found a script here that does everything I want however for some reason it is splitting the document into several pdf's. I would like to keep everything as it is however just create one single pdf.
Edit: My Google sheets have 5 worksheets and each worksheet at the moment becomes a seperate pdf so I end up with 5 different pdfs. I would like it to just come out as 1 pdf with 5 pages inside.
function savePDFs( optSSId, optSheetId ) {
var ss = (optSSId) ? SpreadsheetApp.openById(optSSId) : SpreadsheetApp.getActiveSpreadsheet();
var url = ss.getUrl().replace(/edit$/,'');
var parents = DriveApp.getFileById(ss.getId()).getParents();
var folders = DriveApp.getFoldersByName('Invoices'); // Modified
var folder = folders.hasNext() ? folders.next() : parents.next(); // Modified
var sheets = ss.getSheets();
for (var i=0; i<sheets.length; i++) {
var sheet = sheets[i];
if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&gid=' + sheet.getSheetId() //the sheet's Id
// following parameters are optional...
+ '&size=letter' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false&pagenumbers=false' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()}}
var response = UrlFetchApp.fetch(url + url_ext, options);
var valor = sheet.getRange('D5').getValue(); // Modified
var blob = response.getBlob().setName(valor + '.pdf');
folder.createFile(blob);
}
}
The reason you are getting 5 PDF files is that, you are iterating between each page of the sheet and creating a PDF from there; instead of calling the entire sheet. I ran a test with the following code, and it exported the Google sheet as a 1 PDF.
Note: I made some changes to the first part of the code since I didn't have access to the other functions been call.
I remove this part:
var sheets = ss.getSheets();
for (var i=0; i<sheets.length; i++) {
var sheet = sheets[i];
if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&gid=' + sheet.getSheetId() //the sheet's Id
+ '&size=letter' // paper size
And modify it like this:
// I didn't have access to the optSSId or optSheetId so for my test I added the URL and the active sheet link to the apps script
// you can keep this part as you had it before
var url = "https://docs.google.com/spreadsheets/d/<spreadsheet_ID>/";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
// From the URL_ext I remove + '&gid=' + sheet.getSheetId() since we want the complete sheet
var url_ext = '/export?exportFormat=pdf&format=pdf' //export as pdf
+ '&size=letter' // paper size
So basically you form this URL:
https://docs.google.com/spreadsheets/d/<SPREADSHEETID>//export?exportFormat=pdf&format=pdf&size=letter&portrait=true&fitw=true&sheetnames=false&printtitle=false&pagenumbers=false&gridlines=false&fzr=false
Update:
function savePDFs( optSSId, optSheetId ) {
//var ss = (optSSId) ? SpreadsheetApp.openById(optSSId) : SpreadsheetApp.getActiveSpreadsheet();
//var url = ss.getUrl().replace(/edit$/,'');
//var parents = DriveApp.getFileById(ss.getId()).getParents();
var url = "https://docs.google.com/spreadsheets/d/<Sheet_ID>/";
var folders = DriveApp.getFolderById("<Folder_ID>"); // Modified
//var folder = folders.hasNext() ? folders.next() : parents.next(); // Modified
// I didn't have access to the optSSId or optSheetId so my test I added the URL and the active sheet link to the apps script
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&size=letter' // paper size
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false&pagenumbers=false' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()}}
var response = UrlFetchApp.fetch(url + url_ext, options);
// var valor = sheet.getRange('D5').getValue(); // Modified
var blob = response.getBlob().setName("test" + '.pdf');
folders.createFile(blob);
}
Replace <Sheet_ID> with the ID of the Google Sheet and <Folder_ID> with the ID of the folder where the PDF file will be store.

How to create new PDF in specific Google Drive folder using Google Script

I am trying to figure out how to have the PDF save in a specific folder instead of the root directory.
I have tried several different things, I have been able to create a new folder but even then it still ends up in the root directory.
function SaveAsPDF() {
var ss = SpreadsheetApp.getActive()
var sheet = SpreadsheetApp.getActiveSheet()
var cell = sheet.getRange('K1')
var cellContent = cell.getValue()
if(cellContent == 'JMB'){
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSpreadsheet = SpreadsheetApp.getActive(); // Get active spreadsheet.
var sheetName = sourceSpreadsheet.getActiveSheet().getName();
var pdfName = ss.getRange("H1").getValue() // Set the output filename as SheetName.
var theBlob = createblobpdf(sheetName, pdfName);
var newFile = Driveapp.createFile(theBlob);
sourceSpreadsheet.toast("Saved ", "Success");
}
function createblobpdf(sheetName, pdfName) {
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var url = 'https://docs.google.com/spreadsheets/d/' + sourceSpreadsheet.getId()
+ '/export'
+ '?format=pdf'
+ '&size=legal' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&scale=4' // 1= Normal 100% / 2= Fit to width / 3= Fit to height / 4= Fit to Page
+ '&fitw=true' // fit to width, false for actual size
+ '&top_margin=1.00' // All four margins must be set!
+ '&bottom_margin=1.00' // All four margins must be set!
+ '&left_margin=1.00' // All four margins must be set!
+ '&right_margin=1.00' // All four margins must be set!
+ '&sheetnames=true&printtitle=false' // hide optional headers and footers
+ '&pagenum=RIGHT&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&horizontal_alignment=CENTER' //LEFT/CENTER/RIGHT
+ '&vertical_alignment=TOP' //TOP/MIDDLE/BOTTOM
+ '&gid=' + sourceSheet.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
// request export url
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var theBlob = response.getBlob().setName(pdfName);
return theBlob;
}
};
Try this:
function SaveAsPDF() {
var ss = SpreadsheetApp.getActive()
var sh = SpreadsheetApp.getActiveSheet();
if (sh.getRange("K1").getValue() == 'JMB') {
var sheetName = sh.getName();
var pdfName = sh.getRange("H1").getValue();
var theBlob = createblobpdf(sheetName, pdfName);
const folder = DriveApp.getFolderById("FolderId");
var newFile = folder.createFile(theBlob);
ss.toast("Saved ", "Success");
}
}

PDF attachment corrupted

After the issue with GmailApp declaratrion has benn resolved, I'm stuck now with a new problem, regarding my pdf attachment which is unreadable.
Prior to this bug, the pdf attachment was working perfectly.
I'm doubting that the var "blobresponse" or "pdfOpts" are the source of the problem, but maybe I'm wrong.
What's going wrong with the script ? Could you please explain me ?
Here is a reproducible example
function emailAsPDF() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Recherche"));
var sheet = ss.getActiveSheet();
var gid = sheet.getSheetId();
var pdfOpts =
'exportFormat=pdf&format=pdf'+ // export as pdf
'&size=0' + // paper size letter / You can use A4 or legal
'&portrait=false' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the actual size
'&sheetnames=false&printtitle=true' + // hide optional headers and footers
'&pagenumbers=true&gridlines=false' + // hide page numbers and gridlines
'&horizontal_alignment=CENTER&vertical_alignment=CENTER' +
'&fzr=true' + // do not repeat row headers (frozen rows) on each page
'&attachment=false' +
gid;
// '&size=0&fzr=true&portrait=false&fitw=true&gridlines=false&printtitle=true&sheetnames=false&pagenumbers=true&attachment=false&gid='+gid;
SourceSS = SpreadsheetApp.getActive();
var SourceSheet = SourceSS.getSheetByName("Recherche");
var url = 'https://docs.google.com/spreadsheets/d/' + SourceSS.getId().replace(/edit$/, '') + '/export?exportformat=pdf&format=pdf' + pdfOpts;
//var url = 'https://docs.google.com/spreadsheets/d/'.replace(/edit$/, '') + '/export?exportformat=pdf&format=pdf' + pdfOpts;
var token = ScriptApp.getOAuthToken();
//var options = {
//options = {muteHttpExceptions: true};
//var options = {
var blobresponse = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token,
},
muteHttpExceptions: true}
);
//options);
var CandidateName = ss.getRangeByName("Nom.Candidat").getValue();
var blob=blobresponse.getBlob().setName(ss.getName() + " - " + CandidateName +".pdf" );
var emailAddress = Session.getActiveUser().getEmail();
var signature = Gmail.Users.Settings.SendAs.get("me", emailAddress).signature;
var mess = "Voulez-vous envoyer votre rapport à l'adresse : " + emailAddress;
var ans= Browser.msgBox("Courriel", mess, Browser.Buttons.YES_NO);
if (ans===Browser.Buttons.NO){return;}
var mess="Votre rapport a été envoyé à l'adresse : " + emailAddress;
//var ss=SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Recherche");
var data = ss.getSheetByName("Données");
const corps = data.getRange("A24:E27").getValues();
const htmlTemplate = HtmlService.createTemplateFromFile("HtmlSigTemplate");
htmlTemplate.corps = corps;
var emailSubject = "Vérifications pré-emploi complétées" +" - "+ CandidateName;
const htmlForEmail = htmlTemplate.evaluate().getContent() + "--" + "<br>" + signature;
//console.log(htmlForEmail);
GmailApp.sendEmail(
emailAddress,
emailSubject,
corps,
{htmlBody: htmlForEmail,
attachments:[blob]});
Browser.msgBox("Courriel", mess, Browser.Buttons.OK);
}
function parentFolder() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var file = DriveApp.getFileById(ss.getId());
var ParentFolder= file.getParents();
while ( ParentFolder.hasNext() ) {
var folder = ParentFolder.next();
folderID=folder.getId();
Logger.log(folderID);
}
return folderID;
}
I found the culprit after a long and painful research. You notice that the last line in the variable pdfOpts was missing a little detail
Old code:
var pdfOpts =
'exportFormat=pdf&format=pdf'+ // export as pdf
'&size=0' + // paper size letter / You can use A4 or legal
'&portrait=false' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the actual size
'&sheetnames=false&printtitle=true' + // hide optional headers and footers
'&pagenumbers=true&gridlines=false' + // hide page numbers and gridlines
'&horizontal_alignment=CENTER&vertical_alignment=CENTER' +
'&fzr=true' + // do not repeat row headers (frozen rows) on each page
'&attachment=false' +
gid;
New code:
const pdfOpts = '&top_margin=0.30&bottom_margin=0.30&left_margin=0.25&right_margin=0.25'
+'&size=LETTER' // paper size letter / You can use A4 or legal
+'&portrait=false' // orientation portal, use false for landscape
+'&fitw=true' // fit to page width false, to get the actual size
+'&sheetnames=false' // hide optional headers
+'&printtitle=true' //and footers
+'&pagenumbers=true' // hide page numbers
+'&gridlines=false' //and gridlines
+'&horizontal_alignment=CENTER'
+'&vertical_alignment=CENTER'
+'&fzr=true' // do not repeat row headers (frozen rows) on each page
+'&attachment=false'
+'&gid='+gid;
The code has several issues. I suggest you to start to cleaning up your script by removing the redundant statements and adopting better modern JavaScript practices. I.E.
Instead of var use const or let. Old Google Apps Script code used var all the time because const and let were not supported. The current Google Apps Script default runtime does it.
Related
What's the difference between using "let" and "var"?
v8 JavaScript performance implications of const, let, and var?
Instead of
ss.setActiveSheet(ss.getSheetByName("Recherche"));
var sheet = ss.getActiveSheet();
use
const sheet = ss.getSheetByName("Recherche");
Instead of
SourceSS = SpreadsheetApp.getActive();
var SourceSheet = SourceSS.getSheetByName("Recherche");
var url = 'https://docs.google.com/spreadsheets/d/' + SourceSS.getId().replace(/edit$/, '') + '/export?exportformat=pdf&format=pdf' + pdfOpts;
use
const url = 'https://docs.google.com/spreadsheets/d/' + ss.getId() + '/export?exportformat=pdf&format=pdf' + pdfOpts;
NOTES:
getId() returns the spreadsheet id, it doesn't includes edit.
It not necessary to declared new variables for the spreadsheet and sheet to be exported as PDF as the ones that were previously declared have the required objects.
Also you might find helpful to review previous questions related to the use of UrlFetchApp to create a PDF like the following:
Generate PDF of only one sheet of my spreadsheet
Exporting Google Sheet as PDF with Custom Headers or Footers in Google Apps Script
Can no longer produce PDF from Google Sheets spreadsheet for some of the users

How to diagnose "429 Error" in Google Script

My script is looping through a list, at each index it is saving a sheet in my workbook as a PDF, then saving it to my google drive folder. There are 7 people in the list. The problem is that my script throws a 429 Error after the 6th PDF is exported. I am trying to figure out how to solve this error but I am quite new to google scripting so I need some help in the right direction.
Error Image
function ToPortrait() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var validation_sheet = ss.getSheetByName('ValidDSM');
var lastRow = validation_sheet.getLastRow();
var inputs = ss.getSheetByName('ValidDSM').getRange('A2:A'+lastRow).getValues();
var sheet2 = ss.getSheetByName('DSM');
var tab = ss.getSheetByName('DSMD');
var url = ss.getUrl().replace(/edit$/,'');
var sheets = ss.getSheets();
var optSheetId = 1123194386;
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
}
}
// Loop through List of 7
for (var i = 0; i < inputs.length; i++){
sheet2.getRange('B3').setValue(inputs[i][0]);
SpreadsheetApp.flush();
Utilities.sleep(500);
// Loop through all sheets, generating PDF files.
//for (var i=0; i<sheets.length; i++) {
//var sheet = sheets[i];
// If provided a optSheetId, only save it.
// if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&gid=' + tab.getSheetId() //the sheet's Id
// following parameters are optional...
+ '&size=letter' // paper size
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false&pagenumbers=false' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
// Get folder containing spreadsheet, for later export
var name = sheet2.getRange('B3').getValue();
var folderID = "1IsffOYYQOHZJKggUzRTntfjmJKN0F6ga"; // Folder id to save in a folder.
var folder = DriveApp.getFolderById(folderID);
var response = UrlFetchApp.fetch(url + url_ext, options)
var blob = response.getBlob().setName(name);
//save the pdf to drive
folder.createFile(blob);
}
}
I expect all 7 PDFs to be exported but only 6 are.

how to remove two second copy of pdf

I use this code for generating a pdf file and save it in a folder of my invoice but it saves two copy one in the folder and one in google drive out of all folders, how to remove send copy of pdf in drive but not in folder.
the code is
function runBothfunctions(){
//function 1
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ss1 = ss.getSheetByName('sheet1')
var ss1Id = ss1.getSheetId()
var ss2 = ss.getSheetByName('sheet2')
var ssId = ss.getId()
var clientName = ss1.getRange(3,3).getValue()
var invoiceNumber = ss1.getRange(4,3).getValue()
var totalBill = ss1.getRange(29,9).getValue()
var d = new Date();
var fullDate = ('0' + d.getDate()).slice(-2) +"/"+ ('0' + (d.getMonth() +1)).slice(-2) +"/"+ (d.getYear().toString()).slice(-2)
var invoiceFileName = invoiceNumber + '_' + fullDate + '_' + clientName +'_'+ totalBill
var url = ss.getUrl()
url = url.replace(/edit$/,'')
var url_ext = 'export?exportFormat=pdf&format=pdf'
+ '&size=A4' // paper size: "legal" / "letter" / "A4"
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&gid=' + ss1Id // the sheet's Id
var token = ScriptApp.getOAuthToken()
// Convert sheet1 to PDF
var response = UrlFetchApp.fetch(url + url_ext, { headers: { 'Authorization': 'Bearer ' + token }})
var blob = response.getBlob().setName(invoiceFileName + '.pdf')
// Add the folder ID of the Drive folder where the PDF should be saved. Create a folder and copy this ID: www.goo.gl/TfgqrN
var invoiceURL = DriveApp.getFolderById('19_cTkcDHlekS- 7Y32BEzUVlhghC0UHMZ').createFile(blob).getUrl()
ss2.getRange(ss2.getLastRow() +1, 1).setFormula('=HYPERLINK("' + invoiceURL + '";"' + invoiceFileName + '")')
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
//create an array of the invoice numbers already created
var colArray = sheet.getRange(4, 3).getValues();
//sort the array values to find max
var maxInColumn = colArray.sort(function(a,b){return b-a})[0][