@endlessw1nter

Как оптимизировать код и исправить ошибку Exceeded maximum execution time?

Имеется код для создания файлов по шаблону, при создании более 100 файлов возникает ошибка "Exceeded maximum execution time". Как решить проблему не разбивая свою таблицу на более мелкие? Видел какие-то намеки на использования буфера, но не смог разобраться..

function Creator1() {
  
  const docFile = DriveApp.getFileById("1q8nggbDrcEm7VMaRidn2MkoT0iF0Urukn6aaiGfovKs");
  // это файл шаблона
  const tempFolder = DriveApp.getFolderById("1jIskHluFwL_KWMZLM2Uw8vMoXEJUD8Ef");
  // это директория для новых файлов
  

    
  var list = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var l=list.getLastRow();
  //определяем кол-во строк

  

 for (var i=2; i <= l; i++) {

  var b1 = list.getRange(i, 1).getValue();

  const tempFile = docFile.makeCopy((b1),tempFolder);
  // делаем копию шаблона
  const tempDocFile = DocumentApp.openById(tempFile.getId());
  // открываем созданную копию
  const body = tempDocFile.getBody();
  // тело файла копии

  var a1 = list.getRange(i, 1).getValue()
  var a2 = list.getRange(i, 2).getValue();

  
  
  body.replaceText("<номер>", a1);
  body.replaceText("<фио>", a2);

  
    
  tempDocFile.saveAndClose();
  }
  }
  • Вопрос задан
  • 103 просмотра
Решения вопроса 2
oshliaer
@oshliaer Куратор тега Google Apps Script
Google Products Expert
Никак не оптимизировать, т.к. это облачные вычисления.

Следующие методы сами по себе требует время:
  • makeCopy
  • saveAndClose


Рассмотрите вариант порционного создания файлов. Тут может быть два подхода:
  1. Создание через самозапускаемый триггер. Т.е. триггер, который вызывает сам себя, пока не кончатся задания
  2. Вызов функции в интерфейсе пользователя. Это когда создание каждого документа вызывается через google.script.run на стороне клиента


Помните, что в сутки один пользователь может создать только 200 Документов.
Ответ написан
Комментировать
aekozhevnikov
@aekozhevnikov
hungryking
Вот что вам поможет:
1. Установите библиотеку batch request
2. Включите DriveAPI и DocsAPI в консоли разработчика
3. Вставьте код ниже в файл своего проекта, заполните постоянные переменные, замените название листа если вам необходимо и запускайте функцию Creator()

/**
 * Переменная LIST получает данные с листа с названием 1 которые содержаться в 1 и 2 колонке
 * номер и фио
 * Заполните sampleID и folderID
 */

const sampleID = "ID вашего файла"
const folderID = "ID папки где будут создаваться копии"
const LIST = SpreadsheetApp.getActiveSpreadsheet()
  .getSheetByName('1')
  .getDataRange()
  .getValues()
  .filter(f => f[0] != "")
  .map(f => [f[0], f[1]]);

/** 
 * Функция для создания n копий документа и замены текста в нем
 * данная функция создает количество документов, равное количеству строк в массиве LIST
 * После она запускет функцию batchUpdate() которая берет вновь созданные копии и заменяет в них данные, по строкам для кадого документа
 */

function Creator() {
  var requests = LIST.map(([b1, a2]) => {
    return {
      method: "POST",
      endpoint: `https://www.googleapis.com/drive/v3/files/${sampleID}/copy`,
      requestBody: {
        parents: [folderID], name: `Договор № ${b1} с ${a2}` // заполните здесь название которое вам нужно что бы получилось
      }
    }
  });
  var res = BatchRequest.EDo({
    batchPath: "batch/drive/v3",
    requests: requests,
  });
  console.log(res);
  batchUpdate(res);
}

function batchUpdate(res) {
  var IDS = res.map((item) => {
    return item.id;
  });
  concatArrays(LIST, IDS).forEach(([num, name, id]) => {
    const requests = [
      { replaceAllText: { replaceText: String(num), containsText: { text: "<номер>", matchCase: false } } }, // обязательно используем String() для преобразования чисел в текст
      { replaceAllText: { replaceText: name, containsText: { text: "<фио>", matchCase: false } } }
    ];
    const res = Docs.Documents.batchUpdate({ requests }, id);
    console.log(JSon.stringify(res, null, 2));

    // Utilities.sleep(5000); // Если документов много, может потребоваться использовать скорректированное время ожидания.
  });
}

/** 
 * Эта функция соединяет два массива вместе
 * @param {object} arr1 первый массив, к которму нужно добавить второй массив.
 * @param {object} arr2 второй массив который будем добавлять к первому.
 * @return {object} возвращает объединенный массив
 */

function concatArrays(arr1, arr2) {
  let result = [];
  arr1.forEach((sub, i) => {
    let newSubArr = sub.concat(arr2[i]);
    result.push(newSubArr);
  });
  return result;
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
BasiC2k
@BasiC2k
.NET developer (open to job offers)
Почитайте этот документ: https://developers.google.com/apps-script/guides/s...
Кратко - Google не предоставляет неограниченные облачные ресурсы. На все операции есть определённые лимиты.
Например, скрипт (у частного пользователя) не может выполняться дольше 6 минут.
Есть и другие ограничения, которые необходимо учитывать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы