Google Sheet Script to download - google-apps-script

excuse my bad English.
I have a main Google Sheet that export that from other sheets to fill the information. This action depends on the number in a cell, then I would download the PDF of the sheet. But the name would automatically be the sheet's name. Is there a script I could use so that the name of the pdf file would be one of the data on a specific cell?
I would gladly appreciate the help. This is so I could get this done more quickly since there are so many people.
I tried to follow some code from another thread: [https://stackoverflow.com/questions/56215898/how-to-download-single-sheet-as-pdf-not-export-to-google-drive]
And ended up with something like this:
function onOpen() {
var submenu = [{name:"Save PDF", functionName:"generatePdf"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu('Export', submenu);
}
function generatePdf() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetId = ss.getActiveSheet().getSheetId();
var valor = SpreadsheetApp.getActiveSheet().getRange('G2').getValue();
var filename = valor;
// Creat PDF file as a temporary file and create URL for downloading.
var url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/" + ss.getId() + "/export?exportFormat=pdf&gid=" + sheetId + "&access_token=" + ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url).getBlob().setName(filename);
var file = DriveApp.createFile(blob);
var dlUrl = "https://drive.google.com/uc?export=download&id=" + file.getId();
// Open a dialog and run Javascript for downloading the file.
var str = '<script>window.location.href="' + dlUrl + '"</script>';
var html = HtmlService.createHtmlOutput(str);
SpreadsheetApp.getUi().showModalDialog(html, "sample");
file.setTrashed(true);
// This is used for closing the dialog.
Utilities.sleep(3000);
var closeHtml = HtmlService.createHtmlOutput("<script>google.script.host.close()</script>");
SpreadsheetApp.getUi().showModalDialog(closeHtml, "sample");
}
Didn't work, just maybe one time after so many tries.
Then I tried this: https://gist.github.com/primaryobjects/6370689c6f5fd3799ea53f89551eced7
But the PDF that exports have the cell's lines in the background... So, it doesn't look good.
Is there a way for the export to use the pdf download method, so it looks clean, but automatically put the name of the pdf from a cell value?

Related

Save to PDF script in Google Sheet

I already had a look to the community but I'm struggling in building a script should do the following:
select a specific range of cells of a Google Sheet sheet
save the selected area as a PDF to be downloaded on the PC (no need to save to GDrive or to add a specif name to the PDF)
I tried recording a Macro but dosn't work.
Can you give some hints on how to move on?
Thanks.
These reference links may help you to have some hints on how you will achieve your target:
This first link shows you how to download a range of cell as PDF:
Script to download a range of cells in google sheet as PDF to local computer and other automation scripts?
Script that exports a range to PDF without borders in reference to the first link and answered by ZektorH:
function downloadRangeToPdf() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:E20");
//Create temporary Spreadsheet
var tempSpreadsheet = SpreadsheetApp.create("tempSheetInvoiceExport", range.getValues().length, range.getValues()[0].length);
var tempSheet = tempSpreadsheet.getSheets()[0];
var tempRange = tempSheet.getRange("A1:E20");
tempRange.setValues(range.getDisplayValues());
tempRange.setTextStyles(range.getTextStyles());
tempRange.setBackgrounds(range.getBackgrounds());
tempRange.setFontColors(range.getFontColors());
tempRange.setFontFamilies(range.getFontFamilies());
tempRange.setFontLines(range.getFontLines());
tempRange.setFontStyles(range.getFontStyles());
tempRange.setFontWeights(range.getFontWeights());
tempRange.setHorizontalAlignments(range.getHorizontalAlignments());
tempRange.setNumberFormats(range.getNumberFormats());
tempRange.setTextDirections(range.getTextDirections());
tempRange.setTextRotations(range.getTextRotations());
tempRange.setVerticalAlignments(range.getVerticalAlignments());
tempRange.setWrapStrategies(range.getWrapStrategies());
SpreadsheetApp.flush(); //Force changes to be written before proceeding.
//Generate Download As PDF Link
var url = 'https://docs.google.com/spreadsheets/d/{ID}/export?'.replace('{ID}', tempSpreadsheet.getId());
var exportOptions = 'exportFormat=pdf&format=pdf' + // export as pdf / csv / xls / xlsx
'&size=letter' + // paper size legal / letter / A4
'&portrait=true' + // orientation, false for landscape
'&fitw=true&source=labnol' + // fit to page width, false for actual size
'&sheetnames=false&printtitle=false' + // hide optional headers and footers
'&pagenumbers=false&gridlines=false' + // hide page numbers and gridlines
'&fzr=false' + // do not repeat row headers (frozen rows) on each page
'&top_margin=0.00' + //All four margins must be set!
'&bottom_margin=0.00' + //All four margins must be set!
'&left_margin=0.00' + //All four margins must be set!
'&right_margin=0.00' + //All four margins must be set!
'&gridlines=false' + //true/false
'&gid=' + tempSheet.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url + exportOptions, {
headers: {
Authorization: 'Bearer '+token
}
}).getBlob().setName(tempSpreadsheet.getName()+".pdf");
var pdfFile = DriveApp.createFile(blob);
var downloadLink = HtmlService
.createHtmlOutput('<p>Download your file here.</p>')
.setWidth(200)
.setHeight(100);
SpreadsheetApp.getUi().showModalDialog(downloadLink, "Download PDF");
DriveApp.getFileById(tempSpreadsheet.getId()).setTrashed(true); //Place temporary sheet on trash
}
Then this second link shows you how to download a spreadsheet as PDF to local computer. You can refer best to Tanaike's answer here:
How to download single sheet as PDF (not export to Google Drive)
EDITED (Answer to your question below):
You need to use the sheetID of the second sheet in order to save the PDF for the second sheet.
You should change
FROM:
var sheetId = SpreadsheetApp.getActiveSheet().getSheetId();
TO:
var sheetId = ss.getSheetId();
Because you get the reference of the second spreadsheet by the following logic:
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
So, you just need to use the following code to get the sheet id of the second spreadsheet:
var sheetId = ss.getSheetId();
For your original logic, which is var sheetId = SpreadsheetApp.getActiveSheet().getSheetId(); it will only get the sheetId of the first sheet.
thanks a lot for your hints. I basically reached what I need even if I need a small adaptation.
My spreadsheet has 2 sheets, I would like to add a script button to sheet 1 to download as PDF sheet 2, I slightly modified the script as reported below but I'm still getting my sheet 1 as PDF.
function downloadSheetAsPDF() {
var filename = "Filename.pdf"; // Please set the filename here.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var sheetId = SpreadsheetApp.getActiveSheet().getSheetId();
// Creat PDF file as a temporary file and create URL for downloading.
var url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/" + SpreadsheetApp.getActiveSpreadsheet().getId() + "/export?exportFormat=pdf&gid=" + sheetId + "&access_token=" + ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url).getBlob().setName(filename);
var file = DriveApp.createFile(blob);
var dlUrl = "https://drive.google.com/uc?export=download&id=" + file.getId();
// Open a dialog and run Javascript for downloading the file.
var str = '<script>window.location.href="' + dlUrl + '"</script>';
var html = HtmlService.createHtmlOutput(str);
SpreadsheetApp.getUi().showModalDialog(html, "Download PDF");
file.setTrashed(true);
// This is used for closing the dialog.
Utilities.sleep(3000);
var closeHtml = HtmlService.createHtmlOutput("<script>google.script.host.close()</script>");
SpreadsheetApp.getUi().showModalDialog(closeHtml, "Download PDF");
}
Any suggestion?
Thanks.

How to get the “shareable link” of a Google Drive file via Google Apps Script and paste the link into a cell in Google Sheets?

I have a script that makes a PDF of my invoice and sends it to a Google drive folder.Now I want to get the "Shareable link" from the file it just made and paste it into a specific Cell in google Sheets. I don't have a coding background and at most I can understand and modify some code. So I'm using code I found online to create the PDF. I tried making my own code for the shareable link but I'm getting nowhere. Can anyone help me. This is the code I'm using for the PDF. If I can provide any more useful information please let me know. Thank you! :)
// Get the currently active spreadsheet URL (link)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var token = ScriptApp.getOAuthToken();
var sheet = ss.getSheetByName("Invoice");
//Creating an exportable URL
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ss.getId());
var folderID = "#### Folder ID ####"; // Folder id to save in a folder.
var folder = DriveApp.getFolderById(folderID);
var invoiceNumber = ss.getRange("'Invoice'!I16").getValue()
var InvoiceDate = ss.getRange("!I17").getValue()
var pdfName = "Invoice #"+ invoiceNumber + " - " + Utilities.formatDate(new Date(), "GMT-7", "MM-dd-yyyy");
/* Specify PDF export parameters
From: https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579
*/
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=true&source=labnol' // fit to page width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='; // the sheet's Id
// Convert individual worksheet to PDF
var response = UrlFetchApp.fetch(url + url_ext + sheet.getSheetId(), {
headers: {
'Authorization': 'Bearer ' + token
}
});
//convert the response to a blob
var blobs = response.getBlob().setName(pdfName + '.pdf');
//saves the file to the specified folder of Google Drive
var newFile = folder.createFile(blobs);
// Define the scope
Logger.log("Storage Space used: " + DriveApp.getStorageUsed());
}```
Intuitively, you can achieve a lot only by yourself, and this is the way to go at the beginning:
You want to retrieve the link of the pdf, so you know for sure that it can happen only when the pdf has been created, which is after this line var newFile = folder.createFile(blobs);
Therefore newFile is the PDF you've created, what's left is just to get the link of this file, you can use either getUrl() or getId():
var newFileLink = newFile.getUrl()
or
var newFileLink = "http://drive.google.com/uc?export=view&id=" + newFile.getId()
Now you have stored the link of the created PDF, and you want to write data into your spreadsheet within a specific cell, maybe you want it in J16, since you're using invoiceNumber = ss.getRange("'Invoice'!I16").getValue() to get a value from I16
Assuming you want to set a value in J16. Intuitively again, since getValue retrieve something, so maybe something link setValue will do the opposite:
var writePDFLink = ss.getRange("'Invoice'!J16").setValue(newFileLink)
Hope this was insightful.

Export a Google sheet range as pdf using Apps script and store the pdf in drive

need some help and hope you can help me :)
I have a google spreadsheet document and need to do some actions per script:
Sheet: "Sheet1"
Range: "A1:J39"
print out with settings (landscape, perfect width)
save as PDF document in a folder in a shared google drive (same settings like no 1)
send PDF file per mail to adresses which listed in an other sheet
hope you can help me with this problem....
thx
I'm giving below code I use to send a full sheet as PDF.
You can modify it slightly to
1.Hide unwanted rows and columns
2.Include PDF export options
function send_sheet(){
var today=new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ltrsht = ss.getSheetByName("Letter");
var sheets=SpreadsheetApp.getActiveSpreadsheet().getSheets();
for(var i =0;i<sheets.length;i++){
if(sheets[i].getName()!="Letter"){ sheets[i].hideSheet() }
}
var pdf = DriveApp.getFileById(ss.getId());
var theBlob = pdf.getBlob().getAs('application/pdf').setName(ltrsht.getRange("C16").getValue()+".pdf");
var folderID = ""; // Folder id to save in a folder
var folder = DriveApp.getFolderById(folderID);
var newFile = folder.createFile(theBlob);
var body = 'Dear ' + ltrsht.getRange("C16").getValue() +',\n\nPL. find your ' + ltrsht.getRange("C11").getValue() +' enclosed.\n\nHRD Megawin Switchgear';
GmailApp.sendEmail(ltrsht.getRange("E17").getValue(), ltrsht.getRange("C11").getValue() + " from Megawin HRD", body, {attachments: [theBlob]});
var empsht = ss.getSheetByName("Emp");
empsht.showSheet();
ltrsht.hideSheet();
}
First you have to hide all sheets other than the target sheet
Hide unwanted rows and columns
Convert to PDF
Save in folder
Send to email id which is stored some cell
See below how to format the PDF
https://support.google.com/docs/thread/3457043?hl=en

Add a button to automatically download a google sheet to excel from a google application script

I have an application made on google than handdle different sheets on a google workbook. I need to add a button to allow users download some of these sheets but in an excel format if is possible. I took one code from StackOv and try to modify it, as i don´t want it name the file and save it in drive, i only need it download as same that when from excel it is download in Book1 ("libro1") without saving anywhere. THK!
var ss = SpreadsheetApp.openById("fffffffffffffffffffffffffffff...myID");
var sheetId = ss.ss.getSheetByName('nameSheetNeedToDownload');
var url = "https://docs.google.com/spreadsheets/d/" + sheetId + "/export?format=xlsx&access_token=" + ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url).getBlob().setName(name + ".xlsx");
createFile(blob); // here need to create but without saving
THK you Tanaike!...Yes here i copy the code i have
function downloadAsXlsx() {
var bogus = DriveApp.getRootFolder();
var spreadSheet = SpreadsheetApp.openById('WorkbookID');
var ssID = spreadSheet.getSheetByName('SheetName');
Logger.log(ssID);
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?format=xlsx";
var params = {method:"GET", headers:{"authorization":"Bearer "+
ScriptApp.getOAuthToken()}};
var response = UrlFetchApp.fetch(url, params);
// save to drive
DriveApp.createFile(response);
}

Export (or print) with a google script new version of google spreadsheets to pdf file, using pdf options

I'm trying to make a google script for exporting (or printing) a new version of google spreadsheet (or sheet) to pdf, with page parameters (portrait/landscape, ...)
I've researched about this and found a possible solution here.
There are several similar solutions like this, but only work with old version of google spreadsheet.
Please, consider this code:
function exportAsPDF() {
//This code runs from a NEW version of spreadsheet
var oauthConfig = UrlFetchApp.addOAuthService("google");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://spreadsheets.google.com/feeds/");
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous"); oauthConfig.setConsumerSecret("anonymous");
var requestData = { "method": "GET", "oAuthServiceName": "google","oAuthUseToken": "always" };
var ssID1="0AhKhywpH-YlQdDhXZFNCRFROZ3NqWkhBWHhYTVhtQnc"; //ID of an Old version of spreadsheet
var ssID2="10xZX9Yz95AUAPu92BkBTtO0fhVk9dz5LxUmJQsJ7yPM"; //ID of a NEW version of spreadsheet
var ss1 = SpreadsheetApp.openById(ssID1); //Old version ss object
var ss2 = SpreadsheetApp.openById(ssID2); //New version ss object
var sID1=ss1.getActiveSheet().getSheetId().toString(); // old version sheet id
var sID2=ss2.getActiveSheet().getSheetId().toString(); // new version sheet id
//For Old version, this runs ok.
var url1 = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="+ssID1+"&gid="+sID1+"&portrait=true"+"&exportFormat=pdf";
var result1 = UrlFetchApp.fetch(url1 , requestData);
var contents1=result1.getBlob();
var pdfFile1=DriveApp.createFile(contents1).setName("FILE1.pdf");
//////////////////////////////////////////////
var url2 = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="+ssID2+"&gid="+sID2+"&portrait=true"+"&exportFormat=pdf";
var result2 = UrlFetchApp.fetch(url2 , requestData);
var contents2=result2.getBlob();
var pdfFile2=DriveApp.createFile(contents2).setName("FILE2.pdf");
}
It works right and generates the file “FILE1.pdf”, that can be opened correctly. But for the new version of spreadsheet, it results in error 302 (truncated server response) at “var result2 = UrlFetchApp.fetch(url2 , requestData);”. Well, it’s ok because the url format for the new version doesn’t include the “key” argument. A correct url for new versions must be like "https://docs.google.com/spreadsheets/d/"+ssID2+"/export?gid="+sID2+"&portrait=true&format=pdf"
Using this for url2 (var url2 = "https://docs.google.com/spreadsheets/d/"+ssID2+"/export?gid="+sID2+"&portrait=true&format=pdf") it fails again with error “Authorization can’t be performed for service: google”.
Well, this error could be due to an incorrect scope for the RequestTokenUrl. I’ve found the alternative scope https://docs.google.com/feeds and set it: oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://docs.google.com/feed/");
After the code runs again, a new error happens at the line with UrlFetchApp.fetch(url2 , requestData);: “Error OAuth” … I don’t know how to continue … I’ve tested hundreds of variations without good results.
Any ideas? is correct the scope docs.google.com/feeds for new version of spreadsheets? is correct the oauthConfig?
Thanks in advance.
Here is my spreadsheet-to-pdf script. It works with the new Google Spreadsheet API.
// Convert spreadsheet to PDF file.
function spreadsheetToPDF(id,index,url,name)
{
SpreadsheetApp.flush();
//define usefull vars
var oauthConfig = UrlFetchApp.addOAuthService("google");
var scope = "https://docs.google.com/feeds/";
//make OAuth connection
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
//get request
var request = {
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always",
"muteHttpExceptions": true
};
//define the params URL to fetch
var params = '?gid='+index+'&fitw=true&exportFormat=pdf&format=pdf&size=A4&portrait=true&sheetnames=false&printtitle=false&gridlines=false';
//fetching file url
var blob = UrlFetchApp.fetch("https://docs.google.com/a/"+url+"/spreadsheets/d/"+id+"/export"+params, request);
blob = blob.getBlob().setName(name);
//return file
return blob;
}
I've had to use the "muteHttpExceptions" parameter to know exactly the new URL. With this parameter, I downloaded my file with the HTML extension to get a "Moved permanently" page with my final url ("https://docs.google.com/a/"+url+"/spreadsheets/d/"+id+"/export"+params").
And note that I am in an organization. So I've had to specify its domain name ("url" parameter, ie "mydomain.com").
(Copied from this answer.)
This function is an adaptation of a script provided by "ianshedd..." here.
It:
Generates PDFs of ALL sheets in a spreadsheet, and stores them in the same folder containing the spreadsheet. (It assumes there's just one folder doing that, although Drive does allow multiple containment.)
Names pdf files with Spreadsheet & Sheet names.
Uses the Drive service (DocsList is deprecated.)
Can use an optional Spreadsheet ID to operate on any sheet. By default, it expects to work on the "active spreadsheet" containing the script.
Needs only "normal" authorization to operate; no need to activate advanced services or fiddle with oAuthConfig.
With a bit of research and effort, you could hook up to an online PDF Merge API, to generate a single PDF file. Barring that, and until Google provides a way to export all sheets in one PDF, you're stuck with separate files.
Script:
/**
* Export one or all sheets in a spreadsheet as PDF files on user's Google Drive,
* in same folder that contained original spreadsheet.
*
* Adapted from https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579#c25
*
* #param {String} optSSId (optional) ID of spreadsheet to export.
* If not provided, script assumes it is
* sheet-bound and opens the active spreadsheet.
* #param {String} optSheetId (optional) ID of single sheet to export.
* If not provided, all sheets will export.
*/
function savePDFs( optSSId, optSheetId ) {
// If a sheet ID was provided, open that sheet, otherwise assume script is
// sheet-bound, and open the active spreadsheet.
var ss = (optSSId) ? SpreadsheetApp.openById(optSSId) : SpreadsheetApp.getActiveSpreadsheet();
// Get URL of spreadsheet, and remove the trailing 'edit'
var url = ss.getUrl().replace(/edit$/,'');
// Get folder containing spreadsheet, for later export
var parents = DriveApp.getFileById(ss.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
}
else {
folder = DriveApp.getRootFolder();
}
// Get array of all sheets in spreadsheet
var sheets = ss.getSheets();
// 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=' + 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 blob = response.getBlob().setName(ss.getName() + ' - ' + 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
folder.createFile(blob);
}
}
Thank you!
Variant 2 works with me with options:
var requestData = {
"oAuthServiceName": "spreadsheets",
"oAuthUseToken": "always"
};
Then:
var ssID = ss.getId();
var sID = ss.getSheetByName(name).getSheetId();
//creating pdf
var pdf = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/" + ssID + "/export?gid=" + sID + "&portrait=false&size=A4&format=pdf", requestData).getBlob();
//folder to created pdf in
var folder = DriveApp.getFolderById(id);
//creating pdf in this folder with given name
folder.createFile(pdf).setName(name);
I can change image size, orientation etc. with listed parameters perfectly.