通过电子邮件将 Sparkline 图表作为 Google Sheets 范围内的图像/博客/png 发送

2024-02-25

我尝试将此解决方案应用于我的案例:
通过电子邮件发送 SPARKLINE 图表会发送空白单元格而不是数据 https://stackoverflow.com/questions/50133870/emailing-sparkline-charts-sends-blank-cells-instead-of-data

但是当我尝试将其应用到我的情况时,会弹出错误:

TypeError: Cannot read property '0' of null

关于执行,有有关此错误的更多信息:

我的电子邮件解决方案的 GAS 代码只能发送值,它在这里:

function alertDailyInfo() {

    let emailAddress = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SANDBOX").getRange("F1").getValue();
    
    let treeIconUrl = "https://d1nhio0ox7pgb.cloudfront.net/_img/g_collection_png/standard/256x256/tree.png";
    let treeIconBlob = UrlFetchApp
                       .fetch(treeIconUrl)
                       .getBlob()
                       .setName("treeIconBlob");
    
    let treeUpdate = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SANDBOX").getRange("F6").getValue();
    let waterUpdate = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SANDBOX").getRange("F11").getValue();

            if (treeUpdate > 0) {
            
                    MailApp.sendEmail({
                        to: emailAddress,
                        subject: "TREE WATER UPDATE",
                        htmlBody: "<img src='cid:treeIcon'><br>" + '<br>' + '<br>' +  
                        '<b><u>Tree average is:</u></b>'+ '<br>' + treeUpdate + '<br>' + '<br>' +
                        '<b><u>Water average is:</u></b>'+ '<br>' + waterUpdate + '<br>' + '<br>' 
                        ,
                        inlineImages:
                        {
                            treeIcon: treeIconBlob,
                        }
                    });                
                }
            }

上面链接中提供的解决方案的代码以及我尝试适应我的情况的代码(请检查下面的文件)在这里:

drawTable();

function drawTable() {

 let emailAddress1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SANDBOX").getRange("F1").getValue();

    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: emailAddress1,
        subject: "Spreadsheet Data",
        htmlBody: html,
        inlineImages: images // Added
    })
}

function getData(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SANDBOX");
  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;
  }
}

我在上面粘贴的仅适用于值的代码(第一个代码块)将向我发送如下电子邮件:

但我需要收到这样的电子邮件,迷你图的值低于如下所示:

电子邮件解决方案的代码(仅适用于我在上面粘贴的值(第一个代码块))正在运行。但由于某种原因,当上面链接的解决方案中的代码(第二个代码块)导入/保存到我的 Google Sheets 文件 GAS 脚本库并适应我的情况时,一切都停止工作,显示上述错误。

所以基本上,正如您可能已经理解的那样,我需要发送包含以下值的电子邮件Tree Average and Water Average,我设法让它发挥作用。但我还需要您可以在下面看到的迷你图,并通过检查下面链接的我的文件,也可以将其作为图像/斑点发送,就在信息下方,如上面的屏幕截图所示。

任何人都可以提供有关应用上述解决方案中可能缺少的内容的任何指示,或者是否有更好的替代方案来通过电子邮件发送 SPARKLINE 图作为图像/blob?

这是我的文件:
https://docs.google.com/spreadsheets/d/1ExXtmQ8nyuV1o_UtabVJ-TifIbORItFMWjtN6ZlruWc/edit?usp=sharing https://docs.google.com/spreadsheets/d/1ExXtmQ8nyuV1o_UtabVJ-TifIbORItFMWjtN6ZlruWc/edit?usp=sharing

EDIT_1:
我做了一些编辑以使其更加清晰。

EDIT_2:
根据要求,这是应用于第一个迷你图的公式,第二个迷你图几乎相同:

=ARRAYFORMULA( SPARKLINE(QUERY({IFERROR(DATEVALUE(SANDBOX!$A$2:$A)), SANDBOX!$B$2:$B}, 
 "select Col2 
  where Col2 is not null 
  and Col1 <= "&INT(MAX(SANDBOX!$A$2:$A))&"
  and Col1 >  "&INT(MAX(SANDBOX!$A$2:$A))-(
IFERROR(
          VLOOKUP(
           SUBSTITUTE($F$4," ",""),
            {"24HOURS",0;
            "2DAYS",1;
            "3DAYS",4; 
            "7DAYS",8; 
            "2WEEKS",16;  
            "1MONTH",30;
            "3MONTHS",90; 
            "6MONTHS",180; 
            "1YEAR",365;
            "2YEARS",730; 
            "3YEARS",1095},
           2,FALSE))
)-1, 0),
 {"charttype","column";"color","#00bb21";"empty","ignore";"nan","ignore"}))

EDIT_3:
根据鲁本的建议,我删除了drawTable();在代码块的开头。

我还将迷你图的公式转移到另一个辅助表中,并将其链接到主表中。 尝试后似乎不再出现该错误。虽然收到的邮件有2个问题:

  • 我收到整张表格的表格,我只想要迷你图。
  • 此外,迷你图并不是以图像形式出现,它们根本不显示。他们还应该出现在哪里,上面写着undefined.

我猜整张纸都被设置了,因为函数获取了范围getDataRange();正在获取整个工作表范围。

这是一个屏幕截图:


As the question https://stackoverflow.com/questions/50133870/emailing-sparkline-charts-sends-blank-cells-instead-of-data你参考解释:

创建的图表SPARKLINE https://support.google.com/docs/answer/3093289?hl=en无法直接导入到电子邮件中。

为什么脚本不起作用?因为您没有对其进行任何重大修改,并且因为您使用的公式比另一个问题中提出的公式更复杂,所以在不进行任何修改的情况下使其工作非常困难(如果不是不可能)。

有什么选择?在我看来,你有 3 种不同的选择。

  1. 遵循提出的解决方案的逻辑Tanaike https://stackoverflow.com/a/50146374/14271633在另一个问题中并使用EmbeddedChartBuilder https://developers.google.com/apps-script/reference/spreadsheet/embedded-chart-builder#addRange(Range)尝试分解公式的内容以达到与SPARKLINE https://support.google.com/docs/answer/3093289?hl=en.

  2. Use the SpreadsheetApp https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app方法直接从工作表中获取值并从那里构建图表。这是一个小示例,说明如何使用Chart Service https://developers.google.com/apps-script/reference/charts(你可以达到完全相同的效果EmbeddedChartBuilder)。因为你已经有一个Blob https://developers.google.com/apps-script/reference/base/blob?hl=en对象,您可以将其插入电子邮件中,就像我在工作表中所做的那样。

function constCreateChart() {
  const sS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('HELPER')
  const chart = Charts.newDataTable()
    .addColumn(Charts.ColumnType.NUMBER, '')
    .addColumn(Charts.ColumnType.NUMBER, '')

  // Modfify with your data
  // getRange('A2:A15').getValues()...
  const builder = [...Array(100).keys()].forEach(n => {
    chart.addRow([n, n * n * Math.random()])
  })
  chart.build()

  const chartShap = Charts.newColumnChart()
    .setDataTable(chart)
    .setLegendPosition(Charts.Position.NONE)
    .setOption('hAxis.ticks', [])
    .setOption('vAxis.ticks', [])
    .build()

  sS.insertImage(chartShap.getAs('image/png'), 5, 5)

}
Result
  1. 用这个要求 Google 添加转换使用以下方式获得的图表的可能性SPARKLINES https://support.google.com/docs/answer/3093289?hl=en可以在电子邮件中使用的 Blob 对象。
文档
  • 图表服务中的可用选项 https://developers.google.com/chart/interactive/docs/gallery/areachart
  • Google Sheets 的 Apps 脚本基础知识 #5:在幻灯片中绘制图表和呈现数据 https://developers.google.com/codelabs/apps-script-fundamentals-5#0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过电子邮件将 Sparkline 图表作为 Google Sheets 范围内的图像/博客/png 发送 的相关文章