编辑#2:
我决定尝试对所有电子邮件发出后运行的复制粘贴操作进行批处理。在之前发布的代码中,在每个循环的最后几行中,我将每个采购订单(“电子邮件”表)中的项目复制并粘贴到另一个(“AsignRec”)中。现在,我想做的是将每个循环中“Email”表中的项目存储到 Javascript 数组中,然后将所有内容粘贴到最后的“AsignRec”中,只需一次。
但是,我还是没有做对。我陷入了最后的粘贴/setValues()。我相信该数组的格式正确,因为它的长度为 49,这是发送给 vendor 的唯一 SKU 的数量。尽管如此,在 setValues([OCitems]) 第 185 行,我收到错误“范围高度不正确,为 1,但应该为 49(第 185 行,文件“TestArrayMultiple4”)”。
我认为这意味着目标/输出范围与数组/输入(称为 OCitems)的大小不同。但我不明白为什么,因为我使用 OCitems.length 定义了输出范围的长度。我错过了一些东西,但不确定是什么。
这是代码的重要部分,完整代码如下。与之前相同的 GDocs 链接,脚本文件 TestArrayMultiple4,第 160-185 行。 https://docs.google.com/spreadsheets/d/1yzvMTh0VYhRhiexNzQPIjTwz1FCMq4XnbpGvCF1FYu8/edit#gid=436022027
/// Get Range we want to change to creating Javascript array and paste at end only
var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow).getValues(); // get items to send to supplier from "Email Sheet"
// if supplier number is 1, create array "OCitems" by storing OcNoHeader. If not supplier #1, then append to existing array "OCitems"
if(y == 1){
var OCitems = OcNoHeader}
else
{for(j=0;j<OcNoHeader.length;j++){
OCitems.push(OcNoHeader[j]);
}}
Logger.log(OCitems);
Logger.log("OCitems length = " + OCitems.length)
debugger;
i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);
Logger.log("new i ELSE =" + 1)
debugger;
} // only do while x = max number of suppliers reached
while (i < x);
sheet3.getRange(3, 3, OCitems.length, 9).setValues([OCitems]); // paste operation, NumRows set equal to length of array
==========================
编辑#1:致力于使用多个单元格的 getValues 来提高性能,而不是多次执行单独的 getValue() 。 不幸的是,这并没有以稳定或明显的方式减少执行时间(有时在 6 分钟前完成,有时则不然)。
在下面发布代码(您可以在下面共享的新工作表中的脚本文件“TestArrayMultiple2”中访问它):
使用执行记录,我发现虽然之前花费很长时间的 getValue() 行的执行时间基本上已减少到零,但其他代码行现在花费更多时间并消除了批处理所获得的 yield 其他 getValue()。
特定单元格上仍然有 4-5 个“单独”getValue()(比以前少得多),但我不明白为什么它们会花费这么长时间。如此看来,即使我去掉了剩下的“个别”getValue(),如果只剩下一个的话,需要的时间会更长。
在我看来,它与缓存有关(我确信我没有完全理解这个概念),原因如下: 1) 循环中的第一个 getValue() 总是花费最长的时间。 2)我尝试走不同的路线,通过更改所有电子邮件发送后发生的复制/粘贴操作的代码(“TestArrayMultiple2”脚本文件中的第150行)。我基本上尝试创建一个数组,该数组在每个循环(追加/推送方法)中获取更多数据,但不会在每个循环中粘贴 - 这个想法是在完成循环后将所有数据粘贴到最后。我仍然不正确(第二个脚本文件是最后一个,“TestArrayMultiple3”),但我可以看到电子邮件的发送速度要快得多。
再次感谢您的帮助。
> // version with 1 getDataRange array which stores for supplier ID, name, email, MaxTableRow for PO email, email subject all from Dashboard sheet
function TestArrayMultiple2() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var sheet = ss.getSheetByName("Email");
var sheet1 = ss.getSheetByName("Pedido email");
var sheet2 = ss.getSheetByName("Dashboard");
var sheet3 = ss.getSheetByName("AsignRec");
var sheet4 = ss.getSheetByName("ListadoProductos");
var sheet5 = ss.getSheetByName("Registro-Consolid");
var sheet6 = ss.getSheetByName("Registro-Unico");
var x = ss.getSheetByName("Dashboard").getRange("C4").getValue();
Logger.log("x = " + x)
var offsetV = 4; // number of rows of offset for email status to be inserted in Dashboard sheet
var OffSetColProv = 1; // column in Dashboard sheet with supplier name
var OffsetColMaxPOrows = 3; // Number of unique SKUs or rows in PO. Replace MaxTableRow formula in Email Sheet
var OffSetColPzas = 4; // column in Dashboard sheet with number of items in supplier purchase order.
var OffSetColEmail = 5; // column in Dashboard sheet with supplier email
var OffSetColCC = 13; // column in Dashboard sheet with supplier email CC
var OffSetColSubject = 14; // column in Dashboard sheet with supplier email Subject
var colStatus = 11; // column in Dashboard sheet where send status of email inserted -----> LEAVE AS IS FOR NOW, not an offset, is fixed, col. K = 11
var OffsetEmailRows = 8 // number of rows in Email sheet before the items in PO are shown
var ProvNumEmail = sheet.getRange(1,2); // Supplier number in email sheet used to refresh products in purchase order email via FILTER formula
var StatusRange = sheet2.getRange("K5:K100");
Logger.log("StatusRange = " + StatusRange)
var currentTime = new Date();
var timestamp = Utilities.formatDate(currentTime,'GMT-0600','dd/MM/yyyy HH:mm:ss');
Logger.log("timestamp = " + timestamp);
var ProvArray = sheet2.getRange("E5:S100");
var DashValues = ProvArray.getValues();
i = 0;
do {
var y = DashValues[i][0];
Logger.log("y = " + y)
ProvNumEmail.setValue(y); // set value of next supplier in Email sheet to load next purchase order products
// emails var here in order to update email value in IF email = ERROR condition and skip to else
var Prov = DashValues[i][OffSetColProv];
Logger.log("Prov = " + Prov);
var EmailSubject = DashValues[i][OffSetColSubject];
Logger.log("EmailSubject = " + EmailSubject)
var MaxTableRow = DashValues[i][OffsetColMaxPOrows] + OffsetEmailRows;
Logger.log("MaxTableRow = " + MaxTableRow)
var EmailTo = DashValues[i][OffSetColEmail];
Logger.log("EmailTo = " + EmailTo)
var EmailCC = DashValues[i][OffSetColCC];
Logger.log("EmailCC = " + EmailCC)
var Piezas = DashValues[i][OffSetColPzas];
Logger.log("Piezas = " + Piezas)
SpreadsheetApp.flush();
var name = "Petsy Compras - Juan Carlos León";
var ReplyToEmail = "compras@petsy.mx";
var email = EmailTo;
var subject = EmailSubject;
var name = name;
var replyTo = ReplyToEmail;
var Emailcc = EmailCC;
var schedRange = sheet.getRange("B7:J"+MaxTableRow);
var body = '<div>';
body += "Estimados," +'<br>' + '<br>';
body += "Envío la orden de compra, por un total de " + '<b>' + Piezas + " piezas." + '</b>' +'<br>' + '<br>';
body += "Favor de confirmar las existencias lo más rápidamente posible, dentro del mismo correo y"+ '<b><a style="color:#FF0000">'+ " enviar factura a: "+ '</a></b>' + "facturasproveedores@petsy.mx." +'<br>' + '<br>';
body += "Al dar " +'<b><a style="color:#FF0000"> '+ "RESPONDER A TODOS" + '</a></b>' +" la tabla con los productos pedidos se hace editable: favor de marcar por cada item si será faltante." +'<br>' + '<br>';
body += "Cualquier duda avísenme por favor." +'<br>' + '<br>';
body += "Un saludo" +'<br>' + '<br>';
body += '<b>' + "Juan Carlos León" + '<b>' + '<br>';
body += "Petsy Compras"+'<br>';
body += "Mapa aquí: "+'<br>';
body += "Fijo directo 1: (55) 68 12 07 97 / Fijo directo 2: (55) 68 12 07 99 / Cel y Whatsapp: 55 32 23 57 17"+'<br>' + '<br>';
body += "" +'<br>' + '<br>';
body += getHtmlTable(schedRange);
body += '</div>';
// variables for error email
var emailERR = 'oscialom@petsy.mx'
var subjectERR = 'ERROR ENVIO OC' + ' // ' + Prov + ' ' + timestamp
if(email == 'ERROR' || MaxTableRow == 0) // skip condition to go begin loop with y+1
{
// if above skip condition is true, y+1 to move to next purchase order
Logger.log("y = " + y);
Logger.log("IF");
sheet2.getRange(y + offsetV,colStatus).setValue('NOT_SENT'); // set email send status next to supplier in Dashboard sheet
{
GmailApp.sendEmail(emailERR, subjectERR, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':'',
'cc':''});
}
i++;
Logger.log("new i IF =" + 1);
continue
}
else
{
// if skip condition is false, fire current supplier purchase order email email
Logger.log("i = " + i);
Logger.log("y = " + y);
Logger.log("ELSE");
GmailApp.sendEmail(email, subject, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':body,
'cc':EmailCC});
}
sheet2.getRange(y + offsetV,colStatus).setValue('OK'); // set email send status next to supplier in Dashboard sheet
// START copy-paste Asign-Rec
var MaxTableRowASIGN = sheet3.getRange("A1").getValue();
Logger.log("MaxTableRowASIGN = " + MaxTableRowASIGN)
/// Get Range we want to change to creating Javascript array and paste at end only
debugger; // stop debugger at this point !! REMOVE OR PLACE AT CORRECT LINE IF USING DEBUGGER
var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow);
var ConsolAsignRec = sheet3.getRange("B3:K" + MaxTableRow);
var ProvOC = sheet.getRange("B2").getValue();
Logger.log("ProvOC = " + ProvOC)
var MaxRowB = sheet3.getRange("C1").getValue() + 1;
Logger.log("MaxRowB = " + MaxRowB);
var NextRowB = MaxRowB + 1;
Logger.log("NextRowB = " + NextRowB);
OcNoHeader.copyTo(sheet3.getRange(MaxTableRowASIGN + 1,3),{contentsOnly:true});
var NumRowsProv = OcNoHeader.getNumRows();
var ProvOCcolumn = sheet3.getRange(MaxRowB, 2, NumRowsProv)
Logger.log("ProvOCcolumn = " + ProvOCcolumn);
ProvOCcolumn.setValue(ProvOC);
// END copy-paste Asign-Rec
i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);
Logger.log("new i ELSE =" + 1)
} // only do while x = max number of suppliers reached
while (y<x);
// set y = 1 to reset value again after finishing loop
sheet.getRange(1,2).setValue(1); // reset ProvNumber = 1 to start again next time script is fired.
var EmailsSent = sheet2.getRange("C10").getValue(); // set values
Logger.log("EmailsSent = " + EmailsSent)
var EmailErrors = sheet2.getRange("C11").getValue();
Logger.log("EmailErrors = " + EmailErrors)
var MaxTableRowEND = sheet2.getRange("C9").getValue();
var schedRange = sheet2.getRange("E4:K" + MaxTableRowEND);
var emailEND = "oscialom@petsy.mx";
var subjectEND = 'OCs Inbound enviadas' + ' ' + timestamp + " (errores " + EmailErrors + " / enviados " + EmailsSent + ")";
var EmailCCEND = "";
var bodyEND = getHtmlTable(schedRange);
GmailApp.sendEmail(emailEND, subjectEND, "Requires HTML",
{
'name':name,
'replyTo':replyTo,
'htmlBody':bodyEND,
'cc':EmailCCEND});
StatusRange.clearContent();
/// START RecordTimestamp code
var Avals = sheet4.getRange("A1:A").getValues();
var lastrow1 = Avals.filter(String).length;
Logger.log('lastrow1 =' + lastrow1)
var Avals2 = sheet5.getRange("A1:A").getValues();
var lastrow2 = Avals2.filter(String).length;
Logger.log('lastrow2 =' + lastrow2)
sheet4.getRange("B2:B" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 1)) // copy order-items to Registro sheet, after last filled row
sheet4.getRange("K2:K" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 2)) // copy Prov1 to Registro sheet, after last filled row
var Avals3 = sheet5.getRange("C1:C").getValues();
var lastrow2c = Avals3.filter(String).length;
Logger.log('lastrow2c =' + lastrow2c);
if(lastrow2 == 1)
{ sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
Logger.log('IF')
}
else
{
sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
Logger.log('ELSE')
}
var MaxTableRowEMAIL = sheet6.getRange("G5").getValue()
var subject = "Items pedidos en OC automatizada " + timestamp
var email = "oscialom@petsy.mx";
var EmailCC = "";
var EmailBCC;
var name = "Petsy Compras";
var ReplyToEmail = "compras@petsy.mx"
var schedRange = sheet6.getRange("A1:C" + MaxTableRowEMAIL);
var body = getHtmlTable(schedRange);
{
GmailApp.sendEmail(email, subject, "Requires HTML",
{
'name':name,
'replyTo':ReplyToEmail,
'htmlBody':body,
'cc':''});
}
/// END RecordTimestamp code
Logger.log("MaxTableRowASIGN " + MaxTableRowASIGN);
var endtime = new Date();
Logger.log("timestamp end " + timestamp);
Logger.log("endtime " + Utilities.formatDate(endtime,'GMT-0600','dd/MM/yyyy HH:mm:ss'));
var scripttime = (endtime - currentTime);
Logger.log("scripttime original" + scripttime);
// strip the ms
scripttime /= 1000;
Logger.log("scripttime / 1000" + scripttime);
// get seconds (Original had 'round' which incorrectly counts 0:28, 0:29, 1:30 ... 1:59, 1:0)
var seconds = Math.round(scripttime % 60);
Logger.log("scripttime % 60" + scripttime);
// remove seconds from the date
scripttime = Math.floor(scripttime / 60);
Logger.log("scripttime / 60" + scripttime);
// Browser.msgBox("Script completado en " + seconds + " segundos",Browser.Buttons.OK_CANCEL); // removed MsgBox to measure real execution time
Logger.log("seconds " + seconds)
}
======================
原帖
我编写了一个 Google 脚本来自动执行多个 vendor 的采购订单流程。该流程获取产品列表(来自工作表 ListaProductos),将产品信息格式化为电子邮件格式(工作表“电子邮件”),发送电子邮件,然后进行一些复制/粘贴到同一电子表格的其他工作表中。 但是,我总是遇到脚本执行时间在 75% 左右的情况。我对此还很陌生,一直在阅读,但坦率地说,我不知道下一步该尝试什么。
最佳答案
我在这部分代码中看到了问题:
do {
// read info from the sheet
range.getValue();
// more code here...
} // only do while x = max number of suppliers reached
while (y<x)
操作getValue
需要很长时间才能运行。最佳实践是使用整个范围:
var data = sheet.getDataRange().getValuses();
然后使用数据作为进一步计算的来源。
在此处查看更多信息:
关于javascript - Google 脚本/将执行时间减少到执行时间限制以下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43108046/