Converting a specific sheet in a workbook to a PDF - google-apps-script

I am trying to convert a specific sheet in a workbook to PDF. I got help from some kind people here. However, the code worked once and gave me the desired result but then it stopped working and stated giving me a "Exception: Request failed for https://docs.google.com returned code 500." error.
I have a workbook and in that workbook I have a sheet call 'CallPDF' which I want to convert to a PDF. The script that I used is as follows;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const cfrm = ss.getSheetByName('CallPDF');
function saveCRecord() {
var shan = DriveApp.getFolderById("1RzP4dBMU_ZJRvT0WWF1JLvNRztgzSyRT");
if(cfrm.getRange("H8").getValue() == "Shan Jose") {
const url = `https://docs.google.com/spreadsheets/d/${ss.getId()}/export format=pdf&gid=${ss.getSheetByName('CallPDF').getSheetId()}`;
const blob = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } }).getBlob();
shan.createFile(blob.setName(fileName));
};
}
This code worked for me once and then it started giving me the 'Return Code 500' error. As per the code, it will first check if the values in a cell matches the criteria and if it does then convert the CallPDF sheet to a PDF file, rename it and then save it in a specific folder in Google Drive.
Hoping that someone can help me refine this code and get it working for me.
I have been referencing many codes and sites but it is still giving me the error. I am not a coder or a programmer so my knowledge is very limited which is why I am reaching out for help here from the experts.
Some links that I referenced are;
https://spreadsheet.dev/comprehensive-guide-export-google-sheets-to-pdf-excel-csv-apps-script
How to download single sheet as PDF to my local device directly (not export to Google Drive)?

Related

Efficient Way of sending Spreadsheet over email using GAS function?

I am creating an addon for Google Sheets that my local High School's volunteer clubs can use to keep track of their member's volunteer hours. Most of the code is done and works very nicely, and I am currently working on a system that will send a member a spreadsheet listing all of the volunteer events that they have logged. I have GAS create a separate spreadsheet, and then send an email with that separate spreadsheet attached in PDF. When the email is received, the PDF is empty except for a singular empty cell at the top left of the page.
I am pretty new to GAS but have been able to grasp the content pretty easily. I have only tried one method of sending the Spreadsheet and that is by using the .getAs(MimeType.PDF). When I changed the "PDF" to "GOOGLE_SHEETS," GAS returned the error: "Blob object must have non-null data for this operation." I am not entirely sure what a Blob object is, and have not found any website or video that has fully explained it, so I am not sure how to go about troubleshooting that error.
I think I'm having a problem grabbing the file because it either sends an empty PDF or it returns an error claiming it needs "non-null data."
function TigerMail()
{
var Drive = DriveApp;
var app = SpreadsheetApp;
var LOOKUP = app.getActiveSpreadsheet().getSheetByName("Student
Lookup");
var Name = LOOKUP.getRange("E1").getValue();
Name = Name + "'s Hours";
//app.openById(Name+"'s Hours");
var HOURS = app.create(Name);
var ESheet = HOURS.getSheets()[0];
var ROW = LOOKUP.getLastRow();
var arr = LOOKUP.getRange("D1:J"+ROW).getValues();
var cell = ESheet.getRange("A1:G"+ROW);
cell.setValues(arr);
////////////////////////////////////////////////////
var LOOKUP = app.getActiveSpreadsheet().getSheetByName("Student
Lookup");
var cell = LOOKUP.getRange("D1");
var Addr = cell.getValue();
var ROW = LOOKUP.getLastRow();
var file = Drive.getFilesByName(Name);
var file = file.next();
var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS);
TigerMail.sendEmail(Addr, "Hours", "Attached is a list of all of the
events you have volunteered at:", {attachments: [FORMAT]} );
}
the final four lines are where the errors are occurring at. I believe I am misunderstanding how the .next() and .getFilesByName() work.
(above the comment line: creating a spreadsheet of hours)
(below the comment line: grabbing the spreadsheet and attaching it to an email)
Here is the link to the Google Sheet:
https://docs.google.com/spreadsheets/d/1qlUfTWaj-VyBD2M45F63BtHaqF0UOVkwi04XwZFJ4vg/edit?usp=sharing
In your script, new Spreadsheet is created and put values.
You want to sent an email by attaching the file which was converted from the created Spreadsheet to PDF format.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modification points:
About Drive.getFilesByName(Name), unfortunately, there is no method of getFilesByName() in Drive.
I think that when you want to use the created Spreadsheet, HOURS of var HOURS = app.create(Name) can be used.
About var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS), in the case of Google Docs, when the blob is retrieved, the blob is automatically converted to PDF format. This can be also used for your situation.
In order to save the values put to the created Spreadsheet, it uses SpreadsheetApp.flush().
When above points are reflected to your script, it becomes as follows.
Modified script:
Please modify as follows.
From:
var file = Drive.getFilesByName(Name);
var file = file.next();
var FORMAT = file.getAs(MimeType.GOOGLE_SHEETS);
To:
SpreadsheetApp.flush();
var FORMAT = HOURS.getBlob();
Note:
In your script, it seems that var ROW = LOOKUP.getLastRow() is not used.
References:
flush()
getBlob()
If I misunderstood your question and this was not the result you want, I apologize.

Share issue with script

I have this script I am using to make a copy of a sheet and then send me that copy thru email as a xslx file, if I have the sheet set for share to anyone with a link the script works great, but if I have it set to specific people it runs but gives a Value# instead of the data on the page. the page I am trying to send is a query importrange formula pulling the data on to the sheet. any help would be greatly appreciated.
enter code herefunction emailExcel() {
var mailTo, subject, body, id, sheetNum, sh, sourceSS, copySS, file, url,token, response;
mailTo = 'elder1104#gmail.com';
subject = 'subject';
body = 'text_in_body';
id = '1eI-p0nodA4zqP3fsxP5P6iR6gyvSIGRZDMaQSGkb2ds';
sheetNum = 2;
sourceSS = SpreadsheetApp.openById(id);
copySS = sourceSS.copy('copy of ' + sourceSS.getName());
sh = copySS.getSheets()[sheetNum];
sh.getDataRange().setValues(sh.getDataRange().getDisplayValues())
copySS.getSheets()
.forEach(function (sh, i) {
if(i != sheetNum) copySS.deleteSheet(sh);
})
file = Drive.Files.get(copySS.getId());
url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
token = ScriptApp.getOAuthToken();
response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
MailApp.sendEmail(mailTo, subject, body, {
attachments: [response.getBlob()
.setName('TESTING.xlsx')]
});
DriveApp.getFileById(copySS.getId()).setTrashed(true);
}
To share Drive file to specific people, try to add setSharing(accessType, permissionType) method given in Class File.
As mentioned in Working with enums,
the Drive service uses the enums Access and Permission to determine which users have access to a file or folder.
So to access file or folder in DriveApp, you should add the following enumerated types to determine users who can access a file or folder, besides any individual users who have been explicitly given access
Access
Permission
It will really be helpful to try going through the given documentations.
I took the easy way out and made a new spreadsheet and I am importing to that spreadsheet using a script, so now the new document just has data on it and is working perfectly now.

Google app scripts: email a spreadsheet as excel

How do you make an app script which attaches a spreadsheet as an excel file and emails it to a certain email address?
There are some older posts on Stackoverflow on how to do this however they seem to be outdated now and do not seem to work.
Thank you.
It looks like #Christiaan Westerbeek's answer is spot on but its been a year now since his post and I think there needs to be a bit of a modification in the script he has given above.
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
There is something wrong with this line of code, maybe that exportLinks has now depreciated. When I executed his code it gave an error to the following effect:
TypeError: Cannot read property "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" from undefined.
The workaround is as follows:
The URL in the above line of code is basically the "download as xlsx" URL that can be used to directly download the spreadsheet as an xlsx file that you get from File> Download as > Microsoft Excel (.xlsx)
This is the format:
https://docs.google.com/spreadsheets/d/<<<ID>>>/export?format=xlsx&id=<<<ID>>>
where <<>> should be replaced by the ID of your file.
Check here to easily understand how to extract the ID from the URL of your google sheet.
Here's an up-to-date and working version. One prerequisite for this Google Apps script to work is that the Drive API v2 Advanced Google Service must be enabled. Enable it in your Google Apps script via Resources -> Advanced Google Services... -> Drive API v2 -> on. Then, that window will tell you that you must also enabled this service in the Google Developers Console. Follow the link and enable the service there too! When you're done, just use this script.
/**
* Thanks to a few answers that helped me build this script
* Explaining the Advanced Drive Service must be enabled: http://stackoverflow.com/a/27281729/1385429
* Explaining how to convert to a blob: http://ctrlq.org/code/20009-convert-google-documents
* Explaining how to convert to zip and to send the email: http://ctrlq.org/code/19869-email-google-spreadsheets-pdf
* New way to set the url to download from by #tera
*/
function emailAsExcel(config) {
if (!config || !config.to || !config.subject || !config.body) {
throw new Error('Configure "to", "subject" and "body" in an object as the first parameter');
}
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadsheetId = spreadsheet.getId()
var file = Drive.Files.get(spreadsheetId);
var url = 'https://docs.google.com/spreadsheets/d/'+spreadsheetId+'/export?format=xlsx';
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var fileName = (config.fileName || spreadsheet.getName()) + '.xlsx';
var blobs = [response.getBlob().setName(fileName)];
if (config.zip) {
blobs = [Utilities.zip(blobs).setName(fileName + '.zip')];
}
GmailApp.sendEmail(
config.to,
config.subject,
config.body,
{
attachments: blobs
}
);
}
Update: I updated the way to set the url to download from. Doing it through the file.exportLinks collection is not working anymore. Thanks to #tera for pointing that out in his answer.

Google Script gives "Illegal Spreadsheet Key" when trying to open an external spreadsheet

I've scoured the interweb and found many many "solutions" to this problem, none of which seem to work for me.
My problem is a simple one. I want to import information from a changeable source file .... I think I have this licked once I get over the actual problem of opening the external spreadsheet in the first place.
I'm using Google Apps Script and am trying to open a file within the same Google Drive, from a separate GoogleDoc-spreadsheet.
The following code as far as I can see (once you take out the comments) should open a spreadsheet file but gives an illegal key error.
function openafile() {
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
// =//= look for a specific type of spreadsheet file (excel) - this will always be exported as this Mime Type
if ( file.getMimeType() == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) {
Logger.log('Attempting to open ' + file.getName());
// =//= none of these seem to work .... why?
// var ss = SpreadsheetApp.openById(file.getId());
// var ss = SpreadsheetApp.open(file);
// var ss = SpreadsheetApp.openByUrl(file.getUrl());
Logger.log('Success: ' + ss.getName());
}
}
}
Gerardo has kindly answered the actual question posed, which led on to another question ... "OK, but I have no control over the original format of the file. How do I import from Excel/CSV?"
https://stackoverflow.com/a/26858202/4941031
Gives the answer to this follow-up question.

sheet.copyTo always returns "A server error has occurred" in new Google sheets

No matter what I do I cannot get the sheet.copyTo() function to work in the new Google sheets. Always returns "A server error has occurred". I've tried converting the source to the new format. Doesn't work with csv files either. Exact same code with exact same sources works flawlessly from the old Google sheets.
works for me
function ctest() {
var source = SpreadsheetApp.getActiveSpreadsheet();
var sheet = source.getSheets()[1];
Logger.log(sheet.getName())
var destination = SpreadsheetApp.create("testcopy");
sheet.copyTo(destination);
}