Как оптимизировать код и исправить ошибку 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(); } } |
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(); } }
Дополнительно:
endlessw1nter docs и sheets - разное.
если хочется в бан, продолжай.
Никак не оптимизировать, т.к. это облачные вычисления.
Следующие методы сами по себе требует время:
- makeCopy
- saveAndClose
Рассмотрите вариант порционного создания файлов. Тут может быть два подхода:
- Создание через самозапускаемый триггер. Т.е. триггер, который вызывает сам себя, пока не кончатся задания
- Вызов функции в интерфейсе пользователя. Это когда создание каждого документа вызывается через google.script.run на стороне клиента
Помните, что в сутки один пользователь может создать только 200 Документов.
Вот что вам поможет:
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; } |
/** * Переменная 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; }
- Насколько это будет быстрее? googleapis.com/drive/v3/files/${sampleID}/copy такой же медленный как и обычный copy.
Отметил как решение
- 50 файлов за минуту, потом превышение лимита))
явно все же быстрее чем обычным copy делать, к тому же потом замена значений будет через bacthUpdate что намного быстрее чем каждый файл перебирать
Ответы:
Почитайте этот документ: https://developers.google.com/apps-script/guides/s...
Кратко - Google не предоставляет неограниченные облачные ресурсы. На все операции есть определённые лимиты.
Например, скрипт (у частного пользователя) не может выполняться дольше 6 минут.
Есть и другие ограничения, которые необходимо учитывать.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для оптимизации кода и исправления ошибки "Exceeded maximum execution time" в PHP, следует принять несколько мер:
1. Используйте эффективные алгоритмы: Пересмотрите свой код и обратите внимание на использование циклов, рекурсивных вызовов и других операций, которые могут занимать много времени. Попробуйте улучшить алгоритмы, чтобы сократить время выполнения.
2. Оптимизируйте запросы к базе данных: Если ваш код выполняет много запросов к базе данных, попробуйте объединить их или использовать индексы для ускорения выполнения. Также можно использовать кэширование данных, чтобы избежать повторных запросов.
3. Ограничьте количество данных: Если ваш код обрабатывает большие объемы данных, попробуйте разделить их на более мелкие порции и обрабатывать их по частям. Это позволит избежать перегрузки памяти и улучшит производительность.
4. Используйте установку ограничения времени выполнения: В PHP можно установить максимальное время выполнения скрипта с помощью функции set_time_limit(). Установите разумное значение для вашего скрипта, чтобы избежать ошибки "Exceeded maximum execution time".
Пример использования set_time_limit():
set_time_limit(30); // Устанавливаем максимальное время выполнения в 30 секунд
5. Используйте кэширование: Для часто используемых данных можно использовать кэширование, чтобы избежать повторных вычислений и запросов к базе данных. Например, можно использовать Memcached или Redis для хранения кэша.
Следуя этим рекомендациям, вы сможете оптимизировать свой код и избежать ошибки "Exceeded maximum execution time" в PHP.