How to add an existing chart in sheets while sending an email - google-apps-script

I want a Line chart from my spreadsheet to appear in the email.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Agent Report - Monthly")
var startRow = 3; // First row of data to process since there is a header row
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Agent Report - Monthly").getRange("D3");
var emailAddress = emailRange.getValues();
var chartImg = Charts.newLineChart.setRange(12, 8) //This Throws an error
var subject = "Agent Report - Monthly"; // This is the subject of the email
var greeting_text = 'Hey Please find the below Report '+'</b><br><br>';
var text = greeting_text;
text+=SheetConverter.convertRange2html(sheet.getRange(startRow, 3 ,10,8));
text+='<br>';
var options = {
htmlBody: text,
noReply:true
};
MailApp.sendEmail({
to: "xxx#der.com",
subject: subject,
htmlBody: options,
inlineImages: {
chartImg: chartImage,
}
});
}
When I try to add the chart to the variable ChartImg in line 7, it throws an exception.

If I understand correctly, you already have the chart created without issue in the spreadsheet, and you only want to get it as an image. To do this you need a reference to the chart in the sheet, and then use the getAs() method on the chart's blob, it would look something like this for you:
var chart = sheet.getCharts()[0]; // assuming you only have that chart, this is just to get the chart's reference.
var options = {
htmlBody: "<img src='cid:chart' style='width:24px; height:16px;'/>",
noReply:true
};
var chartImg = chart.getBlob().getAs('image/png').setName("areaBlob");
// Then you would add it in the body of the email as an attachment
MailApp.sendEmail({
to: "xxx#der.com",
subject: subject,
htmlBody: options,
inlineImages: {
chart: chartImg,
}
});
In the following link you can find a more in depth explanation and example: Chart image in email from Google spreadsheet with google-apps-script returns white image

Related

Weird behaviour of Mailapp.sendEmail in Google apps script

I have been sending emails successfully through Google apps script triggered through submission in a Google sheet. Lately (about a week back), the email sender starts behaving very weird.
If I use the following format, my emails get bounced
MailApp.sendEmail(email1, subject, message,{cc:email2,attachments:[file.next()]});
If I use the following form, the email does NOT get delivered neither does it get bounced
MailApp.sendEmail(email, subject, message);
If I use the following format, the recipient gets the message as shown
MailApp.sendEmail(email,subject,{htmlBody: message});
Revecied message
[object Object]
and the rest of the stuff blank!
I'm at my wits' end as to how to go about. Any help or a pointer will be of immense help. Regards
Madhurjya
Following is the app script, which is attached to the Google sheet. Once I run the function sendPasswd() from sheet, it gets some vital parameters from the sheet data and then send the message to the person (through the variable email2)
function sendPasswd() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var dataRange = sheet.getDataRange()
var data = dataRange.getValues();
var subject = "Example Subject";
var message = "";
var i;
var file = DriveApp.getFilesByName("some_file.pdf");
for (i in data) {
var row = data[i];
if (i == 0) continue; // Skip the first row
if (row[4] == "Sent") continue;
var first = row[0]; var last = row[1]; var email = row[2];
var passwd = row[3]; var email2 = row[7];
if (row[15] == "some condition") {
message = "Dear <b>"+first+" "+last+"</b>,<br><br>"+
"This is to inform you that your .... ";
MailApp.sendEmail(email2, subject, message);
//MailApp.sendEmail(email2,subject,{htmlBody: "message"});
//MailApp.sendEmail(email2, subject, message,{cc:"some_email#example.com",attachments:[file.next()]});
}
}
}
The surprising fact is that from the same account similar emails are being sent and are NOT affected!
Madhurjya
This might be happening because you're using htmlbody which is part of options as third argument whereas in sendEmail(recipient, subject, body, options) of class MailApp, body should be third argument, that's is the reason of getting [object Object].
Try following modification:-
MailApp.sendEmail(email2,subject,"",{htmlBody: message});
Reference:
sendEmail
You could also use this way (its really more practical):
const email 'yourEmail#outlook.com'
const cc ='copyEmail#hotmail.com'
const bcc = 'blindCarbonCopy#gmail.com'
MailApp.sendEmail({
to:email,
cc: cc,
bcc: bcc,
subject: 'Whatever you want, even template strings' ,
htmlBody: `
You could just create your HTML IN HERE (using template strings)
Or create before and add here as variable as well.
`
})

How to send email based on cell contents in Google Sheets using custom function

I have a spreadsheet where data will be continuously inputted (through Google Forms and user input), and I would like to have code that will send out a single email for a single row, which I can call multiple times as rows get completed. Currently, I created a custom function that is supposed to do this but when I run it I get an error which reads "You do not have permission to call MailApp.sendEmail. Required permissions: https://www.googleapis.com/auth/script.send_mail (line 6)."
function sendDirectiveResponse(name, message, response, emailAddress) {
var sheet = SpreadsheetApp.getActiveSheet();
var emailSent = "Email Sent";
var message = "Received: " + message + "\n\n Response: " + response;
var subject = "Message Response";
MailApp.sendEmail(emailAddress, subject, message);
return emailSent
}
I expect an email to be sent out and the cell to show "Email Sent" but, instead, it says "#ERROR" and no email is sent.
Sending emails based upon cell contents
function sendMyEmails() {
var ss=SpreadsheetApp.getActive();
//the next few commands create a newsheet and load it with sample data so that you do not have to. You will want to remove this and use a spreadsheet of your own choosing
var sh=ss.insertSheet();//setup
var init=[['Email','Subject','Message','Status'],['sample1#gmail.com','Email Testing','Have a great day.',''],['sample2#gmail.com','Email Testing','Have a great day.',''],['sample3#gmail.com','Email Testing','Have a great day.',''],['sample4#gmail.com','Email Testing','Have a great day.','']];//setup
sh.getRange(1,1,init.length,init[0].length).setValues(init);//setting up data
var rg=sh.getDataRange();//get data
var vA=rg.getValues();
var hObj=[];
var html='';
for(var i=0;i<vA.length;i++) {
for(var j=0;j<vA[i].length;j++) {
hObj[vA[0][j]]=vA[i][j];//this loads the object with all of the data for this row. And you can now refer to it with hObj.headertitle
}
if(!hObj.Status) {//When you supply your own data this will prevent function from sending emails more than once
html+=Utilities.formatString('<br />Email: <strong>%s</strong> Subject: <strong>%s</strong> Message: <strong>%s</strong>', hObj.Email,hObj.Subject,hObj.Message)
sh.getRange(i+1,vA[0].indexOf('Status') + 1).setValue('Done')
//MailApp.sendEmail(hObj.Email, hObj.Subject, hObj.Message);//removed for testing you will have to uncomment this line to actually send email
}
}
var ui=HtmlService.createHtmlOutput(html).setWidth(1000);
SpreadsheetApp.getUi().showModelessDialog(ui, 'Email Testing');//this provides a dialog to show you what would have been sent if everything were enabled.
}

cell reference out of range on Email Notifications

I have the below code for sending a email notification when a cell changes, but it is always returning Cell reference out of range(line 5, file "Missing Cuts Report"). Can anyone advise if i need to change the code or if there is a way of getting it to stop failing and still send the email notification through. The trigger i use is OnChange because when it was on OnEdit it came back with error service invoked too many times on line 17 MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body }). Any help would really be appreciated.
function sendEnailNotification(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var cellvalue = ss.getActiveCell().getValue().toString();
if(SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName() == "Missing Cuts Report") {
if(cell.indexOf('B')!=-1){
if(cellvalue > "") {
//Define Notification Details
var recipients = "email#email.co.uk;
var subject = "New Missing Cut Added";
var body = 'A new line has been added on the Missing Cuts Report on line <b>' + cell + '</b> - click here to view the update';
var msgPlain = body.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body });
}
}
}
}
Hi this is a not a very good way of achieving the result you want. Not really to sure what you are after. I have however made some adjustments to your code with notes after the closing braces. This is not an answer to your original problem. Just some hints.
function sendEmailNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var cellvalue = ss.getActiveCell().getValue().toString();
if(sheet.getName() === "Missing Cuts Report") {
//if(cell.indexOf('B')!== -1){
if(cellvalue !== "") {
//Define Notification Details
var recipients = "email#address.org";
var subject = "New Missing Cut Added";
var body = 'A new line has been added on the Missing Cuts Report on line <b>' + cell + '</b> - click here to view the update';
var msgPlain = body.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body });
} // "<" and ">" are not for comparing string values. (At least not in this case.)
//} //IndexOf will always result in -1 if you are looking for just "B" as your result will always be "B1/B2/B3/ect."
} // Already have the sheet object, no need to call again.
}

Export Google sheet Chart as an image

Would you please help on how to export a chart to a image using google script.
I wrote this code but it doesn't work. I'm worrying that the API getAs is deprecated.
function TestEmailCharts(){
var sheet = SpreadsheetApp.getActiveSheet();
var charts = sheet.getCharts();
if(charts.length!=0)
{
var chartBlobs=new Array(charts.length);
var emailBody="Charts<br>";
var emailImages={};
for(var i=0;i<charts.length;i++){
chartBlobs[i]= charts[i].getAs("image/jpeg").setName("chartBlob"+i);
emailBody= emailBody + "<img src='cid:chart"+i+"'><br>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: "email#gmail.com",
subject: "test2",
htmlBody: emailBody,
inlineImages:emailImages});
}
}
To reproduce the problem, create a Google spread sheet
Create a simple chart with some data.
Add this code to scripts.
Replace email#gmail.com with your email
Normally you should receive an email with chart image
But the problem is that you will receive a email with black image.
Best regards.
Exporting a Google sheet chart as an image
By Email:
First create the chart and then get its blob. Then send the blob as attachment.
function createPieChart(){
var sheet = SpreadsheetApp.openById("<ID>").getSheetByName("<SheetName>");
var chartBuilder = sheet.newChart()
.asPieChart()
.set3D()
.addRange(sheet.getRange("A20").getDataRegion())
.setPosition(16, 5, 0, 0)
.setOption('title', "Total hour split in 2020");
var blob = chartBuilder.build().getBlob();
sendMail(blob);
}
function sendMail(img){
MailApp.sendEmail({
to: "john#domain.com",
subject: "test",
htmlBody: "fair enough",
attachments: [img]}); //If this gives you problems, replace img with img.getAs(MimeType.JPEG)
}
To another spreadsheet (different from where the source data for the chart is):
Similar way, create the chart and then insert the blob as an image in the destination sheet:
function createPieChart(){
var srcSheet = SpreadsheetApp.openById("<ID>").getSheetByName("<SheetName>");
var destSheet = SpreadsheetApp.openById("<ID>").getSheetByName("<SheetName>");
var chartBuilder = srcSheet.newChart()
.asPieChart()
.set3D()
.addRange(sheet.getRange("A20").getDataRegion())
.setPosition(16, 5, 0, 0)
.setOption('title', "Total hour split in 2020");
var blob = chartBuilder.build().getBlob();
destSheet.insertImage(blob, 1, 1);
}

Emailing a chart from a Google spreadsheet with apps script

I've search high and low for an answer but without an y luck. Got a Google spreadsheet which uses apps script to connect to a database to pull in some raw data into a spreadsheet. I then use various spreadsheet formulas to manipulate that data and then final create a chart.
My next challenge is that I want to be able to embed that chart into an email via apps script and send it as an HTML email..
Is this at all possible or should I start looking for some other solution?
Thanks!
Mikael
Here is the code I used to email charts.
Please note that you need to give everyone with the link access to the spreadsheet. If not, you'll get an image in the email stating user is not signed in. (very annoying that there's no workaround to this)
function emailCharts(sheet,emails,emailSubject){
var charts = sheet.getCharts();
if(charts.length==0){
MailApp.sendEmail({
to: emails,
subject: "ERROR:"+emailSubject,
htmlBody: "No charts in the spreadsheet"});
return;
}
var chartBlobs=new Array(charts.length);
var emailBody="Charts<br>";
var emailImages={};
for(var i=0;i<charts.length;i++){
chartBlobs[i]= charts[i].getAs("image/png").setName("chartBlob"+i);
emailBody= emailBody + "<img src='cid:chart"+i+"'><br>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: emails,
subject: emailSubject,
htmlBody: emailBody,
inlineImages:emailImages});
}
Make the spreadsheet Public and run the script. Modified version of the script pasted below with comments
enter code here function
emailCharts(sheet,emails,emailSubject){
var targetspreadsheet = SpreadsheetApp.getActiveSpreadsheet(); // Active spreadsheet of the key file
var sheet = targetspreadsheet.getSheetByName('Sheet1'); // Change the sheet name
var emailSubject = 'test';
var emails = 'test#test.com'; // your email ID
var charts = sheet.getCharts();
if(charts.length==0){
MailApp.sendEmail({
to: emails,
subject: "ERROR:"+emailSubject,
htmlBody: "No charts in the spreadsheet"});
return;
}
var chartBlobs=new Array(charts.length);
var emailBody="Charts<br>";
var emailImages={};
for(var i=0;i<charts.length;i++){
var builder = charts[i].modify();
builder.setOption('vAxis.format', '#');
var newchart = builder.build();
chartBlobs[i]= newchart.getAs('image/png');
emailBody= emailBody + "<p align='center'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: emails,
subject: emailSubject,
htmlBody: emailBody,
inlineImages:emailImages});
}
As the Charts Service appears to only be a partial implementation of EmbeddedChart used in SpreadsheetApp Service not all of the ChartTypes and options are implemented, meaning charts might render differently than they do in Google Sheets. The modified version of the previous answer below will mean charts are included in emails as images as they appear in Google Sheets. As this solution also uses an authentication token generated by the script the view permissions on the Google Sheet does not have to be changed.
// Based on https://stackoverflow.com/a/22200230/1027723
function emailChartUsingImageUrl(){
const idt = SpreadsheetApp.getActive().getId();
const sheet = SpreadsheetApp.getActiveSheet();
const charts = sheet.getCharts();
// setup some variables for our email
const chartBlobs = new Array();
const emailImages = {};
let emailBody = "Charts<br>";
// setup our call to fetch the chart image
const token = ScriptApp.getOAuthToken(); // project requires https://www.googleapis.com/auth/spreadsheets scope
const baseUrl = `https://docs.google.com/spreadsheets/d/${idt}/embed/oimg?access_token=${token}&disposition=ATTACHMENT&bo=false&filetype=png&oid=`;
// for each chart fetch the download image as a blob and appended to our email body
charts.forEach(function(chart, i){
// NEW BIT
const url = baseUrl + chart.getChartId();
chartBlobs[i] = UrlFetchApp.fetch(url).getBlob();
emailBody += "<p align='center'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
});
// Send email with inline images
MailApp.sendEmail({
to: "me#example.com",
subject: "Email Charts - get chart from image url",
htmlBody: emailBody,
inlineImages:emailImages});
}