【问题标题】:Sending stock alert emails using google apps script使用谷歌应用程序脚本发送股票警报电子邮件
【发布时间】:2018-09-02 19:30:54
【问题描述】:

我正在尝试设置一个简单的谷歌应用程序脚本,以在各种组件的库存达到定义的阈值时发送电子邮件。在阅读和搜索之后,我编写了一个脚本,该脚本似乎可以工作,但当我增加从电子表格中提取的范围时,它开始发送错误的电子邮件。

这是我的代码,更多详细信息如下。

var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Inventory Report");
var howFar = 5 //sheet.getMaxRows(); // how many rows of data
var onHand = sheet.getRange(2,14,howFar,1).getValues();
var minimum = sheet.getRange(2,16,howFar,1).getValues();
var itemNum = sheet.getRange(2,1,howFar,1).getValues();
var itemName = sheet.getRange(2,2,howFar,1).getValues();

var sendTo = "test@gmail.com";
var overStock = 1.5;  // warning factor over minimum

function stockAlert() {
  for (var i = 0; i < onHand.length; i++) { 
    if (onHand[i] < minimum[i] * overStock && onHand[i] > minimum[i]) {
        MailApp.sendEmail( sendTo , "Testing Stock Reorder Notifications", itemNum[i] + " " + itemName[i] +" - Stock is low! Current stock is " + onHand[i] + ". Minimum is " + minimum[i] + ".");
    }
    else if (minimum[i] > 0 && onHand[i] < minimum[i]) {
        MailApp.sendEmail( sendTo , "Testing Stock Cirtical Notifications", itemNum[i] + " " + itemName[i] +" - Stock is Critical and will be depleted! Current stock is " + onHand[i] + ". Minimum is " + minimum[i] + ".");
    } 
  }
}

在我的工作表中,最小值为 200、400、200、300、600
在我的工作表中,onHand 的值为 270、270、920、920、1830

这意味着我应该看到第一组值的一封低库存电子邮件,第二组值的一封重要库存电子邮件,最后 3 组值的电子邮件没有。

如果是var howfar = 3,脚本会发送两封相应的电子邮件。 如果var howfar = 5,我会收到第三封关于不应该发送的第五组值的关键股票电子邮件。有趣的是,电子邮件正文显示它引用了正确的值集,但 else if 应该是错误的。

错误电子邮件的正文为:

itemNum itemName - 库存很严重,即将耗尽!当前库存为 1830。最低为 600。

鉴于我在不编码方面的广泛背景,我希望并假设这将是一个简单的修复,但非常感谢任何所有帮助!

【问题讨论】:

  • 如果你愿意,你能分享一个测试电子表格吗?我会在电子表格的聊天中看到你的情况。
  • 顺便说一句,你的代码看起来还不错,真的很奇怪
  • @JSmith 我设置了一张测试表。我刚刚粘贴了原始工作表中的结果值。测试脚本时我得到相同的结果。 docs.google.com/spreadsheets/d/…

标签: google-apps-script google-sheets


【解决方案1】:

这些值是否有可能在电子表格中被视为文本?请注意,字符串"1830" 确实是&lt; 字符串"600"。如果它们是电子表格中的文本(而不是数字),那么当 Apps 脚本读取其中的值时,它们将保留为 Strings。

编辑:确实,这是您问题的根源 - 您在 Array 级别比较二维数组:

Logger.log(minimum[i]); // "[600.0]"
Logger.log(typeof minimum[i]); // object

Logger.log(minimum[i][0]); // 600.0
Logger.log(typeof minimum[i][0]); // number

最简单的解决方法是简单地访问二维数组的所需元素。由于您只获取了单列,因此每个内部数组中只有 1 个元素(在索引 0 处)。因此,&lt;array&gt;[i][0] 而不是 &lt;array&gt;[i]

对此的扩展(适用于工作表值可能是文本的情况)是在使用 JS 函数 parseInt(val, radix) 进行比较之前显式转换为数字。假设 minimum 和其他是二维数组,因为它们在您的问题代码中:

for (var i = 0; i < onHand.length; i++) {
  var min = parseInt(minimum[i][0], 10),
      avail = parseInt(onHand[i][0], 10);
  if (avail < min) {
    // send critical stock email
  }
  else if (avail < min * overStock) {
    // send reorder email
  }
  else {
    // on hand amount is > needed
  }
}

对于一个空白字符串,例如parseInt("", 10) 或其他非数字输入,返回值是数字 NaN,它既不是 &gt; 也不是 &lt;,而不是实际数字,因此错误的输入不应导致发送电子邮件。


另一个问题是您的脚本使用接口调用填充全局变量,这会导致 any 脚本的执行速度变慢。更好的方法是将相关设置包装在一个函数中:

function getStockAmounts() {
  // Return an object of the inventory values.
  const stock = SpreadsheetApp.getActive().getSheetByName("some name");
  const numHeaders = 1,
        numVals = stock.getLastRow() - numHeaders;
  return [
    {p: 'minimum', col: 16},
    {p: 'onHand', col: 14},
    {p: 'itemName', col: 2},
    {p: 'itemNum', col: 1}
  ].reduce(function (obj, key) {
    obj[key.p] = stock.getRange(numHeaders + 1, key.col, numVals, 1)
      .getValues()
      // Return a 1-D array, rather than a 2-D array, since all these are single-column variables.
      .map(function (row) { return row[0]; });
    return obj;
  }, {'numVals': numVals});
}

然后从您的脚本中调用它:

function foo() {
  const stocks = getStockAmounts();
  for (var i = 0; i < stocks.numVals; i++) {
    var min = stocks.minimum[i]; // 1D arrays, so only 1 index is needed.
    ...

【讨论】:

  • 做得好之前应该有过。他也可以使用Number(string)function
  • onHand 已经定义好了,所以我使用了onH 并且它起作用了。谢谢!
  • @MicahRoth 哎呀,错过了。请注意,数组比较与元素比较存在一个基本问题 - getValues 返回一个“二维”数组,而不是一维数组。
  • @tehhowch 感谢您提供更多信息!太多东西要学
猜你喜欢
  • 2012-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-22
  • 2013-11-15
  • 2015-01-28
相关资源
最近更新 更多