in Gscript, how to convert sheets to multiple pdfs without timeout - pdf

I'm trying to setup a gradebook, I would like to loop through the list of students in a sheet that has various vlookups to create an individual mark sheet. I would then like to make a pdf for each of the students. I keep hitting a timeout on the server requests after about 6 students. An error message reports "returned code 429."
I thought I had it working but it would just create a pdf for each student with the first student's information and name. I've tried various code snippets found around the internet but those also time out due to the number of requests.
function PrintReport() {
SpreadsheetApp.getActiveSpreadsheet().toast('Writing the reports.','Printing Reports');
var email = Session.getActiveUser().getEmail();
var TodayDate = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ClassName = ss.getName()
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ss.getId());
var StudentList = ss.getSheetByName('Mark Sheet');
var StudentCount = StudentList.getRange("A2").getValue();
var SLData = StudentList.getRange(7,1,StudentCount).getValues();
var ReportSheet = ss.getSheetByName('Student Report');
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true&source=labnol' // fit to page width, false for actual size
+ '&sheetnames=False&printtitle=True' // 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
var token = ScriptApp.getOAuthToken();
var blobs = [];
var sheetID = ss.getSheetByName('Student Report').getSheetId();
var url_base = ss.getUrl().replace(/edit/,'');
for (var i = 0; i < StudentCount; i++){
ReportSheet.setActiveSelection("B1").setValue(SLData[i][0].toString());
SpreadsheetApp.flush();
var response = UrlFetchApp.fetch(url + url_ext + sheetID, {
headers: {'Authorization': 'Bearer ' + token
}
});
//convert the response to a blob and store in our array
blobs[i] = response.getBlob().setName(SLData[i][0] + '.pdf');
}
ReportSheet.setActiveSelection("B1").setValue(SLData[0][0]);
//create new blob that is a zip file containing our blob array
var zipBlob = Utilities.zip(blobs).setName(ClassName+': Student Reports'+'.zip');
var subject = ClassName+ ": Individual Reports";
var body = "How to print multiple files: Just select all the items you wish to print in Finder and tap Command-P (or choose File>Print). If your system can print those items, it will.";
// If allowed to send emails, send the email with the PDF attachment
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments:[zipBlob]
});
SpreadsheetApp.getActiveSpreadsheet().toast('Reports are all done, please check you email.','Reports',5);
}
It is supposed to create a zipped file of pdfs with the student's names. When the zip is downloaded and extracted, the pdfs contain the mark break down for each student.
If I move the "response" code outside the loop, it produces multiple PDFs with just one student's data.
UPDATE
Modified to the code below but now it makes a pdf for each student but everyone has the last student's information (mark and name).
function PrintReport() {
SpreadsheetApp.getActiveSpreadsheet().toast('Writing the reports.','Printing Reports');
var email = Session.getActiveUser().getEmail();
var TodayDate = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ClassName = ss.getName();
var StudentList = ss.getSheetByName('Mark Sheet');
var StudentCount = StudentList.getRange("A2").getValue();
var SLData = StudentList.getRange(7,1,StudentCount).getValues();
var ReportSheet = ss.getSheetByName('Student Report');
var sheetID = ss.getSheetByName('Student Report').getSheetId();
var blobs = [];
hideAllSheetsExcept('Student Report');
for (var i = 0; i < StudentCount; i++){
ReportSheet.setActiveSelection("B1").setValue(SLData[i][0].toString());
SpreadsheetApp.flush();
//convert the response to a blob and store in array
blobs.push(ss.getBlob().getAs('application/pdf').setName(SLData[i][0] + '.pdf'));
//creates a pdf of the last student's information for everyone!
}
ReportSheet.setActiveSelection("B1").setValue(SLData[0][0]);
//create new blob that is a zip file containing our blob array
var zipBlob = Utilities.zip(blobs).setName(ClassName+': Student Reports'+'.zip');
var subject = ClassName+ ": Individual Reports";
var body = "How to print multiple files: Just select all the items you wish to print in Finder and tap Command-P (or choose File>Print). If your system can print those items, it will.";
// If allowed to send emails, send the email with the PDF attachment
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments:[zipBlob]
});
SpreadsheetApp.getActiveSpreadsheet().toast('Reports are all done, please check you email.','Reports',5);
UnHideEverything();
}

I added a try catch in a while loop and a timeout. Works perfectly
So nest your response like this:
var theurl = 'https://docs.google.com/a/mydomain.org/spreadsheets/d/'
+ ssID
+ '/export?exportFormat=pdf&format=pdf'
+ '&size=A4'
+ '&portrait=true'
+ '&fitw=true'
+ '&top_margin=0.50'
+ '&bottom_margin=0.50'
+ '&left_margin=0.50'
+ '&right_margin=0.50'
+ '&sheetnames=false&printtitle=false'
+ '&pagenum=false'
+ '&gridlines=false'
+ '&fzr=FALSE'
+ '&gid='
+ GID;
var response
var done = false
while (!done){
try{
response = UrlFetchApp.fetch(theurl, params)
done = true
} catch (e) {
console.log(e)
done = false
Utilities.sleep(10000)
}
}

Related

Automatically update my Gsheet with an SQL data base

I need to update a file automatically that already has data in it.
The document is filled with an SQL data base thanks to the code below
However, I want it to update itself everyday without deleting any data that are already in the document and only adding new ones (don't want any duplicates).
function readData(db, queryString) {
//connect to the database
var server = 'your-servername-OR-serverPublicIpAddress';
var username = 'your-sql-username';
var password = 'your-password';
var dbUrl = 'jdbc:sqlserver://' + server + ':1433;databaseName=' + db;
var conn = Jdbc.getConnection(dbUrl, username, password );
//query the data
var stmt = conn.createStatement();
var exec_query = stmt.executeQuery(queryString);
var metaData = exec_query.getMetaData();
var numCols = metaData.getColumnCount();
//save query data to an array
var result=[]; //initiate a blank array
//save the column header
header = []; //initiate the header row
for (var col = 0; col < numCols; col++) {
header.push(metaData.getColumnName(col + 1)); //add the name of each column to the header row
};
result.push(header);//after the header row is formed, put it to the result array
//save the data of each row
while (exec_query.next()) {
row_data = [];
for (var col = 0; col < numCols; col++) {
row_data.push(exec_query.getString(col + 1));//add data of each column to the row data
//Logger.log(row_data);
};
result.push(row_data); // add row data to result
//Logger.log(result);
};
exec_query.close();
return result
};
function pushDataToGoogleSheet(data, SheetName) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(SheetName));
var lastRow = sheet.getLastRow();
sheet.getRange(lastRow+1, 1, data.length, data[0].length).setValues(data);
sheet.getDataRange().removeDuplicates();
};
function main() {
db = 'YOUR_DATABASE_NAME'
SQLquery = 'YOUR_SQL_QUERY'
raw_statistics = readData(db, SQLquery); //get raw statistics
pushDataToGoogleSheet(raw_statistics, 'YOUR_SHEET_NAME'); //push to google sheet
};
function main() {
db = 'YOUR_DATABASE_NAME'
SQLquery = 'YOUR_SQL_QUERY'
raw_statistics = readData(db, SQLquery); //get raw statistics
pushDataToGoogleSheet(raw_statistics, 'YOUR_SHEET_NAME'); //push to google sheet
};
However, in the pushDataToGoogleSheet it says that it can't define the length. So, I don't know if I put the right thing for data or not or if there is an issue in my code...
Do you have an idea ?
Thank you for your help !

Using script to export individual sheets inside a google sheet AND set page height

I have a google sheet with 25 sheets/tabs inside it. I need to be able to export each one individually as a pdf and ideally rename them with the name of their individual sheet.
The following code works great except that my doc is just a few lines too long for a single page.
I have tried using the scale function and setting page margins and neither option changes my final exported file.
Is there a way to print to the height of my page or scale the exported pdf?
function exportSheetsAsPDFs() {
SpreadsheetApp.getActiveSpreadsheet().toast('Writing the reports.','Printing Reports');
var email = Session.getActiveUser().getEmail();
var TodayDate = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// Show one sheet at a time, and print each one out as a PDF
for (var i = 0; i < sheets.length; i++) {
sheets[i].showSheet();
// Hide all sheets except for our currently active one.
for (var j = 0; j < sheets.length; j++) {
if (j != i) {
sheets[j].hideSheet();
}
}
// Ensure all hide / show changes are applied
SpreadsheetApp.flush();
// Export PDF
DriveApp.createFile(ss.getBlob().getAs('application/pdf').setName("My File Name - " + sheets[i].getName() + '.pdf'));
}
// Re-show all sheets
for (var i = 0; i < sheets.length; i++) {
sheets[i].showSheet();
}
SpreadsheetApp.getActiveSpreadsheet().toast('Reports all written.','Printing Complete');
}
I recommend you export your sheet data using UrlFetchApp.fetch and passing some url parameters as it enables you to modify your pdf before creating it in the drive.
Just fiddle with the url parameters below and see what you need. There should be ample description on what every parameter does. Depending on your chosen parameters, you can do the following to address your issue:
Change pdf size (change to a longer size, a3, a4, etc)
Adjust margins on your pdf (you can reduce both top and bottom margins if it solves your issue)
Adjust the scale of your data in the pdf (scale to height, width, page or normal, depending on your needs)
Code:
function exportSheetsAsPDFs() {
SpreadsheetApp.getActiveSpreadsheet().toast('Writing the reports.', 'Printing Reports');
var email = Session.getActiveUser().getEmail();
var TodayDate = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// Show one sheet at a time, and print each one out as a PDF
for (var i = 0; i < sheets.length; i++) {
sheets[i].showSheet();
// Hide all sheets except for our currently active one.
for (var j = 0; j < sheets.length; j++) {
if (j != i) {
sheets[j].hideSheet();
}
}
// Ensure all hide / show changes are applied
SpreadsheetApp.flush();
// Exporting PDF (using getBlob function below)
var theBlob = getBlob(sheets[i]);
DriveApp.createFile(theBlob).setName("My File Name - " + sheets[i].getName() + ".pdf");
}
// Re-show all sheets
for (var i = 0; i < sheets.length; i++) {
sheets[i].showSheet();
}
SpreadsheetApp.getActiveSpreadsheet().toast('Reports all written.', 'Printing Complete');
}
function getBlob(sheet) {
var url = 'https://docs.google.com/spreadsheets/d/';
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var id = spreadsheet.getId();
var gid = sheet.getSheetId();
var url_ext = '/export?'
+ 'format=pdf'
+ '&size=a4' //A3/A4/A5/B4/B5/letter/tabloid/legal/statement/executive/folio
+ '&portrait=true' //true= Potrait / false= Landscape
+ '&scale=3' //1= Normal 100% / 2= Fit to width / 3= Fit to height / 4= Fit to 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=true' //true/false
+ '&printnotes=false' //true/false
+ '&pageorder=2' //1= Down, then over / 2= Over, then down
+ '&horizontal_alignment=LEFT' //LEFT/CENTER/RIGHT
+ '&vertical_alignment=TOP' //TOP/MIDDLE/BOTTOM
+ '&printtitle=false' //true/false
+ '&sheetnames=false' //true/false
+ '&fzr=false' //true/false
+ '&fzc=false' //true/false
+ '&attachment=false'
+ '&gid='
+ gid;
var token = ScriptApp.getOAuthToken();
var params = {
headers: {
'Authorization': 'Bearer ' + token
}
};
var blob = UrlFetchApp.fetch(url + id + url_ext, params).getBlob().getAs('application/pdf');
return blob;
}
Fiddling with scale parameter
Scale = 1 (Normal 100%):
Normal scale resulted into overflow
Scale = 3 (Fit to Height):
Note:
Due to the structure of my sample data, Fit to Height (3) and Fit to Page (4) yields the same format.
Notice the difference of width? That's due to fitting it to height.
Fiddle with the parameters to see and find what you need.
References:
https://stackoverflow.com/a/45211625/14606045
https://stackoverflow.com/a/60653901/14606045

Set resolution when exporting artboards to PNG using script

Sorry that this is so similar to a recent post but I can't find the solution anywhere. I have created a simple script that loops through each artboard in an open illustrator document and exports it as a separate PNG file. All is working well except that I want to set the resolution to 150 dpi and not the default 72 dpi, for production reasons. This is an option that you can set when exporting manually to PNG but I don't seem to be able to set it in the PNG options in the code, although the script runs without errors it ignores the resolution setting. Could someone let me know how to do this, many thanks. Code as follows:
var doc = app.activeDocument;;//Gets the active document
var fileName = doc.name.slice(0, 9);//Gets the G Number
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var filePath = (app.activeDocument.fullName.parent.fsName).toString().replace(/\\/g, '/');
var options = new ExportOptionsPNG24();
for (var i = 0; i < numArtboards; i++ ) {
doc.artboards.setActiveArtboardIndex( i );
options.artBoardClipping = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
var artboardName = doc.artboards[i].name;
//$.writeln("artboardName= ", artboardName);
var destFile = new File(filePath + "/" + fileName + " " + artboardName + ".png");
//$.writeln("destFile= ",destFile);
doc.exportFile(destFile,ExportType.PNG24,options);
}
After doing some digging I've found that if you use imageCapture you can set the resolutuion. So new script below. thanks to CarlosCanto for providing this link via the Adobe Forum https://forums.adobe.com/message/9075307#9075307
var doc = app.activeDocument;;//Gets the active document
var fileName = doc.name.slice(0, 9);//Gets the G Number
var numArtboards = doc.artboards.length;//returns the number of artboards in the document
var filePath = (app.activeDocument.fullName.parent.fsName).toString().replace(/\\/g, '/');
var options = new ImageCaptureOptions();
for (var i = 0; i < numArtboards; i++) {
doc.artboards.setActiveArtboardIndex(i);
var activeAB = doc.artboards[doc.artboards.getActiveArtboardIndex()];
options.artBoardClipping = true;
options.resolution = 150;
options.antiAliasing = true;
options.matte = false;
options.horizontalScale = 100;
options.verticalScale = 100;
options.transparency = true;
var artboardName = doc.artboards[i].name;
var destFile = new File(filePath + "/" + fileName + " " + artboardName + ".png");
doc.imageCapture(destFile, activeAB.artboardRect, options);
}

I want to understand how I can run a google app-script to extract information of schools in a certain state

I'm trying to create a database for all of the schools in a certain state. I have written a google app-script that pulls the details of a school and inserts it in a spreadsheet. The problem is that I want to automate the process of changing the name of the school in the url based on the ones I have.
I am also looking to extract the place_id based on a Lat and Long and with type=school but is not working and only pulls 20 schools:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Google Place Search')
.addItem('Buscar Informacion','callgooglemapsapi')
.addToUi();
}
function callgooglemapsapi()
{
var response = UrlFetchApp.fetch("https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=El%20Colegio%20de%20Tamaulipas&inputtype=textquery&fields=formatted_address,type,place_id,geometry,icon,id,name,permanently_closed,photos,place_id,plus_code,user_ratings_total&key=AIzaSyDQlB5xlLhSQZhdIkBGR0WXiWPLVqMwKkM");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data);
Logger.log(data["candidates"]);
Logger.log(data["candidates"][0]);
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(sheet.getLastRow() + 1,1).setValue(data["candidates"][0]["name"]);
sheet.getRange(sheet.getLastRow() + 0,2).setValue(data["candidates"][0]["formatted_address"]);
sheet.getRange(sheet.getLastRow() + 0,3).setValue(data["candidates"][0]["geometry"]["location"]["lng"]);
sheet.getRange(sheet.getLastRow() + 0,4).setValue(data["candidates"][0]["geometry"]["location"]["lat"]);
sheet.getRange(sheet.getLastRow() + 0,5).setValue(data["candidates"][0]["geometry"]["viewport"]["southwest"]["lng"]);
sheet.getRange(sheet.getLastRow() + 0,6).setValue(data["candidates"][0]["geometry"]["viewport"]["southwest"]["lat"]);
sheet.getRange(sheet.getLastRow() + 0,7).setValue(data["candidates"][0]["geometry"]["viewport"]["northeast"]["lng"]);
sheet.getRange(sheet.getLastRow() + 0,8).setValue(data["candidates"][0]["geometry"]["viewport"]["northeast"]["lat"]);
sheet.getRange(sheet.getLastRow() + 0,9).setValue(data["candidates"][0]["place_id"]);
sheet.getRange(sheet.getLastRow() + 0,10).setValue(data["candidates"][0]["photo_reference"]);
sheet.getRange(sheet.getLastRow() + 0,11).setValue(data["candidates"][0]["plus_code"]);
sheet.getRange(sheet.getLastRow() + 0,12).setValue(data["candidates"][0]["types"]);
I expect to extract the detail information and photos and insert them to a spreadsheet, I have 4,000 school names.
I'd expect that it will look something like this:
function getSchoolData() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('SchoolNames');//assume names in column A
var rg=sh.getRange(2,1,sh.getLastRow-1,1);//skip header assume 1 row
var vA=rg.getValues();
var shB=ss.getSheetByName('SchoolData');
var vB=[]
for(var i=0;i<vA.length;i++) {
vB.push(callgooglemapsapi(vA[i][0],sh));
Utilities.sleep(milliseconds);//you may need a delay in here
}
shB.getRange(2,1,vB.length,vB[0].length).setValues(vB);
}
function callgooglemapsapi(schoolname,sheetname) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(sheetname)||ss.getActiveSheet();
var baseUrl="https://maps.googleapis.com/maps/api/place/findplacefromtext/json"
var key="AIzaSyDQlB5xlLhSQZhdIkBGR0WXiWPLVqMwKkM";
var qs="?input=" + encodeURIComponent(schoolname) + "&inputtype=textquery&fields=formatted_address,type,place_id,geometry,icon,id,name,permanently_closed,photos,place_id,plus_code,user_ratings_total&key="
var response = UrlFetchApp.fetch(baseUrl + qs + key);
var data = JSON.parse(response.getContentText());
return [schoolname,data["candidates"][0]["name"],data["candidates"][0]["formatted_address"],data["candidates"][0]["geometry"]["location"]["lng"],data["candidates"][0]["geometry"]["location"]["lat"],data["candidates"][0]["geometry"]["viewport"]["southwest"]["lng"],data["candidates"][0]["geometry"]["viewport"]["southwest"]["lat"],data["candidates"][0]["geometry"]["viewport"]["northeast"]["lng"],data["candidates"][0]["geometry"]["viewport"]["northeast"]["lat"],data["candidates"][0]["place_id"],data["candidates"][0]["photo_reference"],data["candidates"][0]["plus_code"],data["candidates"][0]["types"]];
}

Authentication lost Google app script

I have created a a google app script that create a pdf from a google sheet and send it via email.
I have three script that work perfectly. But with the fourth script (identical to the other)I lost always the authorization after about one - two hours.
Has someone the same problem?
Thanks
Pasquale
Attached code. I use a trigger to lunch code every time the form is submitted.
// When Form Gets submitted
function onFormSubmit(e) {
var docTemplate = "1mI4SQQe4muuW386jgzkxBlZBWuH0OBRdbz1hItOPjK4";
var docName = "DDT";
var ss = SpreadsheetApp.openById("1HzZFDJYAU6H1pptqcA5fEAVelkZw1LP7si9bBrsF_u0")
var sheet = ss.getSheets()[0];
var lastrow = ss.getLastRow();
var d = new Date ();
var id ="0B1-7TPSHWZ1bMlNLTV9tTFJNb2c"; // cartella Raccolta DDT
var folder = DriveApp.getFolderById(id);
//Get information from form and set as variables
//var email = "pasquale.martucci#decathlon.com";
var email = e.values[1];
var mittente = e.values[2];
var destinatario = e.values[3];
var primaQnt = e.values[4];
var primaDescr = e.values[5];
var secondaQnt = e.values[6];
var secondaDescr = e.values[7];
var terzaQnt = e.values[8];
var terzaDescr = e.values[9];
var quartaQnt = e.values[10];
var quartaDescr = e.values[11];
var quintaQnt = e.values[12];
var quintaDescr = e.values[13];
var aspetto = e.values[14];
var colli = e.values[15];
var peso = e.values[16];
var vettore = e.values[17];
// Ricava indirizzi e città
var cell1 = sheet.getRange("S"+lastrow);
cell1.setFormula("=VLOOKUP(C"+lastrow+";Foglio2!A1:C35;2;FALSE)");
var indirMitt = cell1.getValue()
var cell2 = sheet.getRange("T"+lastrow);
cell2.setFormula("=VLOOKUP(C"+lastrow+";Foglio2!A1:C35;3;FALSE)");
var citMitt = cell2.getValue()
var cell3 = sheet.getRange("U"+lastrow);
cell3.setFormula("=VLOOKUP(D"+lastrow+";Foglio2!A1:C35;2;FALSE)");
var indirDest = cell3.getValue()
var cell4 = sheet.getRange("V"+lastrow);
cell4.setFormula("=VLOOKUP(D"+lastrow+";Foglio2!A1:C35;3;FALSE)");
var citDest = cell4.getValue()
//Ricava data
var day = sheet.getRange("W"+lastrow);
day.setFormula("=(DAY(A"+lastrow+"))");
var month = sheet.getRange("X"+lastrow);
month.setFormula("=(MONTH(A"+lastrow+"))");
var year = sheet.getRange("Y"+lastrow);
year.setFormula("=(YEAR(A"+lastrow+"))");
var day1 = sheet.getRange("W"+lastrow).getValue();
var month1 = sheet.getRange("X"+lastrow).getValue();
var year1 = sheet.getRange("Y"+lastrow).getValue();
var data = day1+"/"+month1+"/"+year1;
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DriveApp.getFileById(docTemplate)
.makeCopy(docName+' N° '+lastrow+' ' +mittente , folder)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,in our google doc template
copyBody.replaceText('keyMittente', mittente);
copyBody.replaceText('keyDestinatario', destinatario);
copyBody.replaceText('keyQNT1', primaQnt);
copyBody.replaceText('keyDescrizione1', primaDescr);
copyBody.replaceText('keyQNT2', secondaQnt);
copyBody.replaceText('keyDescrizione2',secondaDescr);
copyBody.replaceText('keyQNT3', terzaQnt);
copyBody.replaceText('keyDescrizione3', terzaDescr);
copyBody.replaceText('keyQNT4', quartaQnt);
copyBody.replaceText('keyDescrizione4', quartaDescr);
copyBody.replaceText('keyQNT5', quintaQnt);
copyBody.replaceText('keyDescrizione5', quintaDescr);
copyBody.replaceText('keyAspetto', aspetto);
copyBody.replaceText('keyKg', peso);
copyBody.replaceText('keyColli', colli);
copyBody.replaceText('keyVettore', vettore);
copyBody.replaceText('keyIndirMitt', indirMitt);
copyBody.replaceText('keyCitMitt', citMitt);
copyBody.replaceText('keyIndirDest', indirDest);
copyBody.replaceText('keyCitDest', citDest);
copyBody.replaceText('keyNum', lastrow);
copyBody.replaceText('keyData', data);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
var subject = "DDT";
var body = "In allegato il DDT generato tramite il portale SimplyCar.";
GmailApp.sendEmail(email, subject, body, {htmlBody: body, attachments: pdf});
// Delete temp file
// DriveApp.getFileById(copyId).setTrashed(true);
}