I'm trying to work out how to create a PDF document through Google Apps Script which is displayed in landscape orientation (A4 size). This is the code I'm using to create the PDF so far, which comes out in portrait orientation.
function pdfSheet() {
var d = new Date();
var cdate = d.getDate();
var cmonth = d.getMonth() + 1;
var cyear = d.getFullYear();
var current = [cdate + "-" + cmonth + "-" + cyear];
var imageBlob = UrlFetchApp.fetch("https://sites.google.com/site/mysite/smalllogo.png").getBlob();
var base64EncodedBytes = Utilities.base64Encode(imageBlob.getBytes());
var logo = "<img src='data:image/png;base64," + base64EncodedBytes + "' width='170'/>";
var html = "<table width='100%'><tr><td align='right'>" + logo + "<br><br><b>Date:</b> " + current + "</td></tr></table>"; //PDF content will carry on here.
var gmailLabels = "PDF";
var driveFolder = "My Gmail";
var folders = DriveApp.getFoldersByName(driveFolder);
var folder = folders.hasNext() ?
folders.next() : DriveApp.createFolder(driveFolder);
var subject = 'Test PDF';
var tempFile = DriveApp.createFile("temp.html", html, "text/html");
var page = folder.createFile(tempFile.getAs("application/pdf")).setName(subject + ".pdf")
tempFile.setTrashed(true);
var link = page.getUrl();
Logger.log(link);
}
I took most of this from another user and edited to have the current days date (in EST) in the email subject and the PDF name. Hope it helps!
// Simple function to send Daily Status Sheets
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function creatPDF() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Date set with format in EST (NYC) used in subject and PDF name
var period = Utilities.formatDate(new Date(), "GMT+5", "yyyy.MM.dd");
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=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
'&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(ss.getName() + " " + period + '.pdf');
//from here you should be able to use and manipulate the blob to send and email or create a file per usual.
var email = 'email#co-email.com';
var subject = "subject line " + period ;
var body = "Please find attached your Daily Report.";
//Place receipient email between the marks
MailApp.sendEmail( email, subject, body, {attachments:[blob]});
}
Related
I'm trying to work out how to create a PDF document through Google Apps Script which is displayed in landscape orientation (A4 size). This is the code I'm using to create the PDF so far, which comes out in portrait orientation.
function pdfSheet() {
var d = new Date();
var cdate = d.getDate();
var cmonth = d.getMonth() + 1;
var cyear = d.getFullYear();
var current = [cdate + "-" + cmonth + "-" + cyear];
var imageBlob = UrlFetchApp.fetch("https://sites.google.com/site/mysite/smalllogo.png").getBlob();
var base64EncodedBytes = Utilities.base64Encode(imageBlob.getBytes());
var logo = "<img src='data:image/png;base64," + base64EncodedBytes + "' width='170'/>";
var html = "<table width='100%'><tr><td align='right'>" + logo + "<br><br><b>Date:</b> " + current + "</td></tr></table>"; //PDF content will carry on here.
var gmailLabels = "PDF";
var driveFolder = "My Gmail";
var folders = DriveApp.getFoldersByName(driveFolder);
var folder = folders.hasNext() ?
folders.next() : DriveApp.createFolder(driveFolder);
var subject = 'Test PDF';
var tempFile = DriveApp.createFile("temp.html", html, "text/html");
var page = folder.createFile(tempFile.getAs("application/pdf")).setName(subject + ".pdf")
tempFile.setTrashed(true);
var link = page.getUrl();
Logger.log(link);
}
I took most of this from another user and edited to have the current days date (in EST) in the email subject and the PDF name. Hope it helps!
// Simple function to send Daily Status Sheets
// Load a menu item called "Project Admin" with a submenu item called "Send Status"
// Running this, sends the currently open sheet, as a PDF attachment
function onOpen() {
var submenu = [{name:"Send Status", functionName:"exportSomeSheets"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Project Admin', submenu);
}
function creatPDF() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Date set with format in EST (NYC) used in subject and PDF name
var period = Utilities.formatDate(new Date(), "GMT+5", "yyyy.MM.dd");
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=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
'&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(ss.getName() + " " + period + '.pdf');
//from here you should be able to use and manipulate the blob to send and email or create a file per usual.
var email = 'email#co-email.com';
var subject = "subject line " + period ;
var body = "Please find attached your Daily Report.";
//Place receipient email between the marks
MailApp.sendEmail( email, subject, body, {attachments:[blob]});
}
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.
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
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][
Just wondering how I would be able to export a PDF file to contain multiple sheets, but not all in the workbook. I've been only been able to send single sheets as separate PDF attachments. Any insight on this would be great.
var url = ss.getUrl(); //gets url
url = url.replace(/edit/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' +
'&size=letter' +
'&portrait=false' +
'&fitw=true' +
'&sheetnames=false&printtitle=false' +
'&pagenumbers=true&gridlines=false' +
'&fzr=true' +
'&gid=GID'
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var blob = response.getBlob().setName(sheet.getName() + '.pdf');
A guide has been written about this in this blog post by Andrew Roberts, the source code from that post is as follows:
function convertSpreadsheetToPdf(email, spreadsheetId, sheetName, pdfName) {
var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();
spreadsheetId = spreadsheetId ? spreadsheetId : spreadsheet.getId()
var sheetId = sheetName ? spreadsheet.getSheetByName(sheetName).getSheetId() : null;
var pdfName = pdfName ? pdfName : spreadsheet.getName();
var parents = DriveApp.getFileById(spreadsheetId).getParents();
var folder = parents.hasNext() ? parents.next() : DriveApp.getRootFolder();
var url_base = spreadsheet.getUrl().replace(/edit$/,'');
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
// Print either the entire Spreadsheet or the specified sheet if optSheetId is provided
+ (sheetId ? ('&gid=' + sheetId) : ('&id=' + spreadsheetId))
// 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_base + url_ext, options);
var blob = response.getBlob().setName(pdfName + '.pdf');
folder.createFile(blob);
if (email) {
var mailOptions = {
attachments:blob
}
MailApp.sendEmail(
email,
"Here is a file named " + pdfName,
"Please let me know if you have any questions or comments.",
mailOptions);
}
} // convertSpreadsheetToPdf()
function test() {
var TEST_EMAIL = 'your email address'
// Create a PDF containing all the tabs in the active spreadsheet, name it
// after the spreadsheet, and email it
convertSpreadsheetToPdf(TEST_EMAIL)
// Create a PDF containing all the tabs in the spreadsheet specified, name it
// after the spreadsheet, and email it
convertSpreadsheetToPdf(TEST_EMAIL, '1r9INcnsyvSQmeduJWVYAvznOOYei9jeAjsy0acA3G1k')
// Create a PDF just containing the tab 'Sheet2' in the active spreadsheet, specify a name, and email it
convertSpreadsheetToPdf(TEST_EMAIL, null, 'Sheet2', 'PDF 3')
}