download pdf from google sheet and - google-apps-script

I found this code where I can download google sheet to pdf but I want to change it in order to chose another sheet then the active one and download the pdf once the code run without the box.
function PDF() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetId = ss.getActiveSheet().getSheetId();
var url = "https://docs.google.com/a/mydomain.org/spreadsheets/d/" + ss.getId() + "/export?exportFormat=pdf&gid=" + sheetId + "&access_token=" + ScriptApp.getOAuthToken();
var str = '<input type="button" value="Download" onClick="location.href=\'' + url + '\'" >';
var html = HtmlService.createHtmlOutput(str);
SpreadsheetApp.getUi().showModalDialog(html, "Download_Report");
}

From What I meant is I want to run this code on a sheet other then the one I am currently using, for example, if you want to use sheetId of other sheet except for the active sheet, how about the following modification?
From:
var sheetId = ss.getActiveSheet().getSheetId();
To:
When you want to use the sheet name, please modify as follows.
var sheetId = ss.getSheetByName("Sheet2").getSheetId(); // Please set the sheet name like "Sheet2".
When you want to use the index of the sheet, please modify as follows. In this case, index = 1 is the 2nd sheet. So, the 1st sheet index is 0.
var index = 1; // Please set the index of the sheet you want to use.
var sheetId = ss.getSheets()[index].getSheetId();
Of cource, you can directly put the specific sheet ID you want to use.
References:
getSheetByName(name)
getSheets()

Related

Server error when trying to save range of Google sheet cells to PDF in Google Apps Script

I have the following code, running in Google Apps Script. The code attempts to take a range of a spreadsheet and save it as a PDF:
var range = sheet.getRange("A586:K" + lastRow);
// Get the currently active spreadsheet URL (link)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pdfBlob = DriveApp.getFileById(ss.getId()).getAs('application/pdf');
pdfBlob.setName('test.pdf');
// Save the PDF to your Google Drive.
var folder = DriveApp.getFolderById("1EJIzvW-oOnFfFOopiAAsudhbHsF5FGKz");
var file = folder.createFile(pdfBlob);
When I run the code, it runs for a while, then gives me the error:
We're sorry, a server error occurred. Please wait a bit and try again
Any tips on what might be going on?
I believe your goal is as follows.
You want to export the specific range of a sheet as a PDF format using Google Apps Script.
In your script, range is not used. And, the whole sheet is exported. In this case, I think that your goal can be achieved by the query parameter. Ref When this is reflected in your script, how about the following modification?
Modified script:
function myFunction() {
const sheetName = "Sheet1"; // Please set your sheet name.
const folderId = "###"; // Please set your folder ID.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName);
const range = sheet.getRange("A586:K" + sheet.getLastRow());
const startRow = range.getRow() - 1;
const endRow = startRow + range.getNumRows();
const startCol = range.getColumn() - 1;
const endCol = startCol + range.getNumColumns();
const url = `https://docs.google.com/spreadsheets/d/${ss.getId()}/export?format=pdf&gid=${sheet.getSheetId()}&r1=${startRow}&c1=${startCol}&r2=${endRow}&c2=${endCol}`;
const res = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } });
const folder = DriveApp.getFolderById(folderId);
folder.createFile(res.getBlob().setName("sample.pdf"));
}
References:
fetch(url, params)
Related thread.
How to adjust as custom size margins and paper size in script to save google spreadsheet in PDF?

Script To Write Auto-Gen'd Google Doc URL To Spreadsheet

I have a Google Form that does two things upon hitting the Submit button. First, it dumps that data into a Spreadsheet, then it autofills a Google Doc Template with the info from the Form.
In my script to autofill the Google Doc, I've grabbed the URL for the Google Doc. But I need to write this URL into the last row of Column J in my Google Sheet. Correction: using the getActiveSheet functions are fine, I forgot this script is running from the (Active) Google Sheet (apologies!).
Can anyone assist with this? Here's a snippet of the script to get the URL:
function autoFillGoogleDocFromForm(e) {
//e.values is an array of form values
var TimeStamp = e.values[0];
var Technician = e.values[1];
var Vendor = e.values[2];
var xxx = e.values[3];
var yyy = e.values[4];
var SerialNumber = e.values[5];
var AssetTag = e.values[6];
var TicketNumber = e.values[7];
var HostName = e.values[8];
var DocumentLink = e.values[9];
var Return = e.values[10];
var Platform = e.values[11];
var Summary = e.values[12];
var URL = "";
//file is the template file, and you get it by ID
var file = DriveApp.getFileById('aaa');
//Put auto filled Google Doc into the appropriate Vendor Folder
//file.makeCopy will return a Google Drive file object
if (Vendor == "111") {
var folder = DriveApp.getFolderById('bbb')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
if (Vendor == "222") {
var folder = DriveApp.getFolderById('ccc')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
if (Vendor == "333") {
var folder = DriveApp.getFolderById('ddd')
var copy = file.makeCopy(TicketNumber + ' - ' + SerialNumber, folder);
}
//Once we've got the new file created, we need to open it as a document by using its ID
var doc = DocumentApp.openById(copy.getId());
//Get the url of the newly created Google Doc
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
//Since everything we need to change is in the body, we need to get that
var body = doc.getBody();
//Then we call all of our replaceText methods
body.replaceText('{{EmailAddress}}', Technician);
body.replaceText('{{TicketNumber}}', TicketNumber);
body.replaceText('{{HostName}}', HostName);
body.replaceText('{{SerialNumber}}', SerialNumber);
body.replaceText('{{AssetTag}}', AssetTag);
body.replaceText('{{Summary}}', Summary);
body.replaceText('{{Vendor}}', Vendor);
body.replaceText('{{URL}}', url);
//Lastly we save and close the document to persist our changes
doc.saveAndClose();
Thanks in advance!
From your following situation in your question,
Also this is a shared Google Sheet, so I can't use the getActiveSheet function, I'd need to reference the Google Sheet URL, I believe.
If you have the permission to write the values to the shared Google Spreadsheet, how about the following modification?
From:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
To:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
sheet.appendRow([url]);
In this modification, please set the Spredsheet ID and sheet name. By this, the value of url is appended to the next row of the last row of the sheet in the Google Spreadsheet.
If you want to use the Spreadsheet URL instead of Spreadsheet ID, please modify openById("### Spreadsheet ID ###") to openByUrl("### Spreadsheet URL ###").
References:
openById(id)
openByUrl(url)
appendRow(rowContents)
Edit:
From the following replying,
That doesn't seem to work to insert the URL into the last row of column J unfortunately. It looks like this script can use the Active Sheet afterall, I'll edit the OP.
In this case, how about the following modification?
From:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
To:
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + (sheet.getLastRow() + 1)).setValue(url);
Or
var url = doc.getUrl();
//Script to write this URL into the Shared Google Sheet will go here
// This is from https://stackoverflow.com/a/44563639/7108653
Object.prototype.get1stEmptyRowFromTop = function (columnNumber, offsetRow = 1) {
const range = this.getRange(offsetRow, columnNumber, 2);
const values = range.getDisplayValues();
if (values[0][0] && values[1][0]) {
return range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
} else if (values[0][0] && !values[1][0]) {
return offsetRow + 1;
}
return offsetRow;
};
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + sheet.get1stEmptyRowFromTop(10)).setValue(url);
Suggestion:
If you need to write the URL value into the last row of Column J in a shared Google Spreadsheet file, you can try this sample below:
function sample() {
var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/SHEET_ID_IS_HERE/edit#gid=0');
var sheet = ss.getSheets()[0]; // access first sheet
var activeSheet = ss.setActiveSheet(sheet);
//Sample setValue() action to the shared sheet file
activeSheet.getRange("A1").setValue("URL");
}
NOTE: You would need to have an editor permission on the Shared Google Sheet file that you're accessing
References:
openByUrl(url)
getSheets()
setActiveSheet(sheet)
Here's the code that ended up working for me.
//Get the url of the newly created Google Doc
var url = doc.getUrl();
// var sheet = SpreadsheetApp.openById("### Spreadsheet ID ###").getSheetByName("### sheet name ###");
var sheet = SpreadsheetApp.getActiveSheet(); // or SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheetname")
sheet.getRange("J" + (sheet.getLastRow())).setValue(url);

Trying to test the google spreadsheet in apps script using multiple sheets force to go to a specific sheet without using the URL

I am using a number of sheets and want to force my script to go to a specific sheet but instead it stays on the active sheet that was just created in my script ?
Note: I do not want to use the URL but the actual name of the spread sheet instead, and think I have to use the setActiveSheet() but have not been able to find any information but that it does not use a string but instead you have to use the object from the parent class ?
The script is showing in the log the word "Master_Approval" and is the wrong sheet the name of the active sheet.
var Sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = Sprsheet.getActiveSheet();
var mySheet = sheet.getSheetName();
if (sheet.getSheetName() == "2020Members") {
Logger.log('THE ACTIVE SHEETS NAME is :' + mySheet);
}
else {
Logger.log('THE WRONG ACTIVE SHEETS NAME is :' + mySheet);
// Force to the correct sheet !
var sheetDataAsArr = sprSheet.getSheetByName("2020Members");
var sheet = sprSheet.getActiveSheet();
var mySheet = sheet.getSheetName();
Logger.log('THE ACTIVE SHEETS NAME is :' + mySheet);
}
It should show the "2020Members" but is not and if the test fails I want to force the active sheet to be "2020Members" and not the sheet we are in currently.
var sheetDataAsArr = sprSheet.getSheetByName("2020Members");
var mainSheet = sheetDataAsArr.getActiveSheet();
Logger.log('THE ACTIVE is :' + mainSheet);
var sheet = sprSheet.setActiveSheet(mainSheet);
var mySheet = sheet.getSheetName();
Logger.log('THE ACTIVE SHEETS NAME is :' + mySheet);
What is wrong above?
I needed something very similar. Here is what I ended up using. Per your function, change accordingly. And you will need to change "Sheet2", to your sheet name "2020Members".
function theSecondSheet() {
var activeSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
if(activeSpreadSheet.getSheetByName("Sheet2").activate()){
SpreadsheetApp.setActiveSheet(activeSpreadSheet.getSheetByName("Sheet2"));
}
}
What is wrong above ?
Answer:
In your last code snippet you have some lines incorrectly written:
Each instance of sprSheet needs to be Sprsheet.
You need to use getSheetName() on mainSheet to log the name of the sheet
The line sprSheet.setActiveSheet(mainSheet) is setting the active sheet to whatever the active sheet already is, you need to use setActiveSheet(sheetDataAsArr)
Full Code:
function myFunction(){
var Sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = Sprsheet.getActiveSheet();
var mySheet = sheet.getSheetName();
if (sheet.getSheetName() == "2020Members") {
Logger.log('THE ACTIVE SHEETS NAME is :' + mySheet);
}
else {
var sheetDataAsArr = Sprsheet.getSheetByName("2020Members");
var mainSheet = Sprsheet.getActiveSheet();
Logger.log('THE ACTIVE is :' + mainSheet.getSheetName());
var sheet = Sprsheet.setActiveSheet(sheetDataAsArr);
var mySheet = sheet.getSheetName();
Logger.log('THE ACTIVE SHEETS NAME is :' + mySheet);
}
}
Something to note: Google Sheets does have some strange behaviour with bound script files and sometimes the script tab will 'lose' it's bound status to the Spreadsheet if both are open and left unattended for long periods of time; this however can be fixed by reloading the Spreadsheet.
Related Questions:
How to make all sheets of a Google spreadsheet show A1 in upper left?

Google sheet create pdf from another sheet ID

Hi how could this code be modified to create a PDF file from another worksheet instead of the active open worksheet.
Here's part of the code I'm using and it works but I would like to create a PDF from another worksheet ID
Thanks
var source = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var ticketnum = source.getSheetByName("Print Page").getRange('X1').getValue();
var body = 'Attached is your copy'
var Client = source.getSheetByName("Print Page").getRange('O5').getValue();
var Cons = source.getSheetByName("Print Page").getRange('T4').getValue() ;
var jobN = source.getSheetByName("Ticket PDF").getRange('G9').getValue() ;
var mailTo = source.getSheetByName("Print Page").getRange('Z1').getValue() ;
var folder = DriveApp.getFoldersByName('Ticket').next();
var token = ScriptApp.getOAuthToken();
var ssID = spreadsheetId;
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export"+
"?format=pdf&"+
'&portrait=true' +
'&fzr=true' +
'&fitw=True' +
//'&scale=4' +
'&top_margin=0.25' +
'&bottom_margin=0.25' +
'&left_margin=0.25' +
'&right_margin=0.25' +
'&horizontal_alignment=CENTER' +
'&gridlines=false'+
'&sheetnames=False';
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var pdf = response.getBlob().setName( Client + " " + ticketnum + " # " + jobN + " " + '.PDF');
folder.createFile(pdf)
How about this modification?
In this modification, it supposes that another worksheet ID in your question is the other sheet in the active Spreadsheet.
Modified script:
In order to export the specific sheet in the Spreadsheet as PDF file, you can use the query parameter of gid as follows.
From:
"?format=pdf&"+
To:
"?format=pdf&gid=" + spreadsheet.getSheetByName("###").getSheetId() + "&" +
In this case, please set the sheet name you want to export as a PDF to ###.
Note:
If you want to export several sheets in the Spreadsheet as a PDF file, this thread might be useful.
If I misunderstood your question and this was not the direction you want, I apologize.
Added
You want to export the specific Spreadsheet, which is not the active Spreadsheet, as a PDF file.
In your script, please give spreadsheetId. When spreadsheetId is not given the active Spreadsheet by var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();. And spreadsheetId is retrieved from the active Spreadsheet. So please modify as follows.
From:
var source = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheet = spreadsheetId ? SpreadsheetApp.openById(spreadsheetId) : SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
To:
var spreadsheetId = "###"; // Please set the Spreadsheet ID.
var source = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
var spreadsheetId = spreadsheet.getId();
If you want to export the specific sheet in the Spreadsheet, please use the query parameter gid. And if you want to export several sheets in the Spreadsheet, this thread might be useful.

Saving as PDF with images and in landscape [duplicate]

This question already has an answer here:
Creating PDF in Landscape (Google Apps Script)
(1 answer)
Closed 3 months ago.
I have a code that, upon a submission from a linked form, will select the row with the most recently submitted information, which auto-fills another sheet in the format I prefer and then saves that as a PDF. I have used this code for several worksheets but now I have need of it on a sheet that contains an image. My PDF is saving without the image, which is essential to the process. In addition to this, I would also like it to save in landscape if someone could help with that, I'd appreciate it.
I've played around with the code a bit, but I had help with writing it and don't understand the language enough to make this work.
function generatePdf() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheeta = ss.getSheetByName('Firstsheet');
sheeta.getRange("A2:A").clear();
var lastrow = sheeta.getLastRow();
var range = sheeta.getRange(lastrow, 1);
var values = range.setValue("autofill"); //This is a checkbox in column A which triggers the vlookup on the second sheet
var originalSpreadsheet = SpreadsheetApp.getActive();
var sourcesheet = originalSpreadsheet.getSheetByName("Secondsheet");
var sourcerange = sourcesheet.getRange('A:I');
var sourcevalues = sourcerange.getValues();
var data = sourcesheet.getDataRange().getValues();
var pdfname = sourcesheet.getRange('E34').getDisplayValue();
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var projectname = SpreadsheetApp.getActiveSpreadsheet();
var sheet = sourcesheet.copyTo(newSpreadsheet);
var destrange = sheet.getRange('A:I');
destrange.setValues(sourcevalues);
newSpreadsheet.getSheetByName('Sheet1').activate();
newSpreadsheet.deleteActiveSheet();
var pdf = DriveApp.getFileById(newSpreadsheet.getId());
var theBlob = pdf.getBlob().getAs('application/pdf').setName("Sheet" + pdfname);
var folderID = "folder ID goes here";
var folder = DriveApp.getFolderById(folderID);
var newFile = folder.createFile(theBlob);
DriveApp.getFileById(newSpreadsheet.getId()).setTrashed(true);
sheeta.getRange("A2:A").clear();
}
I need the image in A1:F29 (merged) to save into the intermediary sheet that this formula creates to then save to the PDF. It would also be nice to save in landscape if at all possible.
1) The problem with the missing image is that you’re making the copy process twice, the first one using copyTo() function which copy the all sheet correctly. And then a second one where you use:
var destrange = sheet.getRange('A:I');
destrange.setValues(sourcevalues);
Which copy all the data, even “over the cell” images but not “in cell” images (probably because this is a new Sheets feature), which probably is the problem you’re facing. So you should delete those 2 lines of code in order to not override the first copy process. That’s what i did and worked fine.
2) As there is no option to specify the landscape feature, you can use the method they used in the link provided by #cooper [1] making a request to the export Url. I implemented the code and worked as intended, you just have to erase these 2 lines:
var pdf = DriveApp.getFileById(newSpreadsheet.getId());
var theBlob = pdf.getBlob().getAs('application/pdf').setName("Sheet" + pdfname);
For this:
var url = newSpreadsheet.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...
'&portrait=false' + //orientation, false for landscape
'&gid=' + newSpreadsheet.getSheetId(); //the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var theBlob = response.getBlob().setName("Sheet" + pdfname);
[1] https://ctrlq.org/code/19869-email-google-spreadsheets-pdf