在单元格公式计算完毕后,在Google表单提交上发送电子邮件

时间:2016-03-11 18:15:57

标签: google-apps-script google-sheets google-apps

我正在制作一个在提交Google表单时发送电子邮件的脚本。表单包含与设备租赁相对应的复选框。数据从表单中获取并发送到Google电子表格,电子表格根据用户选择的设备计算租赁价格。

一切都很好,电子邮件会根据需要填写数据,但总价格总是空的。

电子表格正在进行所有繁重工作,以确定要添加到总数中的设备成本,并且价格单元每次都填写正确的价格 - 它只是不会发送到电子邮件。

我熟悉JavaScript,但只是学习Google Scripts,因此可能还有其他优化领域,但我的问题是如何在单元格公式完成之前延迟sendEmail函数?

这是我的原始剧本:

function sendFormByEmail(e){  
  var sheet =   SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Totals for Email');
  var ss = SpreadsheetApp.getActive();  

  //Note: tried a sleep and flush here (see paragraph below)      

  var price = ss.getRange("K" + lastDataRow()).getValues();

  //Note: tried while loop here (see paragraph below)

  var email = "email@address.com";
  var s = SpreadsheetApp.getActiveSheet();
  var headers = s.getRange(1, 1, 1, s.getLastColumn()).getValues()[0];  
  var subject = "Rental Form: " + e.namedValues[headers[1]].toString() + " " + e.namedValues[headers[2]].toString();

  //Loop through the array and append values to the message.
  var message = "";
  for ( var i in headers ){
    message += e.namedValues[headers[i]].toString() + "\n";
  }  
  message += "Total: $" + price + "\n\n"; //This price is always empty in the received email (when the form is submitted). When running/debugging from the script, it has data.

  MailApp.sendEmail(email, subject, message); // Send the email
}
function lastDataRow(){
  var spr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Totals for Email');
  var column = spr.getRange('A:A');
  var values = column.getValues();
  var ct = 0;
  while ( values[ct][0] != "" ){
    ct++;
  }

  return (ct);
}

我尝试添加一个sleep Utilities.sleep(10000);和一个flush SpreadsheetApp.flush();,并在while循环中使用这两个来专门检查price cell。我知道while循环也有效,因为它从脚本本身成功运行(只是不在表单提交上)。

count = 0;
while ( price == 0 ){ //This while loop doesn't work either!
  if ( count >= 3 ){
    price = "Unknown Price"; //Set to unknown if loop was unsuccessful
    break; //Leave the while loop after 3 attempts.
  }
  Utilities.sleep(10000); //Delay for 10 seconds @todo: did not allow the formula to run first...
  SpreadsheetApp.flush(); //Let the spreadsheet finish calculating before continuing. @todo: this didn't work either...
  price = ss.getRange("K" + lastDataRow()).getValues(); //Recapture cell data after the delay.
  count++;
}

如果可能的话,我想避免在脚本中执行所有计算。任何想法将不胜感激!

1 个答案:

答案 0 :(得分:0)

您可以设置if(), else()条件,检查单元格中是否存在包含最终价格的值。您可能遇到问题,因为即使在有可见数据之前,单元格也包含公式。

您最好的选择是在时间触发器上运行您的功能,并且只有在某个单元格充满可见数据时才执行您需要的代码。要检查的简单单元格是时间戳,因为该单元格不涉及公式。如果时间戳已填满,则您的代码将执行最终数学而不是工作表,并将该变量数据用于电子邮件。然后,您的代码也可以将该价格写回工作表。

或者,您可以编写两个都具有时间触发器的代码。其中一个会将值写入不包含公式的单元格。这可能是价格或其他功能将由if(), else()检查并执行大部分代码的任何内容。