Performance 如何减少此Google Apps脚本的执行时间?
我编写了一个脚本,从电子表格中获取一行数据,并在其中循环,如果行的数据满足某些条件(例如有电话号码但尚未发送),则调用函数发送SMS 然而,在添加了大约600行之后,脚本执行时间超过了它的限制,根据我的研究,这似乎是5分钟。我使用JavaScript对象读取数据,使用for循环遍历行 如果可以加快速度,有人能告诉我吗?我对编程非常陌生,但对于所有这些计算能力来说,这似乎是一项很轻的任务,我不明白为什么需要这么长时间 提前谢谢 下面是我正在使用的函数的代码:Performance 如何减少此Google Apps脚本的执行时间?,performance,google-apps-script,Performance,Google Apps Script,我编写了一个脚本,从电子表格中获取一行数据,并在其中循环,如果行的数据满足某些条件(例如有电话号码但尚未发送),则调用函数发送SMS 然而,在添加了大约600行之后,脚本执行时间超过了它的限制,根据我的研究,这似乎是5分钟。我使用JavaScript对象读取数据,使用for循环遍历行 如果可以加快速度,有人能告诉我吗?我对编程非常陌生,但对于所有这些计算能力来说,这似乎是一项很轻的任务,我不明白为什么需要这么长时间 提前谢谢 下面是我正在使用的函数的代码: // Will send SMS on
// Will send SMS on the currently active sheet
function sendSms() {
// Use the send sms menu to trigger reconcile
var user = ScriptProperties.getProperty(PROPERTY_USER_RECONCILE);
if (user == null)
reconcileUser();
// The sheets
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Registo");
var settingsSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");
// Fetch values for each row in the Range.
var startRow = 2;
var apiKey = settingsSheet.getRange("B2").getValue();
var apiSecret = settingsSheet.getRange("B3").getValue();
var prefix = settingsSheet.getRange("B4").getValue();
var numRows = sheet.getMaxRows() - 1;
var numCols = 16;
var statusColNum = 15; // IMPT: To keep track status in col 15
var dataRange = sheet.getRange(startRow, 1, numRows, numCols);
// Make sure there is API key and secret
if (apiKey == "" || apiSecret == "") {
Browser.msgBox("You MUST fill in your API key and secret in Settings sheet first!");
return;
}
// Create one JavaScript object per row of data.
var objects = getRowsData(sheet, dataRange);
var totalSent = 0;
for (var i = 0; i < objects.length; ++i) {
// Get a row object
var rowData = objects[i];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getSheetByName("SMS Modelo");
var template = templateSheet.getRange("A1").getValue();
// jump loop iteration if conditions not satisied
if (rowData.resolv == "x" || rowData.contactoUtente == null || rowData.contactoUtente == "" || rowData.reserv == null || rowData.reserv == "" || rowData.cont == "x" || rowData.sms !== null) continue;
var message = fillInTemplateFromObject(template, rowData);
var senderName = "Farm Cunha"
var mobile = rowData.contactoUtente;
// Send via Nexmo API
var response = nexmoSendSms(apiKey, apiSecret,"+351" + mobile, message, senderName);
if (response.getResponseCode() == 200) {
var object = JSON.parse(response.getContentText());
if (object.messages[0]['status'] == "0") {
// Set to QUEUE status - We assumed SENT, as we don't handle delivery status.
//sheet.getRange(startRow + i, statusColNum).setValue(STATUS_QUEUE);
sheet.getRange(startRow + i, statusColNum).setValue(STATUS_SENT);
// Set the reference id
sheet.getRange(startRow + i, 19).setValue(object.messages[0]['message-id']);
// sheet.getRange(startRow + i, statusColNum+3).setValue(new Date()); linha pode ser activada para fazer timestamp do envio
totalSent++;
}
else {
// If status is not 0, then it is an error.
// Set status to the error text
sheet.getRange(startRow + i, statusColNum).setValue(object.messages[0]['error-text']);
}
}
else {
// Non 200 OK response
sheet.getRange(startRow + i, statusColNum).setValue("Error Response Code: " + response.getResponseCode);
}
SpreadsheetApp.flush();
// Need a wait. Need to throttle else will have "Route Busy" error.
Utilities.sleep(2000);
}
// Update total sent
var lastTotalSent = parseInt(ScriptProperties.getProperty(PROPERTY_SMS_SENT_FOR_RECONCILE));
if (isNaN(lastTotalSent)) lastTotalSent = 0;
ScriptProperties.setProperty(PROPERTY_SMS_SENT_FOR_RECONCILE, (lastTotalSent + totalSent).toString());
Logger.log("Last sent: " + lastTotalSent + " now sent: " + totalSent);
reconcileApp();
}
//将在当前活动工作表上发送SMS
函数sendSms(){
//使用发送sms菜单触发协调
var user=ScriptProperties.getProperty(属性\用户\协调);
if(user==null)
协调者();
//床单
var sheet=SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“注册表”);
var settingsSheet=SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“设置”);
//获取范围中每行的值。
var startRow=2;
var apiKey=settingsSheet.getRange(“B2”).getValue();
var apiSecret=settingsSheet.getRange(“B3”).getValue();
var prefix=settingsSheet.getRange(“B4”).getValue();
var numRows=sheet.getMaxRows()-1;
var numCols=16;
var statusColNum=15;//导入:跟踪列15中的状态
var dataRange=sheet.getRange(startRow,1,numRows,numCols);
//确保有API密钥和密码
如果(apiKey==“”| | apiSecret==“”){
msgBox(“您必须先在设置表中填写API密钥和密码!”);
返回;
}
//每行数据创建一个JavaScript对象。
var objects=getRowsData(表,数据范围);
var totalSent=0;
对于(变量i=0;i
您的循环中有一些东西太耗时:电子表格读取和API调用+2秒睡眠
很明显,我建议您将这些从循环中删除(特别是模板页阅读,它们总是相同的!)。一个可能的解决方案是检查行对象的条件,并将有效条目保存在数组中。。。然后在此数组中迭代以调用API
如果这仍然太长,则分小批进行,在scriptproperties中保存部分迭代的结束位置,并使用计时器触发器,该触发器将每5分钟继续一次过程,直到完成(并在结束时终止触发器)
在这个论坛上有一些关于这种“机制”的例子,我最近提出的一个例子是(这更像是一个草稿,但想法在那里)好的,我已经解决了这个问题,从循环中取出这3行代码,正如Serge(谢谢)告诉我的:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getSheetByName("SMS Modelo");
var template = templateSheet.getRange("A1").getValue();
这是如此简单,我不知道我怎么没有看到
这个简单的更改使脚本更快。例如,浏览600行需要5分钟以上。现在,5000多行只需几秒钟。非常感谢Serge。我认为在数组中保存有效条目对我来说是一个更好的选择。我认为其他的选择不会很有效。这是因为这个电子表格将被不懂技术的人以非常特殊的方式使用。另外,我也不确定如何实现它们,因为我是编程新手:)2秒睡眠似乎是API的一个要求。。。不过我不确定。将进行测试。