我建议将公式直接放入电子表格中,而不是通过脚本插入公式。这将大大简化您的代码。
我采用了你的公式并添加了一些元素:
1 - 将 AF 列转换为在发送电子邮件时更新的列。
2 - 添加了“状态”列(可能是 AG 列??)。这就是公式的所在。
3 - 将公式转换为ARRAYFORMULA。请注意,公式中的每个范围都包含一整列(例如 I2:I)。这也需要将AND 替换为“*”,将OR 替换为“+”。请参阅下面的说明。
4 - 添加了ARRAY_CONSTRAIN,以便仅在添加新数据行时添加公式。如果这不在这里,那么公式将显示在工作表底部的每一行列中 - 看起来不是很好,而且有点令人反感。
=ARRAY_CONSTRAIN(ArrayFormula(if(M2:M="EMAIL SENT","EMAIL SENT",IF(((I2:I="YOUR TRIP DWL")+(I2:I="MEGA PACK DWL (YT + AA + BONUS)"))*(J2:J<=0)*(K2:K<>"")*(L2:L<>""), "Send Email", "Wait"))),COUNTA(I2:I),1)
这是我的布局和公式结果的屏幕截图。
逻辑是这样的:
检查 M 列(您的 AF 列)。评估是否已发送电子邮件。如果是,则什么也不做;如果不是,则评估是否该发送电子邮件。
-
如果尚未发送电子邮件,则评估某些字段的状态。
显示公式结果的行数由ARRAY_CONSTRAIN 和参数COUNTA(I2:I) 控制。这会计算第 I 列(您的第 I 列)中包含内容的行数。选择此列是假设 L 列中始终存在一个值。如果不是这种情况,则选择另一个始终包含内容的单元格/列。如果您选择具有数值的单元格/列,则可能需要将 COUNTA 更改为 COUNT。
ARRAYFORMULA 公式只输入一个单元格(相当于“状态”列中的单元格 AG2)。 ARRAYFORMULA 逐行计算公式并自动在列的每一行中显示结果。 ARRAY_CONSTRAIN 约束结果;在我们的例子中,它仅限于那些有值的行。
IF 语句中的 AND 和 OR 发生了什么?
请注意,IF 语句实际上并不包含AND 和OR 函数。显然,它们对ARRAYFORMULA 产生了无效的影响。但要归功于Max Makhrov in "Google Sheets ARRAYFORMULA with nested if statements" 他建议的地方。
Replace AND with * and OR with +
对代码的影响
您的代码应该循环并评估“状态”列。
如果值为“发送电子邮件”,则发送电子邮件并将“状态”列更新为“电子邮件已发送”。否则,什么也不做。
更新:代码更改
这是符合建议公式的代码。该代码是自我记录的,并且相当容易遵循。大致流程如下。
1 - 允许用户变量
2 - 远程打开电子表格
3 - 计算数据的行数
4 - 按行循环遍历数据
5 - 如果单元格值 = "Send Email",则发送电子邮件,并使用 "EMAIL SENT" 更新相邻列的值
function so_52680239() {
// Declare user variables
// SpreadsheetID
var ResultsSheetID = "1Iz-qmOnzZp4EAmGzWJORNpJGkueYzGFUTkpUZ9g3-as";
// SheetName
var SheetName = "Results";
// Column letter for the Status Column
var StatusColumnLetter = "N";
// Start row for the Status Column
var StatusHeaderRow = 1;
// open the Results Spreadsheet
// Supply the ID
var ResultsSheet = SpreadsheetApp.openById(ResultsSheetID);
var Results_ss = ResultsSheet.getSheetByName(SheetName);
// Convert the column letter for Status Column to a number
var StatusColumnNumber = letterToColumn(StatusColumnLetter);
//Logger.log("StatusColumnNumber = "+StatusColumnNumber);
// Create a string variable range for the Status Column
var StatusStartRange = StatusColumnLetter+StatusHeaderRow+":"+StatusColumnLetter;
//Logger.log("StatusStartRange = "+StatusStartRange);
// Get the last row with content in the StatusColumn
var LastRowvals = Results_ss.getRange(StatusStartRange).getValues();
var LastDataRow = LastRowvals.filter(String).length;
//Logger.log('Last row = '+LastDataRow);
// declare the search range
var searchRange = Results_ss.getRange(StatusHeaderRow+1,StatusColumnNumber, LastDataRow-1);
//var searchRangeA1 = searchRange.getA1Notation();
//Logger.log('searchRangeA1 = '+searchRangeA1);
// Get array of values in the search Range
var rangeValues = searchRange.getValues();
// Loop through array and if condition met, send email
// Note, only one column of data so no looping by column
for ( j = 0 ; j < LastDataRow - 1; j++){
if(rangeValues[j][0] === 'Send Email'){
// do stuff
// insert code to send email
//Logger.log("j = "+j+", value = "+rangeValues[j][0]+", so Send Email");
// Update your Column AF (one column to the left of the formula results column) with "EMAIL SENT"
Results_ss.getRange(StatusHeaderRow+1+j,StatusColumnNumber).offset(0, -1).setValue('EMAIL SENT');
}else {
// do Nothing
//Logger.log("j = "+j+", value = "+rangeValues[j][0]+", so do nothing");
};
};
}
//Utility to convert a column letter to a column number
function letterToColumn(letter)
{
var column = 0, length = letter.length;
for (var i = 0; i < length; i++)
{
column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
}
return column;
}
屏幕截图 - 运行代码之后。注意记录#2 已更新。
学分:
yagisanatode.com 获取快速/高效的数据更新方式:Google Apps Script – Iterating Through Ranges in Sheets the Right and Wrong Way
纯代码解决方案
如果无法为公式手动更新电子表格,脚本可以执行相同的任务。
假设:I 列始终包含数据;这用于计算要处理的数据行数。
Provisio:如果在运行脚本时,AF2 中的相关单元格为空,则将在该单元格中插入公式。然后该公式将评估数据,结果可能是它显示“发送邮件”值。但是,没有规定可以在同一更新例程中发送邮件。
我会留给提问者来决定他们如何选择处理这件事。
function so_52680239_02() {
// Declare user variables
// SpreadsheetID
var ResultsSheetID = "1ILmQ5cAwRD0Va0lPKcAhr7OTvwLaX_UtFCJ8EEL4TwM";
// SheetName
var SheetName = "Results01";
// Column letter for the Status Column
var StatusColumnLetter = "M";
// Start row for the Status Column
var StatusHeaderRow = 1;
// Column letter for the TripType (assume that there is always data in this cell)
var TripTypeColumnLetter = "I";
// open the Results Spreadsheet
// Supply the ID
var ResultsSheet = SpreadsheetApp.openById(ResultsSheetID);
var Results_ss = ResultsSheet.getSheetByName(SheetName);
// Convert the column letter for Status Column to a number
var StatusColumnNumber = letterToColumn(StatusColumnLetter);
// Logger.log("StatusColumnNumber = "+StatusColumnNumber); //DEBUG
// Convert the column letter for Trip Type Column to a number
var TripTypeColumnNumber = letterToColumn(TripTypeColumnLetter);
// Logger.log("TripTypeColumnNumber = "+TripTypeColumnNumber);// DEBUG
// Create a string variable range for the Status Column
var StatusStartRange = StatusColumnLetter + StatusHeaderRow + ":" + StatusColumnLetter;
// Logger.log("StatusStartRange = "+StatusStartRange); // DEBUG
// Create a string variable range for the Trip Type Column
var TripTypeRange = TripTypeColumnLetter + StatusHeaderRow + ":" + TripTypeColumnLetter;
// Logger.log("TripTypeRange = "+TripTypeRange); // DEBUG
// Get the last row with content in the Trip Type Column
var TripLastRowvals = Results_ss.getRange(TripTypeRange).getValues();
var TripLastDataRow = TripLastRowvals.filter(String).length;
// Logger.log('Last trip row = '+TripLastDataRow);// DEBUG
// Define the formula
var myformula = '=IF(((AND(OR(I' + row + '="YOUR TRIP DWL",I' + row + '="MEGA PACK DWL (YT + AA + BONUS)"),M' + row + '<=0,AA' + row + '<>"",AE' + row + '<>""))), "Send Email", "Wait")';
// declare the search range in Column AF
var searchRange = Results_ss.getRange(StatusHeaderRow + 1, StatusColumnNumber, TripLastDataRow - 1);
// Logger.log('searchRange = '+searchRange.searchRangeA1); //DEBUG
//Get array of values in the search Range
var rangeValues = searchRange.getValues();
//Logger.log("rangevalues = "+rangeValues)
// establish some variablkes for use in the loop
var emailformula = "";
var emailformularange = "";
// loop for email formula
for (var row = 0; row < TripLastDataRow - 1; row++) {
if (rangeValues[row][0] == "") {
// cell is empty, insert formula
emailformula = '=IF(((I' + (row + 2) + '="YOUR TRIP DWL")+(I' + (row + 2) + '="MEGA PACK DWL (YT + AA + BONUS)"))*(J' + (row + 2) + '<=0)*(K' + (row + 2) + '<>"")*(L' + (row + 2) + '<>""), "Send Email", "Wait")';
emailformularange = '' + StatusColumnLetter + (row + 2) + ''
var rangeList = Results_ss.getRangeList([emailformularange]);
rangeList.setFormula(emailformula);
//Logger.log("row = "+row+", value = "+rangeValues[row][0]+", Action: Cell is empty, so insert formula in "+emailformularange);//DEBUG
} else if (rangeValues[row][0] == "EMAIL SENT") {
//do nothing
//Logger.log("row = "+row+", value = "+rangeValues[row][0]+", Action: Email already sent so do nothing"); // DEBUG
} else if (rangeValues[row][0] == "Wait") {
//do nothing
//Logger.log("row = "+row+", value = "+rangeValues[row][0]+", Action: Wait, so do nothing"); //DEBUG
} else if (rangeValues[row][0] == "Send Email") {
// Send mail
emailformularange = '' + StatusColumnLetter + (row + 2) + ''
Results_ss.getRange(emailformularange).setValue('EMAIL SENT');
// Logger.log("row = "+row+", value = "+rangeValues[row][0]+", Action: Send Mail and update cell "+emailformularange+" to 'EMAIL SENT'"); //DEBUG
}
}
}