【问题标题】:How to step through google script如何单步执行谷歌脚本
【发布时间】:2018-06-09 16:19:38
【问题描述】:

我正在尝试编写一个 Google 表格脚本宏。我如何逐步了解为什么超过了时间? 我的问题是循环,当我将迭代最大值(场景)设置为 46 时,代码似乎运行良好,大约需要 1-2 秒。当最大值设置为 47 时,它会因超过最大执行时间(4-5 分钟)而死亡。怎么回事?

function testing() {

  var aa = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Run 
  Program");

  var scenarios = aa.getRange("H19").getValue();



  for (i = 1; i <= scenarios; i++){

  var ss = 
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet6");

  var range = ss.getRange("b6:u6");
  var min = 1  ;
  var max = 20 ; 
  var numbers = []
    for (var i = min; i <= max; i++) {             
      numbers.push(i);
  }  


  shuffleArray(numbers)
  var counter = 0;
  for (var x = 1; x <= range.getWidth(); x++) {
    for (var y = 1; y <= range.getHeight(); y++) {
      range.getCell(y, x).setValue(numbers[counter]);
      counter++;
    }
  }
  var range = ss.getRange("v6:ao6");
  var min = 21  ;
  var max = 40  ;
  var numbers = []
    for (var i = min; i <= max; i++) {
     numbers.push(i);
  }
  shuffleArray(numbers)
  var counter = 0;
  for (var x = 1; x <= range.getWidth(); x++) {
    for (var y = 1; y <= range.getHeight(); y++) {
      range.getCell(y, x).setValue(numbers[counter]);
      counter++;
    }
  }
  var range = ss.getRange("ap6:at6");
  var min = 41  ;
  var max = 45  ;
  var numbers = []
    for (var i = min; i <= max; i++) {
     numbers.push(i);
  }
  shuffleArray(numbers)
  var counter = 0;
  for (var x = 1; x <= range.getWidth(); x++) {
    for (var y = 1; y <= range.getHeight(); y++) {
      range.getCell(y, x).setValue(numbers[counter]);
      counter++;
    }
  }
  }
//  function Chart4() {
  var spreadsheet = SpreadsheetApp.getActive();
      spreadsheet.getRange('A1').activate();
      spreadsheet.getSheetByName('Chart4').showSheet()
     .activate();
      spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Chart4'), 
true);
};

【问题讨论】:

  • 对于这种情况,单步执行代码需要很长时间,因为循环太多。您可以使用Logger.log() 语句来查看发生了什么。你可以阅读Link to Trouble shooting guide
  • 使用 console.timeconsole.timeEnd 将每个循环的执行时间打印到 Stackdriver。还要尽你所能摆脱getCellsetValue 上的双重嵌套循环。学习数组,以及如何使用setValues

标签: google-apps-script


【解决方案1】:

您的代码需要很多帮助。这是一个帮助您入门的提示。

正如其他人所提到的,您应该在整个范围内调用 .getValues(),这会为您提供一个单元格值的二维数组 [[A1value,B1value,...],[A2val,B2val...], ...]。您应该首先获取宽度和长度并分配给一个变量。引用该变量而不是在循环条件中调用 API。事实上,由于您提前知道范围,因此您应该在主 for 循环以及电子表格 (ss) 之外定义您需要的所有范围:

var aa = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Run Program");
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet6");
var range1 = ss.getRange("b6:u6");
var range2 = ss.getRange("v6:ao6");
for (i = 1; i <= scenarios; i++) { ...

如果您重复调用 API,脚本会开始花费很长时间。

不确定你的宏到底想做什么,但这里有一个运行这种循环的模板以及你应该如何考虑它。

var range = ss.getRange(A1-style-address);
var values = range1.getValues();

var width = range1[0].length;
var height = range1.length;

var new_values = new Array(); 

for (var i = 0; i < height; i++) {
    for (var j = 0; j < width; j++) {

       //do something with values[i][j], like push to new_values

    }
}
//something like:
//var new_range = ss.getRange(different A1-style address) 
//new_range.setValues(new_array)  

您必须确保新数组包含二维数组中的值,该数组与您将它们放入的范围具有相同的维度,否则会引发错误。

我会让你弄清楚如何修改循环内的 new_values 数组以确保它的大小正确。

如果这对您来说是新的,这里有一个 javascript 中的 link to an overview of arrays,这里有一些 array documentation

【讨论】:

    【解决方案2】:

    Range.getCell() 调用有时会很昂贵,应该避免。使用 Range.getValues() 并遍历二维数组。此外,不要使用活动电子表格按 Id 打开电子表格进行单元测试。这样您就可以直接从 GAS 编辑器调试/运行。 GAS 编辑器通常会在代码中捕获此类性能问题,并显示指向代码中行号的警告。

    【讨论】:

    • 为什么您错误地认为使用getActive()意味着您无法从脚本编辑器运行或调试脚本?
    • 不知道你为什么在这里“错误地”调用。除非项目是电子表格中的内联项目,否则 getActive() 会起作用吗?
    • SpreadsheetApp.getActive()SpreadsheetApp.getActiveSpreadsheet() 对于绑定到 Google 表格文件的所有 Apps 脚本项目均有效。您不必在选项卡中打开电子表格。 SpreadsheetApp.openById 不能与 .currentonly 访问范围限制器一起使用,这意味着您的应用程序更有可能通过请求访问用户的每一个 Google 电子表格来表现出恶意。
    猜你喜欢
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多