Related
I am now need to convert the Google Sheet page to PDF, email to user and save the PDF format straightway to Google Drive.
And i need the Google Drive link after save it to Google Drive.
The steps from convert the Google Sheet to PDF, and i've done but I've stuck at getting the URL to be paste on the specific cells.
i know to get the URL using this code Logger.log(fileUrl)
But how to paste on cell the command ?
var changedFlag = false;
var TEMPLATESHEET='Boom-Report';
function emailSpreadsheetAsPDF() {
//Utilities.sleep(300000); //to pause for 60 seconds . Make sure photo completely upload to google sheet
DocumentApp.getActiveDocument();
DriveApp.getFiles();
// This is the link to my spreadsheet with the Form responses and the Invoice Template sheets
// Add the link to your spreadsheet here
// or you can just replace the text in the link between "d/" and "/edit"
// In my case is the text: 17I8-QDce0Nug7amrZeYTB3IYbGCGxvUj-XMt8uUUyvI
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E/edit");
// We are going to get the email address from the cell "B7" from the "Invoice" sheet
// Change the reference of the cell or the name of the sheet if it is different
const value = ss.getSheetByName("Source Email-Boom").getRange("X3").getValue();
const email = value.toString();
// Subject of the email message
const subject = ss.getSheetByName("Source Email-Boom").getRange("B3").getValue();
// Email Text. You can add HTML code here - see ctrlq.org/html-mail
const body = "Boom Lifts Inspection Report - Sent via Auto Generate PDI Report from Glideapps";
// Again, the URL to your spreadsheet but now with "/export" at the end
// Change it to the link of your spreadsheet, but leave the "/export"
const url = 'https://docs.google.com/spreadsheets/d/1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E/export?';
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=A4' + // paper size letter / You can use A4 or legal
'&portrait=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the 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=1832955909'; // the sheet's Id. Change it to your sheet ID.
// You can find the sheet ID in the link bar.
// Select the sheet that you want to print and check the link,
// the gid number of the sheet is on the end of your link.
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
// Generate the PDF file
var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();
// Send the PDF file as an attachement
GmailApp.sendEmail("biha#equip-inc.com", subject, body, {
htmlBody: body,
attachments: [{
fileName: ss.getSheetByName("Source Email-Boom").getRange("B3").getValue().toString() +".pdf",
content: response.getBytes(),
mimeType: "application/pdf"
}]
});
// Save the PDF to Drive. (in the folder) The name of the PDF is going to be the name of the Company (cell B5)
const nameFile = ss.getSheetByName("Source Email-Boom").getRange("B3").getValue().toString() +".pdf"
const folderID = "1ZKWq9jWmeEQlxncuTPHssCFXC3Fidmxn";
DriveApp.getFolderById(folderID).createFile(response).setName(nameFile);
// create file URL
var SpreadsheetID = "1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E";
var ss2 = SpreadsheetApp.openById(SpreadsheetID);
var Sheetname2= "BL-Inspection Report";
var sheet2 = ss2.getSheetByName(Sheetname2);
// Get the last row based on the data range of a single column.
var lastRow2 = sheet2.getLastRow();
var lastColumn2 = sheet2.getLastColumn();
//EXAMPLE: Get the data range based on our selected columns range.
var dataRange2 = sheet2.getRange(1,1, lastRow2, lastColumn2);
var dataValues2 = dataRange2.getValues();
var dataMatch=[];
//***** */
// Loop through array and if condition met, add relevant
// background color.
var p=34 ; //Column No. for Name column AI:AI (Report No)
var filename = encodeURI(nameFile);
var files = DriveApp.getFilesByName(nameFile);
while (files.hasNext()) {
var file = files.next();
if (file) {
var fileUrl = file.getUrl();
};
};
////////////////HELP THIS PART////////////////////////////////
for ( j = 0 ; j < lastRow2 ; j++){
var zz=j;
var yy=dataValues2[j][34];
if(dataValues2[j][34] == subject){
var doclink = Logger.log(fileUrl);
var range = sheet2.getRange(j+1, 128);
range.setValue(doclink);
};
};
}
If cell B3 value in First Source is find in Google Drive, paste the URL in Column DX where the AI is same with First Source.
I believe your goal is as follows.
You want to search the file of filename subject retrieved from the cell "B3" of "Source Email-Boom" sheet from your Google Drive, and when the value of subject is found from the column "AI" of "BL-Inspection Report" sheet, you want to put the URL of the file to the column "AJ".
For my question of For example, you want to put the URL of the just created file?, from Yes of your replying, I understood that you wanted to put the URL of the just created file in this script.
In this case, how about the following modification? I thought that in this case, the file URL of the just created file can be directly retrieved from DriveApp.getFolderById(folderID).createFile(response).setName(nameFile). So, how about the following modification?
From:
DriveApp.getFolderById(folderID).createFile(response).setName(nameFile);
To:
var fileUrl = DriveApp.getFolderById(folderID).createFile(response).setName(nameFile).getUrl();
And also, please modify as follows.
From:
var filename = encodeURI(nameFile);
var files = DriveApp.getFilesByName(nameFile);
while (files.hasNext()) {
var file = files.next();
if (file) {
var fileUrl = file.getUrl();
};
};
////////////////HELP THIS PART////////////////////////////////
for (j = 0; j < lastRow2; j++) {
if (dataValues2[j][34] == subject) {
var doclink = Logger.log(fileUrl);
var range = sheet2.getRange(j + 1, 128);
range.setValue(doclink);
};
};
To:
var range = sheet2.getRange("AI2:AI" + sheet2.getLastRow()).createTextFinder(subject).findNext();
if (range) {
range.offset(0, 1).setValue(fileUrl);
}
In this modification, the cell is searched using TextFinder.
Reference:
createTextFinder(findText)
I'm currently using a script that uses text from cells in google sheets to populate specific fields in a google doc which is then saved as a pdf.
I want to replace one of the fields in the google doc with an image from a cell in sheets (an auto-generated QR code), but when I use the function body.replaceText the replaced field in the output PDF contains the string 'cellimage' rather than the image.
Below is the script used:
function createBulkPDFs(){
const docFile = DriveApp.getFileById("1y6hduq3CzpM5Nr8WuhlvQNZmcKViHXNWG1zvR9KgCTk");
const tempFolder = DriveApp.getFolderById("1SLj2sldcNixIe_q8RIm_LIAON1L9rImH");
const pdfFolder = DriveApp.getFolderById("1TrhUjonuXodeZWMQMJV7ZjtN4jp8WSRH");
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Customs");
const data = currentSheet.getRange(2,1,currentSheet.getLastRow()-1,20).getValues();
let errors = [];
data.forEach(row => {
try{
createPDF(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8],row[9],row[10],row[11],row[12],row[13],row[14],row[15],row[16],row[17],row[18],row[19],row [0],docFile,tempFolder,pdfFolder); //row numbers are to name columns //then this //row 0 is the NAMEof the PDF
errors.push([""]);
} catch(err) {
errors.push(["Failed"]);
}
}); //close forEach
currentSheet.getRange(2,21,currentSheet.getLastRow()-1,1).setValues(errors);
}
function createPDF(number,model,fors,length,width,thickness,litres,notes,blank,orders,dates,finSetup,lamination,artwork,finSystem,leash,finish,phoneNumber,shipping,qrcode,pdfName,docFile,tempFolder,pdfFolder) {
const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody();
body.replaceText("{number}",number); //name in doc on left, named column in here on right //need to do this next!!!!
body.replaceText("{model}",model);
body.replaceText("{for}",fors);
body.replaceText("{length}",length);
body.replaceText("{width}",width);
body.replaceText("{thickness}",thickness);
body.replaceText("{litres}",litres);
body.replaceText("{notes}",notes);
body.replaceText("{blank}",blank);
body.replaceText("{orderTakenBy}",orders);
body.replaceText("{dateTaken}",dates);
body.replaceText("{finSetup}",finSetup);
body.replaceText("{lamination}",lamination);
body.replaceText("{artwork}",artwork);
body.replaceText("{finSystem}",finSystem);
body.replaceText("{leash}",leash);
body.replaceText("{finish}",finish);
body.replaceText("{phoneNumber}",phoneNumber);
body.replaceText("{shippingCo}",shipping);
body.replaceText("{qrcode}",qrcode);
tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs(MimeType.PDF);
pdfFolder.createFile(pdfContentBlob).setName(pdfName);
tempFolder.removeFile(tempFile)
Ideally the qrcode text would be replaced with an image (that is big enough to scan - maybe 150 x 150)
Can someone please help me with next steps. I am a n00b to google scripts.
I made an Excel Sheet in Google Drive to be used by 15 Peoples. The function is that the macro should create a PDF from the Sheet and send it to peoples as Mail. But I want to make a copy as PDF in Google Drive where can I see all of this persons permissions to see all of the sent Mails.
I must say that I am a beginner for this macro thing, I tried 2 codes but I always get the same Error.
function TEST2()
{
var Datum = Utilities.formatDate(new Date(), "GMT+2", "dd.MM.YYYY HH:mm");
var as = SpreadsheetApp.getActive();
var newas = SpreadsheetApp.create("XX");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("XX");
sheet = as.getSheetByName("XX");
sheet.copyTo(newas);
newas.getSheetByName('XX');
newas.deleteActiveSheet();
var pdf = DriveApp.getFileById(newas.getId()).getAs('application/pdf').getBytes();
var anhang = {fileName:("XX Order" + Datum + ".pdf"),content:pdf,mimeType:'application/pdf'};
var folderID = "TEST FOLDER";
var folder = DriveApp.getFolderById(folderID);
var newFile = DriveApp.createFile(folder);
newFile;
MailApp.sendEmail(
{
to: "Mail Adress",
subject: "XX Order " + Datum,
htmlBody: "XX - Order ",
attachments: anhang
})
SpreadsheetApp.getUi().alert('Mail wurde versendet ' + Datum)
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
I always get the same Error message. That the script cannot find a document with this ID.
Ok i found the solution :)
var folderID = "XXX BESTELLUNG";
var folderID2 = "XXX Bestellung";
var folder = DriveApp.getFoldersByName(folderID);
var theblob = newas.getBlob().getAs('application/pdf').setName('XXX Bestellung ' + Datum);
var newFile = folder.next().getFoldersByName(folderID2).next().createFile(theblob);
when i change the code in this case, i get the solution whicht i want :)
I am generating a PDF file from a spreadsheet using an app script I found here.
This one uses the good old
Method getAs('application/pdf') and works great.
The problem is that the PDF document generated in this way has unwanted asymmetric margins (larger on the right, narrow on the left). I just wanted the page to be centered. The weird thing is that when I print from the Google menu File -> Print (or Ctrl + P) the document appears centered correctly.
My code looks like this:
function CreaPDF() {
//The function prints an invoice to PDF. First it copies spreadsheet to a new document.
//Deletes all sheet except the one to print. Saves it to PDF.
//It overwrites any existing doc with same name.
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sheetName = "Factura";
var folderID = getParentFolder(); // Folder id to save in a folder.
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
var numf = sourceSpreadsheet.getRangeByName("NumeroFactura").getValue();
var anof = numf.split("/",2); // Seeks number and year -> filename
var pdfName = anof[1] +"_Factura_" + anof[0]+ "_Dra_Salazar"; // Nombre del documento;
//Copy whole spreadsheet 2 temporary sheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
//Deletes pdf if already exists
var files = DriveApp.getFilesByName(pdfName);
while (files.hasNext()) {
files.next().setTrashed(true);
}
var destSheet = destSpreadsheet.getSheets()[0];
//repace cell values with text (to avoid broken references)
var sourceRange = sourceSheet.getRange(1, 1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getDisplayValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
SpreadsheetApp.getActiveSpreadsheet().toast('Creando PDF');
//save to pdf
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
return true;
}
My settings when I print are:
Paper size: "A4"
Scale: "Normal" (I also tried: "fit to width" and
"fit on page")
Orientation: "Portrait"
Margins: "Normal"
As seen in the Google Help Forums it seems like an old issue with the way google prints. In summary, it seems that print settings are not saved and there is no way to pass any parameter to the getAs('application/pdf') method either. So i assume that the method (and menu print options) use default parameters that can not be modified. Any solution for this? The "Print or change page setup" help page does not help too much.
Thank you very much
Try this solution based on https://ctrlq.org/code/19869-email-google-spreadsheets-pdf
Using export url parameters you can set needed options for result pdf. Also you can set specific id of sheet to export, so you don't need to make duplicate of your whole spreadsheet anymore.
function CreaPDF() {
//The function prints an invoice to PDF. First it copies spreadsheet to a new document.
//Deletes all sheet except the one to print. Saves it to PDF.
//It overwrites any existing doc with same name.
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sheetName = "Factura";
var folderID = getParentFolder(); // Folder id to save in a folder.
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
var numf = sourceSpreadsheet.getRangeByName("NumeroFactura").getValue();
var anof = numf.split("/",2); // Seeks number and year -> filename
var pdfName = anof[1] +"_Factura_" + anof[0]+ "_Dra_Salazar"; // Nombre del documento;
SpreadsheetApp.getActiveSpreadsheet().toast('Creando PDF');
// export url
var url = 'https://docs.google.com/spreadsheets/d/'+sourceSpreadsheet.getId()+'/export?exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=A4' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=false' // 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='+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+'.pdf');
// delete pdf if already exists
var files = folder.getFilesByName(pdfName);
while (files.hasNext())
{
files.next().setTrashed(true);
}
// create pdf
var newFile = folder.createFile(theBlob);
return true;
}
Motivated by Kos' soultion.
I tracked request that created by google spreadsheet Download as GUI with chrome developer Tools. When you click next in Print settings, chrome sents post request and gets pdf file.
Let's cut to the chase. Below is my code.
var sourceSpreadsheet = SpreadsheetApp.getActive();
var url = 'https://docs.google.com/spreadsheets/d/' + sourceSpreadsheet.getId() + '/pdf?id=' + sourceSpreadsheet.getId()
var formData = {
'a': 'false',
'pc': '[null,null,null, ... SOME VERY LONG LIST OF NULLS AND NUMBERS ... 166]],[[0,5]]]],0]',
'gf': '[]'
};
var token = ScriptApp.getOAuthToken(); // doesn't needed when sheet is public
var options = {
'method': 'post',
'payload': formData,
'muteHttpExceptions': true,
headers: {
'Authorization': 'Bearer ' + token
}
};
var response = UrlFetchApp.fetch(url, options)
var theBlob = response.getBlob().setName('YourPDFName.pdf');
You can fill formData['pc'] by following:
1. Record requests at Network tab.
2. Click pdf?id=blahblah
pic for step 2
3. Scroll down to find Form Data
pic for step 3
4. Copy form data and fill your code.
Form data looks like:
[null,null,null,null,null,null,null,null,null,0,[["$Sheet_id"]],10000000,null,null,null,null,null,null,null,null,null,null,null,null,null,null,$day_after_30-12-1899,null,null,[$note,null,1,$note,0,0,0,0,$fixed_row,1,1,1,$headers,$footers,1,1],["A4",1,2,1,[0.75,0.75,0.7,0.7]],null,0,[["$Sheet_id",[[26,52]....],[[0,5]]]],0]
There are many more parameters but I can't find them all. Also parameters can be wrong as I found their value by checking changed value.
When you change $day_after_30-12-1899, date printed in pdf changes.
You can customize headers/footers. They are UTF16 encoded and has several control characters.
| Name in `Download as` GUI | character |
|---------------------------|-----------|
| page number A | \uee12 |
| page number B | \uee15 |
| page number C | \uee16 |
| Workbook title | \uee10 |
| sheet name | \uee11 |
| meaning in date & time | character |
|---------------------------|-----------|
| date formatstr start | \uee13 |
| year | yyyy |
| month | M |
| day | d |
| date formatstr end | \uee14 |
| | |
| time formatstr start | \uee17 |
| am or pm | am/pm |
| hour in 12hour clock | h |
| minute | mm |
you can use time and date like this YourText\uee13yy. M. d\uee14Yourtext
I'd recommend create formData['pc'] with GUI and modify $day_after_30-12-1899.
*Any corrections are welcome. While I'm not a native English speaker, there are many awkward/incorrect expressions.
I set up a script to convert an office contact list in Google Sheets to PDF and email it to a list every month as an attachment. I'm trying to figure out how to format the PDF to be in landscape and remove gridlines and haven't had success. I'm relatively new to scripting so I'm sure I'm missing something. Here is my code. I'd appreciate any advice. Thanks!
function EmailSpreadsheetAsPDF() {
var file = DriveApp.getFileById('xxxxx_spreadsheet_key_xxxxx');
var formattedDate = Utilities.formatDate(new Date(), "GMT-7", "MMMM yyyy");
Logger.log(formattedDate);
var email = "xxxxx#xxxxx.xxx";
var subject = "Contact List - " + formattedDate;
var body = "Attached is the current contact list for " + formattedDate + "." + "\n\nPlease email xxxxx#xxxxx.xxx with any corrections or updates.";
MailApp.sendEmail(email, subject, body, {
name: 'xxxxx',
attachments: [file.getAs(MimeType.PDF)]
});
}
Yes, it is possible. You will however have to user UrlFetchApp for this purpose. As shown here(read post#89), you can export the file as a PDF while setting gridline visibility to false by using the following command:
var pdfBlob = UrlFetchApp.fetch("https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key="
+docKey
+"&exportFormat=pdf&gid="
+printSheetIndex
+"&gridlines=false&printtitle=false&size=A4&sheetnames=false&fzr=true&portrait="
+portraitInd
+"&fitw=true"
, requestData).getBlob().setName(docName);
Read the provided link for more detailed information.