Export Google sheet Chart as an image - google-apps-script

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);
}

Related

How do I change positions of charts that I have pulled from a google sheet, to position them in an email using appscript

Im currently taking charts from the 2nd tab of my google sheet to embed them into an email using appscript. I was wanting to know how can I make the position of the charts permanent within the email as the images move depending on the size of the browser window. please see my current script and associated images.
function emailChartSource(){
const sheet = SpreadsheetApp.getActiveSpreadsheet();
const sheetName = sheet.getSheetByName('At a Glance');
const charts = sheetName.getCharts();
var bodyEmail = "Hi Team,<br> Below is an overview of the testing efforts for UAT Wireless<br>"
var currentDate = Utilities.formatDate(new Date(), 'America/Denver', 'M/d/yy');
var imgcontainer = {};
var bodyCharts = "";
var chartcount = charts.length
for(var chartNo=0; chartNo <=chartcount-1;chartNo++){
var img = charts[chartNo].getAs("image/png")
imgcontainer["chart" + (chartNo+1)]=img
bodyCharts = bodyCharts + "<img src='cid:chart" + (chartNo+1)+"'>";
}
bodyEmail = bodyEmail + bodyCharts;
MailApp.sendEmail({
to: "someemail#gmail.com",
subject: "UAT Wireless Testing Status Report as of " + currentDate + " - Boost Prepaid",
htmlBody: bodyEmail,
inlineImages: imgcontainer,
});
}
Incorrect Display
How I would like it to display

Send range via email with google script

I want to send range by email
For example:
https://docs.google.com/spreadsheets/d/1GH5r0sY_Z-15M479xG12yCUZaV0NRU8jpkWAxPNBuwU/edit?usp=sharing
I tried this:
function sendInvoiceList(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Invoice").getRange("A1:B10").getValues();
var message = sheet;
var email_subj = "Invoice " + Utilities.formatDate(new Date(), "GMT+1:00", "dd.MM.yyyy");
MailApp.sendEmail({
to: "user#gmail.com",
subject: email_subj,
htmlBody: "Please send us this list:<br><br><br>" + message
});
}
The system send this:
textA1,textA2,textA3,textA4,textA5,textA6,textA7,textA8,textA9,textA10
I need value in range A1:B10 but the system only A1 separated by comma I need in column format.
How do it?
Thanks for support
Angelo
Your setting message equal to a two dimensional array you need to rethink that. I think this maybe closer to what you want. I tested it with some data of my own but don't know what you have. Share an image of your spreadsheet if you need more assistance.
function sendInvoiceList(){
var ss=SpreadsheetApp.getActive()
var sh=ss.getSheetByName("Invoice");
var rg=sh.getRange("A1:B10")
var vA=rg.getValues();
var html='<style>td,th{border:1px solid black;}</style><table>';
vA.forEach(function(r,i){
html+='<tr>';
r.forEach(function(c,j){
if(i=0) {
html+=Utilities.formatString('<th>%s</th>',c)
}else{
html+=Utilities.formatString('<td>%s</td>',c)
}
});
html+='</tr>';
});
html+='</table>';
var email_subj = "Invoice " + Utilities.formatDate(new Date(), "GMT+1:00", "dd.MM.yyyy");
MailApp.sendEmail({to: "user#gmail.com",subject: email_subj,htmlBody: "Please send us this list:<br><br><br>" + html});
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), 'Display');//Just a dialog for testing the html
}

How to add an existing chart in sheets while sending an email

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

Inserting 3d chart from Google Sheet into email as an image using Appscript

I am trying to insert 3D charts from google sheet into email using the below code but the image in the email is getting converted to 2D.
Can anyone help me to pull the charts from google sheet into an email with all its properties intact?
The Original Chart
The Chart in Email
function email(sheet, toMail, ccMail, msg){
var charts = sheet.getCharts();
var emailImages={};
var chartBlobs=new Array(charts.length);
for(var i=0;i<charts.length;i++){
chartBlobs[i]= charts[i].getAs("image/png").setName("chartBlob"+i);
emailBody= emailBody + "<p align='left'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: toMail,
cc: ccMail,
subject: "ABC",
htmlBody: emailBody,
inlineImages:emailImages});
}
You want to send email including the 3D chart on Spreadsheet.
If my understanding is correct, how about this workaround? I experienced the same issue with you. When the chart on Spreadsheet are retrieved as a blob, the chart of the blob is different from the original chart. I think that this might be a bug. In this case, as one of several workarounds, I used the following flow.
Flow of modified script:
Retrieve charts from Spreadsheet.
Create Google Slides as a temporal.
Insert the charts to Slides as images.
Retrieve the inserted charts as blobs.
Send email including the retrieved blob.
Remove the temporal Google Slides.
Modified script:
In this modification, I modified your script. Please modify your script as follows.
function email(sheet, toMail, ccMail, msg){
var charts = sheet.getCharts();
var slides = SlidesApp.create("sample"); // Added
var slide = slides.getSlides()[0]; // Added
var emailImages={};
var chartBlobs=new Array(charts.length);
var emailBody = ""; // Added
for(var i=0;i<charts.length;i++){
var image = slide.insertSheetsChartAsImage(charts[i]); // Added
chartBlobs[i]= image.getAs("image/png").setName("chartBlob"+i); // Modified
emailBody= emailBody + "<p align='left'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: toMail,
cc: ccMail,
subject: "ABC",
htmlBody: emailBody,
inlineImages:emailImages});
DriveApp.getFileById(slides.getId()).setTrashed(true); // Added
}
Note:
In this modified script, the temporal Google Slides is moved to the trash box.
I reported this issue to the issue tracker.
References:
Save a canvas image to google drive.
Also I proposed above workaround here.
insertSheetsChartAsImage()
setTrashed()
If I misunderstood your question and this workaround was not what you want, I apologize.

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});
}