Таймауты Google Script

Проблема:

importXLSXtoGsheet() функции importXLSXtoGsheet() истекает, прежде чем она сможет обработать все 52 файла XLSX. Я получил сообщение об ошибке: Exception: Time-out: https://www.googleapis.com/batch/drive/v3 at [unknown function](Code:63) at Do(Code:8) at importXLSXtoGsheet(Code:71)

Если я запускаю функцию с 1 файлом в папке importXLS, она работает правильно.

Сценарий объяснил:

У меня есть 52 папки, каждая из которых содержит один файл электронной таблицы.
Каждая папка доступна для разных коллег. В течение дня люди вносят изменения в файлы.

  1. В конце дня все файлы собираются в одну папку ( gsheetFolder ) и преобразуются в файлы XLSX с помощью функции collectAndExportXLS .

Эти файлы вечером копируются на локальный сервер (с использованием пакетного сценария и синхронизации диска), который обновляет другую информацию в файле и копируется обратно в importXLSXfolder .

  1. Утром функция importXLSXtoGsheet запускается и преобразует все файлы XLSX в папке importXLSXfolder в файлы Gsheet в gsheetFolder .
  2. После этого запускается sortGsheetFiles , сортируя и перемещая каждый файл Gsheet в одну из 52 папок (используя список массивов из текущей электронной таблицы).

Другие действия включают в себя очистку папок с deleteFolder функции deleteFolder .

Автор сценария:

var gsheetFolder = '###'
var XLSXfolder = '###'
var importXLSXfolder = '###'

// Modified
function deleteFolder(folderId) {
  var url = "https://www.googleapis.com/drive/v3/files?q='" + folderId + "'+in+parents+and+trashed%3Dfalse&fields=files%2Fid&access_token=" + ScriptApp.getOAuthToken();
  var res = UrlFetchApp.fetch(url);
  var obj = JSON.parse(res.getContentText());
  var reqs = obj.files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
  var requests = {batchPath: "batch/drive/v3", requests: reqs};
  if (requests.requests.length > 0) BatchRequest.Do(requests);
}

// Added
function deleteFiles(files) {
  var reqs = files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
  var requests = {batchPath: "batch/drive/v3", requests: reqs};
  if (requests.requests.length > 0) BatchRequest.Do(requests);
}

// Added
function getValuesFromSpreadsheet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  return sheet.getRange("A2:B53").getValues();
}

// Modified
function sortGsheetFiles() {
  var url = "https://www.googleapis.com/drive/v3/files?q='" + gsheetFolder + "'+in+parents+and+mimeType%3D'" + MimeType.GOOGLE_SHEETS + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
  var res = UrlFetchApp.fetch(url);
  var obj = JSON.parse(res.getContentText());
  var values = getValuesFromSpreadsheet();
  var reqs = values.reduce(function(ar, e) {
    for (var i = 0; i < obj.files.length; i++) {
      if (obj.files[i].name == e[0]) {
        ar.push({
          method: "PATCH",
          endpoint: "https://www.googleapis.com/drive/v3/files/" + obj.files[i].id + "?addParents=" + e[1] + "&removeParents=" + gsheetFolder,
        });
        break;
      }
    }
    return ar;
  }, []);
  var requests = {batchPath: "batch/drive/v3", requests: reqs};
  if (requests.requests.length > 0) BatchRequest.Do(requests);
  deleteFolder(importXLSXfolder);
}

// Modified
function importXLSXtoGsheet(){
  deleteFolder(XLSXfolder);
  var url = "https://www.googleapis.com/drive/v3/files?q='" + importXLSXfolder + "'+in+parents+and+mimeType%3D'" + MimeType.MICROSOFT_EXCEL + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
  var res = UrlFetchApp.fetch(url);
  var obj = JSON.parse(res.getContentText());
  var reqs = obj.files.map(function(e) {return {
      method: "POST",
      endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id + "/copy",
      requestBody: {mimeType: MimeType.GOOGLE_SHEETS, name: e.name + ".xlsx", parents: [gsheetFolder]},
    }
  });
  var requests = {batchPath: "batch/drive/v3", requests: reqs};
  if (requests.requests.length > 0) BatchRequest.Do(requests);
  deleteFolder(importXLSXfolder);
}

// Modified
function ConvertBackToXLS(fileList) {
  var token = ScriptApp.getOAuthToken();
  var reqs1 = fileList.map(function(e) {return {
      method: "GET",
      url: "https://docs.google.com/spreadsheets/export?id=" + e.id + "&exportFormat=xlsx&access_token=" + token,
    }
  });
  var res = UrlFetchApp.fetchAll(reqs1);
  var reqs2 = res.map(function(e, i) {
    var metadata = {name: fileList[i].name, parents: [XLSXfolder]};
    var form = FetchApp.createFormData(); // Create form data
    form.append("metadata", Utilities.newBlob(JSON.stringify(metadata), "application/json"));
    form.append("file", e.getBlob());
    var url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
    return {url: url, method: "POST", headers: {Authorization: "Bearer " + token}, body: form};
  });
  FetchApp.fetchAll(reqs2);
}

// Modified
function collectAndExportXLS() {
  deleteFolder(gsheetFolder);
  var values = getValuesFromSpreadsheet();
  var reqs1 = values.reduce(function(ar, e) {
    if (e[0] && e[1]) {
      ar.push({
        method: "GET",
        endpoint: "https://www.googleapis.com/drive/v3/files?q='" + e[1] + "'+in+parents+and+trashed%3Dfalse&fields=files(id%2Cname)",
      });
    }
    return ar;
  }, []);
  var resForReq1 = BatchRequest.Do({batchPath: "batch/drive/v3", requests: reqs1});
  var temp = resForReq1.getContentText().split("--batch");
  var files = temp.slice(1, temp.length - 1).map(function(e) {return JSON.parse(e.match(/{[Ss]+}/g)[0])});
  var fileList = files.reduce(function(ar, e) {return ar.concat(e.files.map(function(f) {return f}))}, []);
  ConvertBackToXLS(fileList);
  deleteFiles(fileList);
}

Всего 1 ответ


О вашем вопросе я могу понять, как показано ниже.

  • Когда importXLSXtoGsheet() запускается с 52 файлами, возникает ошибка.
  • Когда importXLSXtoGsheet() запускается с менее чем 13 файлами, ошибки не возникает.
  • Другие функции, кроме importXLSXtoGsheet() работают нормально.

Если мое понимание правильное, как один из обходных путей, он определяет максимальное количество для обработки файлов один раз. Когда это отражается на importXLSXtoGsheet() вашего скрипта, модифицированный скрипт выглядит следующим образом.

Модифицированный скрипт:

function importXLSXtoGsheet(){
  deleteFolder(XLSXfolder);
  var url = "https://www.googleapis.com/drive/v3/files?q='" + importXLSXfolder + "'+in+parents+and+mimeType%3D'" + MimeType.MICROSOFT_EXCEL + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
  var res = UrlFetchApp.fetch(url);
  var obj = JSON.parse(res.getContentText());

  // I modified below script.
  var n = 10; // Maximum number.
  var files = [];
  var len = obj.files.length;
  for (var i = 0; i < len; i++) {
    files.push(obj.files.splice(0, n));
    len -= n - 1;
  }
  files.forEach(function(f) {
    var reqs = f.map(function(e) {return {
        method: "POST",
        endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id + "/copy",
        requestBody: {mimeType: MimeType.GOOGLE_SHEETS, name: e.name + ".xlsx", parents: [gsheetFolder]},
      }
    });
    var requests = {batchPath: "batch/drive/v3", requests: reqs};
    if (requests.requests.length > 0) BatchRequest.Do(requests);
  });
  deleteFolder(importXLSXfolder);
}

Замечания:

  • В этом примере сценария 10 файлов обрабатываются в каждом пакетном запросе. Если вы хотите изменить это, пожалуйста, измените var n = 10; ,

Есть идеи?

10000