我正在尝试设置一个简单的Google Apps脚本,以在各种组件的库存达到定义的阈值时发送电子邮件。阅读和搜索后,我整理了一个脚本,该脚本似乎可以正常工作,但是当我增加从电子表格中提取的范围时,就开始发送错误的电子邮件。
这是我的代码,下面是更多详细信息。
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
这意味着我应该在第一组值中看到一封低库存电子邮件,在第二组值中看到一封关键库存电子邮件,而后三组值则没有电子邮件。
如果为var howfar = 3
,脚本将发送两封适当的电子邮件。
如果为var howfar = 5
,我将收到第三封重要股票电子邮件,其中包含不应发送的第五组值。有趣的是,电子邮件正文显示它正在引用正确的值集,但是else if
应该为假。
不正确的电子邮件正文显示为:
itemNum
itemName
-库存至关重要,库存将耗尽!当前库存为1830。最小值为600。
鉴于我在编码方面的广泛背景,我希望并认为这将是一个简单的解决方法,但是所有帮助将不胜感激!
答案 0 :(得分:2)
是否有可能在电子表格中将值视为文本?请注意,字符串"1830"
确实是<
字符串"600"
。如果它们是电子表格中的文本(而不是数字),则当Apps Script读取其中的值时,它们将保留为String
。
编辑:的确,这就是问题的根源-您在Array
级别比较2D阵列:
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
然后,最简单的解决方法是简单地访问2D数组的所需元素。由于您仅获取单列,因此每个内部数组(索引为0)只有1个元素。因此,用<array>[i][0]
代替了<array>[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
,它既不是>
也不是<
,而不是实际数字,因此错误的输入不应导致产生电子邮件被发送。
另一个问题是您的脚本会使用接口调用填充全局变量,这会导致 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.
...