应用程序脚本 运行ning 上的 for 循环非常慢,我怎样才能让它 运行 更快?

for loop on apps script running very slow, how can i make it run faster?

我有一个代码已经使用了 2 年,直到最近它都运行良好。几周前它开始发出超时警告,现在它不再 运行ning 了。 该代码从 google 驱动器上的 13 个不同文件夹中提取每张图片,然后将它们添加到 sheet,它在第 200 行后发出超时警告。我对其进行了一些修改,但我仍然得到超过最大执行时间警告(现在 360 行之后)

如果有人对此有解决方案,我将不胜感激。该脚本过去 运行 非常快(每秒大约 2-3 行),现在每行大约需要 3-4 秒。 非常感谢您!

这是脚本:

function Iteration() {
  var lista_carpetas = SpreadsheetApp.getActive().getSheetByName("carpetas").getRange("A2:A").getValues(); //event list
  var lista_carpetas_ok = lista_carpetas.reduce(function(ar, e) {
    if (e[0]) ar.push(e[0])
    return ar;
  }, []); 
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("data");
  sheet.clear()
  sheet.appendRow(["Name", "Date", "Size", "URL", "Download", "Description", "Image","Folder Id"]);

  for (var i = 5; i <8; i++) {
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("data");
    var folderId = lista_carpetas_ok[i];
    var season1 = SpreadsheetApp.getActive().getSheetByName("carpetas").getRange("B2:B").getValues(); //event list
  var season = season1.reduce(function(ar, e) {
    if (e[0]) ar.push(e[0])
    return ar;
  }, []);

 
    var folder = DriveApp.getFolderById(folderId);
    var contents = folder.getFiles();

    var cnt = 0;
    var file;

    while (contents.hasNext()) {
        var file = contents.next();
        cnt++;

        Logger.log(file);
        Logger.log(cnt);
// writes the various chunks to the spreadsheet- just delete anything you don't want
            data = [
                file.getName(),
                file.getDateCreated(),
                file.getSize(),
                file.getUrl(),
                "https://docs.google.com/uc?export=download&confirm=no_antivirus&id=" + file.getId(),
                file.getDescription(),
                "=image(\"https://docs.google.com/uc?export=download&id=" + file.getId() +"\")",
                folderId,
            ];

            sheet.appendRow(data);
    };

  }
  
}

试试这个:

function Iteration() {
  const ss = SpreadsheetApp.getActive();
  const sh0 = ss.getSheetByName("carpetas");
  const evlist = sh0.getRange("A6:A9").getValues().flat();
  const sh1 = ss.getSheetByName("data");
  sh1.clear();
  sh1.appendRow(["Name", "Date", "Size", "URL", "Download", "Description", "Image", "Folder Id"]);
  for (let i = 0; i < 3; i++) {
    let folder = DriveApp.getFolderById(evlist[i]);
    let contents = folder.getFiles();
    while (contents.hasNext()) {
      let file = contents.next();
      sh1.appendRow([file.getName(),file.getDateCreated(),file.getSize(),file.getUrl(),"https://docs.google.com/uc?export=download&confirm=no_antivirus&id=" + file.getId(),file.getDescription(),"=image(\"https://docs.google.com/uc?export=download&id=" + file.getId() + "\")",evlist[i]]);
    };
  }
}
  • 如果您必须使用“A2:A”之类的范围,则始终使用“A2:A”+ sheet.getLastRow() 的形式,否则您始终必须删除插入的空值从 getLastRow() 到 getMaxRows() 的范围很浪费时间。在这种情况下,使用固定范围实际上效果更好,因为您只使用了三行。

  • 您可以将所有图像存储在 Google 图片库中,然后将其与 API 一起删除。

根据您在回复中的解释,

I didn't copy the whole code because the rest is just 4 more loops just like the one that i copied but for the other folders. So 4 loops in total pull the pictures from 13 different folders on google drive, and each loop pulls the pictures from 3-4 folders.

We have 13 folders on google drive which hold pictures from 2019-2022, and I made a loop that pulls the pictures from each folder that holds pictures for that year. Therefore the script has 4 for loops (only showing the first one above, which pulls the pictures from folders in rows 6 to 8, which are the folders for year 2018) that pull pictures from the folders on google drive.

我相信你的现状和目标如下。

  • 您在“carpetas”的“A”列中有 13 个文件夹 ID sheet。
  • 在您的脚本中,您想使用“carpetas”的“A6:A8”中的值sheet。
  • 通过从“carpetas”的“A7:A9”检索到的文件夹 ID 的文件夹中检索文件元数据sheet,您想将检索到的文件元数据放入“数据”sheet .
  • 您想降低脚本的处理成本。

修改点:

  • 当您想从单元格“A6:A8”中检索文件夹 ID 时,当我看到您的脚本时,您的脚本似乎从单元格“A7:A9”中检索值。
  • 在您的脚本中,循环中使用了 appendRow。在这种情况下,工艺成本变高。 Ref
  • var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("data")可以出循环
  • season 未使用。所以var season1 = SpreadsheetApp.getActive().getSheetByName("carpetas").getRange("B2:B").getValues()可以去掉。

当这些点反映在你的脚本中,就变成了下面这样。

修改后的脚本:

function Iteration() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var carpetasSheet = ss.getSheetByName("carpetas");
  var lista_carpetas = carpetasSheet.getRange("A2:A" + carpetasSheet.getLastRow()).getValues();
  var lista_carpetas_ok = lista_carpetas.filter(([a]) => a);
  var sheet = ss.getSheetByName("data");
  sheet.clear();
  var files = [["Name", "Date", "Size", "URL", "Download", "Description", "Image", "Folder Id"]];
  for (var i = 4; i < 7; i++) {
    console.log(lista_carpetas_ok[i][0]) // Here, you can see the folder ID in the log.
    var folderId = lista_carpetas_ok[i][0];
    try {
      var folder = DriveApp.getFolderById(folderId);
      var contents = folder.getFiles();
      while (contents.hasNext()) {
        var file = contents.next();
        var id = file.getId();
        data = [
          file.getName(),
          file.getDateCreated(),
          file.getSize(),
          file.getUrl(),
          "https://docs.google.com/uc?export=download&confirm=no_antivirus&id=" + id,
          file.getDescription(),
          "=image(\"https://docs.google.com/uc?export=download&id=" + id + "\")",
          folderId,
        ];
        files.push(data);
      };
    } catch (e) {
      // In this modification, when your folder ID cannot be used, that folder ID is skipped. At that time, an error message can be seen in the log.
      console.log(e.message);
    }
  }
  if (files.length == 0) return;
  sheet.getRange(1, 1, files.length, files[0].length).setValues(files);
}

注:

  • 由于您的回复 only showing the first one above, which pulls the pictures from folders in rows 6 to 8, which are the folders for year 2018,此修改后的脚本从单元格“A6:A8”中检索文件夹 ID。但如果你想从“A7:A9”中检索文件夹ID,请将for (var i = 4; i < 7; i++) {修改为for (var i = 5; i < 8; i++) {

参考文献: