Emailing SPARKLINE charts sends blank cells instea

2019-02-19 12:48发布

问题:

I have a Google Sheet with cells of both data and =sparkline() in-cell charts, and want to send this data view in an email. I currently use Apps Script to make an HTML email, but the sparkline charts display as blank cells in the email's table.

The data as viewed on Google Sheets:
The data as viewed in the email:

This is my Apps Script code:

function drawTable() {
    var ss_data = getData();
    var data = ss_data[0];
    var background = ss_data[1];
    var fontColor = ss_data[2];
    var fontStyles = ss_data[3];
    var fontWeight = ss_data[4];
    var fontSize = ss_data[5];
    var html = "<table border='1'>";
    for (var i = 0; i < data.length; i++) {
        html += "<tr>"
        for (var j = 0; j < data[i].length; j++) {
            html += "<td style='height:20px;background:" + background[i][j] + ";color:" + fontColor[i][j] + ";font-style:" + fontStyles[i][j] + ";font-weight:" + fontWeight[i][j] + ";font-size:" + (fontSize[i][j] + 6) + "px;'>" + data[i][j] + "</td>";
        }
        html += "</tr>";
    }
    html + "</table>"
    MailApp.sendEmail({
        to: Session.getUser().getEmail(),
        subject: "Spreadsheet Data",
        htmlBody: html
    });
}


function getData(){
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getDataRange();
  var background = ss.getBackgrounds();
  var val = ss.getDisplayValues();
  var fontColor = ss.getFontColors();
  var fontStyles = ss.getFontStyles();
  var fontWeight = ss.getFontWeights();
  var fontSize = ss.getFontSizes();
  return [val, background, fontColor, fontStyles, fontWeight, fontSize];
}

Could anyone please suggest the code needed to display sparkline charts in the email, or any other work around?

回答1:

How about this workaround? I think that there are several workaround in your situation. So please think of this as one of them.

Unfortunately, the chart created by SPARKLINE() cannot be directly imported to the email. So as a workaround, I used the following flow.

  1. Convert from the chart created by SPARKLINE() to the images using EmbeddedChart.
  2. Send email with the images as the inline images.

Modified script :

drawTable();
function drawTable() {
    var ss_data = getData();
    var data = ss_data[0];
    var background = ss_data[1];
    var fontColor = ss_data[2];
    var fontStyles = ss_data[3];
    var fontWeight = ss_data[4];
    var fontSize = ss_data[5];
    var html = "<table border='1'>";
    var images = {}; // Added
    for (var i = 0; i < data.length; i++) {
        html += "<tr>"
        for (var j = 0; j < data[i].length; j++) {
            if (typeof data[i][j] == "object") { // Added
                html += "<td style='height:20px;background:" + background[i][j] + ";color:" + fontColor[i][j] + ";font-style:" + fontStyles[i][j] + ";font-weight:" + fontWeight[i][j] + ";font-size:" + (fontSize[i][j] + 6) + "px;'><img src='cid:img" + i + "'></td>"; // Added
                images["img" + i] = data[i][j]; // Added
            } else {
                html += "<td style='height:20px;background:" + background[i][j] + ";color:" + fontColor[i][j] + ";font-style:" + fontStyles[i][j] + ";font-weight:" + fontWeight[i][j] + ";font-size:" + (fontSize[i][j] + 6) + "px;'>" + data[i][j] + "</td>";
            }
        }
        html += "</tr>";
    }
    html + "</table>"
    MailApp.sendEmail({
        to: Session.getUser().getEmail(),
        subject: "Spreadsheet Data",
        htmlBody: html,
        inlineImages: images // Added
    })
}

function getData(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
  var ss = sheet.getDataRange();
  var val = ss.getDisplayValues();
  var background = ss.getBackgrounds();
  var fontColor = ss.getFontColors();
  var fontStyles = ss.getFontStyles();
  var fontWeight = ss.getFontWeights();
  var fontSize = ss.getFontSizes();
  var formulas = ss.getFormulas(); // Added
  val = val.map(function(e, i){return e.map(function(f, j){return f ? f : getSPARKLINE(sheet, formulas[i][j])})}); // Added
  return [val,background,fontColor,fontStyles,fontWeight,fontSize]; 
}

// Added
function getSPARKLINE(sheet, formula) {
  formula = formula.toUpperCase();
  if (~formula.indexOf("SPARKLINE")) {
    var chart = sheet.newChart()
      .setChartType(Charts.ChartType.SPARKLINE)
      .addRange(sheet.getRange(formula.match(/\w+:\w+/)[0]))
      .setTransposeRowsAndColumns(true)
      .setOption("showAxisLines", false)
      .setOption("showValueLabels", false)
      .setOption("width", 200)
      .setOption("height", 100)
      .setPosition(1, 1, 0, 0)
      .build();
    sheet.insertChart(chart); 
    var createdChart = sheet.getCharts()[0];
    var blob = createdChart.getAs('image/png');
    sheet.removeChart(createdChart);
    return blob;
  }
}

Result :

Note :

  • In this modified script, it supposes that you use the chart as SPARKLINE.
  • I created a chart in the sheet using insertChart(), because the blob directly retrieved from newChart() cannot be used as an image. When the chart is created to the sheet, the blob retrieved from the created chart can be used as an image.
  • If you want to modify the size of images, please modify setOption("width", 200) and setOption("height", 100).

References :

  • EmbeddedChart
  • Visualization: Sparkline

If I misunderstand your question, I'm sorry.