Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
355 views
in Technique[技术] by (71.8m points)

javascript - Google sheet script timeout error

I'm trying to get file names and IDs from images and there are more than 3000 images and the number will just keep adding.

I have this piece of code online that works pretty well. However the problem is that the script will always timeout before it can finish getting all the images.

So I'm wondering if there's a way to continue from where from the last session. I know there are many answers addressing session timeout problems but my javascript isn't proficient enough to figure out how to write them.

Thanks

Here's the code I have

function listFilesInFolder(folderName) {

   var sheet = SpreadsheetApp.getActiveSheet();
   sheet.appendRow(["Name", "File-Id"]);


//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
    var folder = DriveApp.getFolderById("ID");
    var contents = folder.getFiles();

    var cnt = 0;
    var file;

    while (contents.hasNext()) {
        var file = contents.next();
        cnt++;
            data = [
                file.getName(),
                file.getId(),
            ];
            sheet.appendRow(data);
    };
};
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When I saw your question, I imaged 2 patterns. But I think that there are several answers for your situation. So please think of this as two of them.

Pattern 1 :

  • Use setValues() instead of appendRow().
    • The data is created in the while loop. And put the data to Spreadsheet using setValues().

Modified script :

function listFilesInFolder(folderName) {
  var data = [["Name", "File-Id"]];
  var folder = DriveApp.getFolderById("ID"); // Please set this.
  var contents = folder.getFiles();
  while (contents.hasNext()) {
    var file = contents.next();
    data.push([file.getName(), file.getId()]);
  };
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(sheet.getLastRow() + 1, 1, data.length, data[0].length).setValues(data); // Modified
};

Pattern 2 :

  • Use Drive API.
    • Retrieve the data using Drive API. And put the data to Spreadsheet using setValues().

In order to use this sample script, please enable Drive API at Advanced Google Services and API console. You can see the flow of this at here.

Modified script :

function listFilesInFolder2(folderName) {
  var folderId = "ID"; // Please set this.
  var data = [["Name", "File-Id"]];
  var params = {
    'pageSize': 1000,
    'q': "'" + folderId + "' in parents and mimeType!='" + MimeType.FOLDER + "'",
    'fields': "nextPageToken,items(id,title)"
  };
  do {
    var r = Drive.Files.list(params);
    params["pageToken"] = r.nextPageToken;
    r.items.forEach(function(e) {data.push([e.title, e.id])});
  } while(r.nextPageToken);
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(sheet.getLastRow() + 1, 1, data.length, data[0].length).setValues(data); // Modified
};

References :

If these were not what you want, I'm sorry.

Added :

By the comment of @Steve Gon why do you think SetValue is better than AppendRow?, I added the reason I propose setValues() instead of appendRow().

In this issue, when many files (more than 3000) in a folder are retrieved and put to the spreadsheet, the process time is over 6 minutes which is the limitation. If my understanding is correct, I think that OP wants to solve this issue. Although I proposes to use "setValues()" because I had known that the values of 10000 rows with the 2 columns can be put to a sheet without errors using it, I had not shown about the difference of the process time in my answer. I'm really sorry for this. So I added this.

I prepared 2 sample scripts for this situation. The main work is to put 10,000 rows with 2 columns to a sheet. This is larger than 3,000 of the issue. At that time, it measures the process time of setValues() and appendRow().

Sample script using setValues()

var label = "sampleLabel"
console.time(label);
var rows = 10000;
var values = [];
for (var i = 0; i < rows; i++){
  values.push(["Name", "File-Id"]);
}
var ss = SpreadsheetApp.getActiveSheet();
ss.getRange(ss.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
console.timeEnd(label);

Sample script using appendRow()

var label = "sampleLabel"
console.time(label);
var rows = 10000;
var ss = SpreadsheetApp.getActiveSheet();
for (var i = 0; i < rows; i++){
  ss.appendRow(["Name", "File-Id"]);
}
console.timeEnd(label);

Result :

  • When setValues() was used, the process time was 2 s - 3 s. And there are no errors.
  • When appendRow() was used, when the value was put to 1400 - 1500 rows, the execution time was over 6 minutes. Although I had tried several times, 3000 rows couldn't be put.

This is the reason I proposed setValues().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...