Why Google sheets missing the last email when sending emails? - google-apps-script

my google sheet will email a PDF copy of the sheet to a list of 4 emails ( in cells L5:L8 )
but it seems that the email in cell L8 never picked , logger shows it in the array ! .
see my code and help figuring the problem !? I'm suspecting something wrong in my FOREACH loop .
function onEdit2(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var r = sheet.getRange('L11').getValue();
if (r == "Send") {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ssID = ss.getId();
var sheet = ss.getActiveSheet();
var sheetName = ss.getName();
var key = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName();
var token = ScriptApp.getOAuthToken();
var setcolor= SpreadsheetApp.getActiveSheet().setTabColor("#0000A0");
var emails= sheet.getRange("L5:L8").getValues();
var subject = "Daily report ";
var body = "Please find the attached" +" "+ key ;
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?"
+ "format=xlsx" + "&gid="+sheetgId+ "&portrait=true" +
"&exportFormat=pdf";
var tempSheet = ss.insertSheet("tempSheet"); // Added
sheet.getRange("A1:J27").copyTo(tempSheet.getRange(1, 1)); // Added
SpreadsheetApp.flush(); // Added
var sheetgId = tempSheet.getSheetId(); // Added
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?" + "format=xlsx" + "&gid="+sheetgId+ "&portrait=true" + "&exportFormat=pdf";
var result = UrlFetchApp.fetch(url, {headers: {'Authorization': 'Bearer ' + token}});
var contents = result.getContent();
emails.forEach(function(email){
MailApp.sendEmail(email.toString(),sheetName ,body, {attachments: [{fileName: sheetName + ".pdf", content: contents, mimeType: "application//pdf"}]});
ss.deleteSheet(tempSheet); // Added
})
}
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
for ( var i = 0 ; i<sheets.length ; i++) {
var sheet1 = sheets[i];
sheet1.getRangeList(['L3','L11']).clearContent();
}
}

Related

correcting an Error on multiple myfunction in onEdit - Help please

I am getting an error ReferenceError: options is not defined at myfunctionFDI(OverallScript.gs:39:48)at onEdit(OverallScript.gs:3:1), when I am trying to run multiple myfunctions within onEdit, what am I doing wrong, it appears to run the first myfunction correctly. Help would be appreciated script is here
function onEdit(e) {
myfunctionMCR(e);
myfunctionFDI(e);
}
function myfunctionMCR(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var recipients = "joebloggs#blogs.com";
var message = '';
if(cellvalue === 'MCR Approved'){
message = 'Cell ' + cell + ' in Sheet MAN ' + sheetName + ' was changed to MCR Approved and is ready for your Review & Approval.';
var subject = 'Cell Changed to MCR Approved';
var body = message + ' Visit ' + ss.getUrl() + ' to view the change and approve';
var options = {
cc: "fredblogs#blogs.com,bobblogs#blogs.com"
}
MailApp.sendEmail(recipients, subject, body, options);
}
}
function myfunctionFDI(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var recipients = "fredblogs#blogs.com";
var message = '';
if(cellvalue === 'FDI'){
message = 'Cell ' + cell + ' in Sheet MAN ' + sheetName + ' was changed to FDI and is ready for your review.';
var subject = 'Cell Changed to FDI Review';
var body = message + ' Visit ' + ss.getUrl() + ' FDI to Review';
MailApp.sendEmail(recipients, subject, body, options);
};
}

Script to email inactive sheets of a sheet workbook

I have a script to send the active sheet of a workbook sheet in excel to a mailing list
function SendaMailOK(){
var DateName1 = SpreadsheetApp.getActiveSheet( ).getRange("B4").getValue();
var newdate = new Date(SpreadsheetApp.getActiveSheet( ).getRange("B4").getValue());
var d = Utilities.formatDate(newdate, Session.getScriptTimeZone(), "dd-MM-yyyy");
var f = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Adresses Mail');
//Send active sheet as email attachment
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ssID = ss.getId();
var sheetgId = ss.getActiveSheet().getSheetId();
var sheetName = ss.getSheetName();
var token = ScriptApp.getOAuthToken();
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?" + "format=xlsx" + "&gid="+sheetgId+ "&portrait=false" + "&exportFormat=xlsx";
var result = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var contents = result.getContent();
var subject = "Rapport du " + d;
var body = "Bonjour, \n\nCi-joint le rapport, \n \nCdlt";
var n=f.getLastRow();
for (var i = 1; i < n+1 ; i++ ) {
var emailAddress = f.getRange(i,1).getValue();
MailApp.sendEmail(emailAddress,subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"application//xlsx"}]});
}
};
After modifying my file, I need to send 2 sheets of the workbook as attachments and no longer the active sheet.
Problem, I can't adapt the script.
Thanks for your help.
Sending multiple files
I played around with your code a little and found a way to do it taking from some of the work that Tanaike has done in this area. If you don't know where to look for stuff like this then always check out Tanaikes work because I've always found it to be well done.
function SendaMailOK() {
const ss = SpreadsheetApp.getActive();
let esh = ss.getSheetByName('Sheet3');
let ssID = ss.getId();
let token = ScriptApp.getOAuthToken();
let emails = esh.getRange(1, 1, esh.getLastRow()).getValues().flat().join(',');
const names = ['Sheet0', 'Sheet1'];
const shts = ss.getSheets().filter(sh => ~names.indexOf(sh.getName()));
let files = [];
shts.forEach((sh, i) => {
let d = Utilities.formatDate(new Date(sh.getRange("B4").getValue()), Session.getScriptTimeZone(), "dd-MM-yyyy");
let sheetgId = sh.getSheetId();
let url = "https://docs.google.com/spreadsheets/d/" + ssID + "/export?" + "format=xlsx" + "&gid=" + sheetgId + "&portrait=false" + "&exportFormat=xlsx";
let contents = UrlFetchApp.fetch(url, { headers: { 'Authorization': 'Bearer ' + token } }).getBlob().setName(`${sh.getName()}.xlsx`);
files.push(contents);
});
var subject = `Files: ${names.join(', ')}`;
var body = "Hello, here are your files";
MailApp.sendEmail(emails, subject, body, { attachments: files });
}

Trigger based email send on google sheets giving some random results i dont understand

I have been trying to make a script that will send email of a range of cells over email. While the sending email part works perfectly, when i add time based trigger to it, its sending out a random email i dont understand.
I am trying to send out a range of cells in my sheet that gets updated live to my boss automatically at 9:30Am everyday.
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var recipient = 'aaaabalamurali1996#gmail.com'
var subject = 'NRV Tracker'
var date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy")
var schedRange = sheet.getRange("A1:Y6");
//var schedRange = sheet.getRange(Col == 3 && compare == date);
var body = '<div style="text-align:center;display: inline-block;font-family: arial,sans,sans-serif">'
body += '<H1>'+ 'NRV Tracker ' +'</H1>';
body += '<H2>'
body += getHtmlTable(schedRange);//change this line
body += '</div>';
debugger;
recipient = 'abc#abc.com'; // For debugging, send only to self
GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
var ts = ss.getSheetByName("D-1 Day");
var srange = sheet.getRange("A1:Y6");
var trange = ts.getRange("A1:Y6");
srange.copyTo(trange, {contentsOnly: true});
}
function getHtmlTable(range){
var ss = range.getSheet().getParent();
var sheet = range.getSheet();
startRow = range.getRow();
startCol = range.getColumn();
lastRow = range.getLastRow();
lastCol = range.getLastColumn();
// Read table contents
var data = range.getValues();
// Get css style attributes from range
var fontColors = range.getFontColors();
var backgrounds = range.getBackgrounds();
var fontFamilies = range.getFontFamilies();
var fontSizes = range.getFontSizes();
var fontLines = range.getFontLines();
var fontWeights = range.getFontWeights();
var horizontalAlignments = range.getHorizontalAlignments();
var verticalAlignments = range.getVerticalAlignments();
var colWidths = [];
for (var col=startCol; col<=lastCol; col++) {
colWidths.push(sheet.getColumnWidth(col));
}
var rowHeights = [];
for (var row=startRow; row<=lastRow; row++) {
rowHeights.push(sheet.getRowHeight(row));
}
var tableFormat = 'style="font-size: 10px; border:1px solid black;border-collapse:collapse;text-align:center" border = 1 cellpadding = 1';
var html = ['<table '+tableFormat+'>'];
// Column widths appear outside of table rows
for (col=0;col<colWidths.length;col++) {
html.push('<col width="'+colWidths[col]+'">')
}
for (row=0;row<data.length;row++) {
html.push('<tr height="'+rowHeights[row]+'">');
for (col=0;col<data[row].length;col++) {
// Get formatted data
var cellText = data[row][col];
if (cellText instanceof Date) {
cellText = Utilities.formatDate(
cellText,
ss.getSpreadsheetTimeZone(),
'M/d');
}
var style = 'style="'
+ 'color: ' + fontColors[row][col]+'; '
+ 'font-family: ' + fontFamilies[row][col]+'; '
+ 'font-size: ' + fontSizes[row][col]+'; '
+ 'font-weight: ' + fontWeights[row][col]+'; '
+ 'background-color: ' + backgrounds[row][col]+'; '
+ 'text-align: ' + horizontalAlignments[row][col]+'; '
+ 'vertical-align: ' + verticalAlignments[row][col]+'; '
+'"';
html.push('<td ' + style + '>'
+cellText
+'</td>');
}
html.push('</tr>');
}
html.push('</table>');
return html.join('');
}
When i use the trigger i am getting this email.
enter image description here
Try referencing the range of cells that you wish to send to a new sheet and use the code below to send that sheet as a PDF. It is very easy to implement.
// Generate a PDF file from a Google spreadsheet and send it to a specified email address
function emailSpreadsheetAsPDF() {
const sheetToPrint = "SPREADSHEET NAME"; // name of the sheet to print
const ss = SpreadsheetApp.getActiveSpreadsheet(); // the sheets to use
const email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SHEET NAME').getRange('E3').getValue().toString(); // grab the email address from the specified cell
const subject = `SUBJECT - ${ss.getName()}`; // the subject of the email
const body = "BODY"; // body of the email
const shID = ss.getSheetByName(sheetToPrint).getSheetId(); // the ID of the sheet
const url = 'https://docs.google.com/spreadsheets/d/SS_ID/export?'.replace('SS_ID', ss.getId()); // url of the spreadsheet
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf / csv / xls / xlsx
'&size=A4'+ // size of the PDF (legal / A4 / letter)
'&portrait=true'+ // orientation of the PDF (false for landscape)
'&fitw=true'+ // 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='+shID; // the sheet's Id
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
// generate the PDF file
var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();
// send the email to the specified address with the specified body text and attached PDF file
GmailApp.sendEmail(email, subject, body, {
htmlBody: body,
attachments: [{
fileName: `FILE NAME - ${ss.getName()}` + ".pdf",
content: response.getBytes(),
mimeType: "application/pdf"
}]
});
}
All you have to do is change the SPREADSHEET NAME, SHEET NAME, SUBJECT, BODY, and FILE NAME. Changing around the ExportOptions could also potentially help you.
Once you have this implemented, just set up a trigger for it to run every morning at 9AM.
If you have any questions, do not hesitate to contact me.

attach a sheet to a mailid mentioned in another sheet

I have a spreadsheet with multiple sheets and I have another sheet with column A containing mail ids
and column B containing sheet names.
Whenever a sheet comes I will check with relevant mail ids to where the sheets have to be attached
For eg for sheetname 10001515ADC I have to attach the sheet to mail id guru3291#gmail.com and mail it.
Similarly for 10003810ADC the mail id is kumaraguru#aai.aero
The Code I worked on
function email(){
var heet= SpreadsheetApp.openById('1mbFTGxhvSbbttfkaezJpfU1TXNtJUPBvujREPi3yVwo');
var mid = heet.getSheetByName('Sheet1');
var getNames = mid.getDataRange().getValues();
getNames.shift();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheetsObj = {};
for (var i = 1; i < sheets.length; i++) {
sheetsObj[sheets[i].getSheetName()] = sheets[i];
}
Logger.log(sheetsObj);
for (var i = 0; i < getNames.length; i++) {
var r = getNames[i];
if (r[1] in sheetsObj) {
var ssID = ss.getId();
Logger.log(ssID);
var c =r[1];
var p =ss.getSheetByName(c);
p.activate;
Logger.log(p);
var sheetgId = ss.getActiveSheet().getSheetId();
Logger.log(sheetgId);
var sheetName = ss.getName();
Logger.log(sheetName);
}
var token = ScriptApp.getOAuthToken();
var email = r[0];
var subject = "Important Info!";
var body = "Latest Recency Report \n\nRegards,\n VOTV-ATM-OPS";
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?" + "format=xlsx" +
"&gid="+sheetgId+ "&portrait=true" + "&exportFormat=pdf";
var result = UrlFetchApp.fetch(url, {
headers: { 'Authorization': 'Bearer ' + token}
});
var contents = result.getContent();
MailApp.sendEmail(email,subject ,body, {attachments:[{fileName:sheetName+".pdf", content:contents,
mimeType:"application//pdf"}]});
}
}
Your script is sending the wrong sheet because your activate request is not going through
This is due to the fact that you are referring to the method activate without calling it
To call a method, you need to reference it including the () brackets
So, modify p.activate; to p.activate();
See also Fucniton invoacation in Javascript.
SIDE NOTE
You do not need to activate a sheet to work with it.
The lines
var p =ss.getSheetByName(c);
p.activate();
var sheetgId = ss.getActiveSheet().getSheetId();
can be replaced by
var p =ss.getSheetByName(c);
var sheetgId = p.getSheetId();

how Send specific part of the sheet as email?

this script sends a pdf copy to my email when I type Send in cell L6 , this code send the whole sheet and I need to send as only A1:J22 , any Ideas ?
function onEdit2(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var r = sheet.getRange('L6').getValue();
if (r == "Send") {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ssID = ss.getId();
var sheetgId = ss.getActiveSheet().getSheetId();
var sheetName = ss.getName();
var token = ScriptApp.getOAuthToken();
var email = "EMAIL HERE";
var subject = "Daily report ";
var body = "Please find the attached Daily report";
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?"
+ "format=xlsx" + "&gid="+sheetgId+ "&portrait=true" +
"&exportFormat=pdf";
var result = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var contents = result.getContent();
MailApp.sendEmail(email,subject ,body, {
attachments: [{
fileName: sheetName + ".pdf",
content: contents,
mimeType: "application//pdf"
}]
})
}
}
You want to retrieve the cells of A1:J22 and want to create them to PDF data.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
In this modification, create a temporal sheet and copy the values of the cells of A1:J22 to it. Then, the temporal sheet is converted to PDF file. And, the temporal sheet is deleted.
Modified script:
When your script is modified, please modify as follows.
function onEdit2(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var r = sheet.getRange('L6').getValue();
if (r == "Send") {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ssID = ss.getId();
var sheet = ss.getActiveSheet(); // Added
// var sheetgId = ss.getActiveSheet().getSheetId(); // removed
var sheetName = ss.getName();
var token = ScriptApp.getOAuthToken();
var email = "EMAIL HERE";
var subject = "Daily report ";
var body = "Please find the attached Daily report";
var tempSheet = ss.insertSheet("tempSheet"); // Added
sheet.getRange("A1:J22").copyTo(tempSheet.getRange(1, 1)); // Added
SpreadsheetApp.flush(); // Added
var sheetgId = tempSheet.getSheetId(); // Added
var url = "https://docs.google.com/spreadsheets/d/"+ssID+"/export?" + "format=xlsx" + "&gid="+sheetgId+ "&portrait=true" + "&exportFormat=pdf";
var result = UrlFetchApp.fetch(url, {headers: {'Authorization': 'Bearer ' + token}});
var contents = result.getContent();
MailApp.sendEmail(email,subject ,body, {attachments: [{fileName: sheetName + ".pdf", content: contents, mimeType: "application//pdf"}]});
ss.deleteSheet(tempSheet); // Added
}
}
References:
insertSheet(sheetName)
copyTo(destination)
deleteSheet(sheet)
If I misunderstood your question and this was not the direction you want, I apologize.