通过电子邮件将 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 发送 的相关文章

  • 禁用 ASPNET 身份 2.0 中的用户

    我正在寻找一种方法来禁用用户而不是从系统中删除它们 这是为了保持相关数据的数据完整性 但似乎 ASPNET 身份只提供删除帐户 有一个新的锁定功能 但似乎可以控制锁定以禁用用户 但只有在尝试了一定次数的错误密码后才将用户锁定 还有其他选择吗
  • 按照说明后“找不到您尝试购买的商品”

    所以我按照以下说明进行操作http developer android com google play billing billing admin html http developer android com google play bi
  • 收到 Python 错误“来自:无法读取 /var/mail/Bio”

    我正在运行一个 bio python 脚本 这会导致以下错误 from can t read var mail Bio 由于我的脚本与邮件没有任何关系 我不明白为什么我的脚本在 var mail 中查找 这里似乎有什么问题 我怀疑这会有帮助
  • 如何将函数导入到Vue组件中?

    我正在尝试将单个函数导入到我的 Vue 组件中 我为我的函数创建了一个单独的 js 文件 randomId js exports randomId gt My function 在我的 Vue 组件中 我导入了 Random js let
  • gjs 如何使用 g_data_input_stream_read_line_async 在 Gnome Shell 扩展中读取套接字流

    我正在尝试编写一个 Gnome Shell 扩展 通过 Socket 服务器与 Arduino 进行通信 服务器和 Arduino 运行良好 但我陷入了监听传入服务器消息的扩展代码 因为我需要一种非阻塞方法 所以使用异步读取行 https
  • 什么时候使用静态库需要头文件?

    如果我在 Linux 中用 C 创建一个静态库并生成 a 文件 我 或其他人 如何使用该库 例如 我的库定义了一个类 我认为仅仅提供 a 文件是不够的 还需要提供头文件 我如何知道 a 文件必须提供哪些头文件 例如 我是否需要提供我的库代码
  • 如何将 char 转换为 unsigned int?

    我有一个字符数组 它实际上用作字节数组 而不是用于存储文本 在数组中 有两个特定字节表示我需要存储到无符号 int 值中的数值 下面的代码解释了设置 char bytes bytes 2 bytes 0 0x0C For the sake
  • 有什么方法可以禁用/覆盖 Galaxy Tab 4 上的多任务按钮吗? [复制]

    这个问题在这里已经有答案了 我们编写了一个工业控制应用程序 并随我们的制造产品预装在三星 Galaxy 平板电脑上 我们使用的平板电脑是运行 Honeycomb 的 Tab 10 但我们无法再获得足够的 OEM 平板电脑 因此我们改用运行
  • 如何使用 PHP 从 iframe 获取 url

    如何从下面的链接获取 YouTube 网址 您可以使用 regex 和 preg match 函数 preg match src iframe string match url match 1 UPDATE如果您有使用 php 生成的页面或
  • 了解客户端文件的对象 URL 以及如何释放内存

    我在用createObjectURL获取本地图像文件的引用 URL 当我完成文件 图像后 我打电话revokeObjectURL释放该内存 一切对我来说都很好 但我只是想确保我释放了我能释放的所有内存 我检查后出现了我的担忧chrome b
  • RecyclerView 不调用 onCreateViewHolder 或 onBindView

    没有收到任何错误 所有数据似乎都有效 由于某种原因 没有调用与视图相关的方法 我已确定以下事项 getItemCount 是唯一被调用的适配器方法 并且返回一个正整数值 我知道这将是你们将要查看的区域 构造函数正在被调用 成员变量有效 Pa
  • 设置 Silex Bootstrap 时出现 Apache 错误:无法检查 htaccess 文件

    我正在尝试使用 Silex Bootstrap 建立一个网站 我已将它与其他 Web 项目一起放在我的文件夹中 并更改了 Apache 配置中的 DocumentRoot
  • 如何在 Xcode 10 中恢复快速帮助?

    在我升级到 Xcode 10 后 快速帮助信息仅提供所选类或结构的声明 是否有某个设置可以使其与 Xcode 9 中的设置相同 升级后我遇到了同样的问题 其中函数签名是单击选项时唯一显示的内容 当我删除里面的所有内容后 快速帮助再次出现 L
  • Docker-compose:npm 安装成功后卷中不存在 node_modules

    我有一个具有以下服务的应用程序 web 在端口 5000 上保存并运行 python 3 Flask Web 服务器 使用 sqlite3 worker 有一个index js文件是队列的工作人员 Web 服务器通过端口使用 json AP
  • 我可以以某种方式“编译”一个Python脚本以在没有安装Python的PC上运行吗?

    所以我有一个Python脚本 myscript py 我是这样执行的 python D myscript py 但是 我必须安装 Python 并将其包含在PATH使其工作的环境变量 是否有可能以某种方式将 Python 可执行文件与 Py
  • Android On Focus Listener 和 On Click Listener on ImageView

    我有一个 imageview 它具有两个属性 可聚焦的 and 可聚焦触摸模式 set to true
  • 如何解释 mgcv 的随机效应图

    我有一些关于在 GAM 中使用随机效果的问题 首先 您如何解释和传达输出图 我在这个 GAM 中将火灾建模为随机效应 因为它在我的不同现场站点上很大程度上是随机发生的 并且我只将其记录为二进制 它不能作为普通变量工作 因为它的级别太少 而且
  • Cakephp - CSRF 令牌不匹配

    我在 Cakephp 3 6 中有一个项目 其中 MessageController 中的 3 个操作由 Ajax 调用 但是 我有一个问题 当我向其中一个操作发送请求时 XHR 会向我返回以下内容 message CSRF token m
  • 带有 .htaccess 的漂亮网址?

    我刚刚创建了一个新的 WordPress 页面模板 在其中运行一些 php mysql 脚本 我想对其子页面应用 mod 重写 例如我生成了以下链接 http www quotist com quotes by authors html l
  • java中的回调是什么[重复]

    这个问题在这里已经有答案了 可能的重复 什么是回调函数 https stackoverflow com questions 824234 what is a callback function 我已经阅读了回调的维基百科定义 但我仍然没有明

随机推荐

  • 如何添加执行 Django 管理操作来更改表单页面的自定义按钮?

    我已经为我的模型定义了一个自定义管理操作 它按预期完美运行 我还研究了向管理员更改表单页面添加按钮的多种方法 我缺少的唯一步骤是如何使更改表单页面中的按钮使用当前对象执行我的自定义管理操作 目标是允许管理员单独检查每个对象并对它们执行操作
  • SwipeRefreshLayout + 另一个视图

    我的布局设置如下
  • 有没有办法防止 JavaScript/jQuery 中的元素失去焦点?

    focusout blur 事件仅在元素失去焦点后触发 顺便说一句 我更喜欢不使用插件来做到这一点 是的 你可以使用这个
  • Firebase 扇出 - 最具成本效益的方法?

    我知道这个问题可能已被多次提出 但我已阅读了大多数可用的问题 但没有找到任何可以完全帮助回答我的问题的问题 正如 Firebase 团队提出的 扇出技术是确保快速数据读取的推荐方法 但会带来数据复制的成本 我知道这个问题是主观的 取决于应用
  • 您最喜欢的 SVN Web 应用程序部署工作流程是什么?

    我们目前使用的部署设置有些复杂 涉及远程 SVN 服务器 用于 DEV STAGE 和 PROD 的 3 个 SVN 分支 通过补丁等在它们之间提升代码 我想知道在小型开发团队的情况下您使用什么进行部署 主干用于开发 分支 生产 用于生产
  • 将 MultiIndex 列合并到 pandas 数据框中的单个索引

    在我的代码中 我将 2 个数据库集成到 1 个数据库中 问题是当我向数据库中再添加一列时 结果与预期不符 使用Python 2 7 code import pandas as pd import pandas io formats exce
  • laravel 会话返回 null 尽管设置它

    只是原生 php 中的一个简单函数 protected function some function session start if isset SESSION a SESSION a some value return true els
  • 如何让我的班级充满活力?

    我想要一个带有一个附加属性的字符串 比如说是以红色还是绿色打印它 子类化 str 不起作用 因为它是不可变的 我看到了它的价值 但它可能很烦人 多重继承有帮助吗 我从来没有用过那个 仅继承 object 并使用 self value str
  • 什么可能导致 imagecolorsforindex() 出现“颜色索引超出范围”错误?

    当对一大堆 JPG PNG 和 GIF 文件进行补丁大小调整时 PHP 意外地死机 并显示以下错误消息 imagecolorsforindex function imagecolorsforindex 颜色索引 226 超出范围 相关代码片
  • AspectJ - 更改方法参数的值

    我想要这样的东西 public void doSomething ReplaceFooBar String myString ReplaceFooBar是我的自定义注释 其值应为myString并做一个replaceAll在方法开始执行之前
  • PipEnv:如何处理本地安装的 .whl 包

    我正在使用 PipEnv 设置一个项目 以及一些我需要从预编译的二进制文件安装的包 在以前的项目中 我只是将某些本地文件夹中的 whl 文件安装到我的环境中 但这似乎会导致锁定文件出现问题 如果其他人尝试从存储库安装 因为 pipfile
  • 使用 -NoExit 启动 PowerShell 不起作用

    需要在 PowerShell 中启动多个作业 但它们应该位于不同的会话中 因此 要启动一个 可以使用 Start Process powershell ArgumentList command Get Process noexit nopr
  • 在 woocommerce 结帐页面自定义字段中添加日期

    我正在尝试在 woocommerce 结帐页面中添加自定义选择选项 它正在添加额外的字段 但我想在选择选项的值中添加日期 有什么解决办法吗 这是我在主题 function php 中添加的代码 today new DateTime tomo
  • tfs:如何解锁更改

    我最初编辑了一个文件 该文件进行了结帐 我收到了一台新电脑 现在我想编辑该文件 我不关心原始编辑 TFS 报告另一个用户对该文件具有独占锁定 它实际上不是另一个用户 而是我 但机器不同 因此工作空间不同 我尝试使用以下命令通过 tf 命令行
  • 在海量数据集上学习决策树

    我正在尝试使用 MATLAB 从巨大 即无法存储在内存中 数据集构建二元分类决策树 本质上 我正在做的是 收集所有数据 Try out n数据的决策函数 选出最佳决策函数 https stackoverflow com questions
  • 为不受支持的语言选择本地化

    我有 en 和 ru 语言的本地化 如果用户选择任何其他语言 fr de 我需要显示俄语本地化变体 我尝试将 info plist 中的 本地化本机开发区域 更改为 ru 俄语 但在使用不受支持的语言时 它始终显示英语 有相关问题 http
  • iFrame 内的 cordova 回调

    我使用 cordova 和 nanohttpd 创建了一些 Android Web 应用程序 主页是通过 localhost url 从 nanohttp 加载的 主页包含一个 iFrame 它从与主页相同的域 localhost 加载一些
  • 将 nd 数组转换为键、值字典

    python中是否有一个函数可以将nd数组转换为字典 其中key是索引元组 value是该索引处的矩阵值 例如 A np random random 3 4 5 Result i j k A i j k 当然 你可以使用np ndenume
  • 在 iPhone SDK 中实现 Core-Plot 时出现错误:“CorePlot-CocoaTouch.h:没有这样的文件或目录”

    当我尝试在 iPhone 应用程序中实现 Core Plot 时 出现以下错误 CorePlot CocoaTouch h 没有这样的文件或目录 我从下面的链接下载安装了 Core plot 包 http code google com p
  • 通过电子邮件将 Sparkline 图表作为 Google Sheets 范围内的图像/博客/png 发送

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