Недокументированные проблемы ограничения API листов - PullRequest
0 голосов
/ 20 октября 2018

Я уже просматривал сообщения, в которых люди сталкивались с похожими проблемами, но не смогли найти четкого ответа.

Я пытаюсь получить двумерный массив из 264735 слотов, используя следующие строки кода:

  var optionalArguments = {majorDimension: "ROWS",
                     valueRenderOption: "FORMULA",
  };
  var sourceValuesObject = Sheets.Spreadsheets.Values.get(spreadsheetId, rangeA1Notation, optionalArguments)

но вот что я получаю:

код ответа: 413. Сообщение: ответ слишком велик.

Это выглядит странно, потому что я не вижу такого рода ограничений, написанных нигде, а также как пользователь может получить большое количество данных, если 300000 ячеек или меньше делают ошибку API.

IЯ пытался разделить запросы, и это работает, но это усложняет и замедляет мой код, плюс я получаю пустой ответ при попытке обновить значения до диапазона моего листа.

Указываю ли я правильное направление,Это нормально, есть ли обходной путь?

РЕДАКТИРОВАТЬ: Вот образец таблицы

Сначала я попытался получить разделенные диапазоны, используяSheets.Spreadsheets.Values.get внутри цикла for, и это сработало.

То же самое с batchGet дает мне ту же ошибку, поэтому я предполагаю, что внутри ячеек слишком большие данные.

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Ну вот что я обнаружил, пытаясь сравнить разные способы получения значений:

function compare(){
  getValuesSpreasheetApp();
  getValuesUrlFetch();
  getValues();
}
//using spreadsheetApp.getFormulas()
function getValuesSpreasheetApp(){
  var t0 = new Date().getTime();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var dataRange = ss.getActiveSheet().getDataRange();
  var formulas = dataRange.getFormulas();
  var values = dataRange.getValues();
  var t1 = new Date().getTime();
  Logger.log("spreadsheetApp: " + (t1 -t0));
}
//using UrlFetchApp.fetchAll
function getValuesUrlFetch()
{
  var t0 = new Date().getTime();
  var ranges = ["'Copie de Feuille 1'!A1:JE500", "'Copie de Feuille 1'!A501:JE1000"];
  var token = ScriptApp.getOAuthToken();
  var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
  var requests = ranges.map(function(e) {
      return {
      method: "get",
      url: "https://sheets.googleapis.com/v4/spreadsheets/" + spreadsheetId + "/values/" + e + "?majorDimension=ROWS&valueRenderOption=FORMULA",
      headers: {Authorization: "Bearer " + token},
      muteHttpExceptions: true,
    }
  });
  var res = UrlFetchApp.fetchAll(requests);
  var values = res.reduce(function(ar, e) {
    Array.prototype.push.apply(ar, JSON.parse(e.getContentText()).values);
    return ar;
  }, []);
  var t1 = new Date().getTime();
  Logger.log("UrlFetch: " + (t1 -t0));
}
//using Sheets.Spreadsheets.Values.get()
function getValues(){
  var t0 = new Date().getTime();
  var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
  var ranges = ["'Copie de Feuille 1'!A1:JE500", "'Copie de Feuille 1'!A501:JE1000"];
  var optionalArguments = {majorDimension: "ROWS",
                 valueRenderOption: "FORMULA",
 };
  res = [];
  for(var i = 0; i < ranges.length; i++)
    res.push(Sheets.Spreadsheets.Values.get(spreadsheetId, ranges[i]));
  var values = res.reduce(function(ar, e) {
    Array.prototype.push.apply(ar, e.values);
    return ar;
  }, []);
  var t1 = new Date().getTime();
  Logger.log("values.get: " + (t1 -t0));
}

и вот результат:

[18-10-23 01: 35: 30: 034 CEST] электронная таблицаApp: 13828

[18-10-23 01: 35: 33: 614 CEST] UrlFecth: 3580

[18-10-23 01: 35: 38: 185 CEST] values.get: 4570

Спасибо @ Tanaike за то, что дали мне такой точный ответ, когда произошла ошибка, и дали мне предупреждающее решение,Вот эталонный тест, а fetchAll - самое быстрое решение.

0 голосов
/ 21 октября 2018

Как насчет этого обходного пути?

Эксперимент:

В этом эксперименте используется ваша общая примерная электронная таблица.

Когда конечная точка Sheets API напрямую вызывается UrlFetchApp, еслиразмер ответа превышает 50 МБ (52 428 800 байт), возвращается ответ менее 50 МБ.Размер 50 МБ обусловлен ограничением UrlFetchApp.С другой стороны, в Advanced Google Service он не может подтвердить эту ситуацию, потому что ошибка возникает, когда она превышает ограничение.Таким образом, с помощью UrlFetchApp, причина ошибки в вашей ситуации может быть подтверждена.Итак, сначала я подтвердил это с помощью следующего сценария.

var spreadsheetId = "#####";
var range = "'Copie de Feuille 1'!A1:JE1000";
var url = "https://sheets.googleapis.com/v4/spreadsheets/" + spreadsheetId + "/values/" + range + "?majorDimension=ROWS&valueRenderOption=FORMULA";
var res = UrlFetchApp.fetch(url, {headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}});
Logger.log(res.getContentText().length.toString())
var values = JSON.parse(res.getContentText());

При запуске вышеуказанного сценария возвращается 52428450.И ошибка «Неопределенный строковый литерал» возникает в последней строке.Это означает, что объект неполон.Из этого результата обнаружено, что значения не могут быть получены одним вызовом values.get с диапазоном 'Copie de Feuille 1'!A1:JE1000.Это то же самое, что и I '-' I's comment .

В вашей выборочной электронной таблице было обнаружено, что граница диапазона, в котором возникает ошибка, составляет 'Copie de Feuille 1'!A1:JE722.При попытке получить значения из диапазона 'Copie de Feuille 1'!A1:JE723 возникает ошибка.Размер значений, извлеченных из 'Copie de Feuille 1'!A1:JE722, составляет 52 390 229 байт.Это менее 50 МБ (52 428 800 байт).Размер от 'Copie de Feuille 1'!A1:JE723 составляет 52 428 450 байт, что соответствует значению от 'Copie de Feuille 1'!A1:JE1000.Исходя из этого, выясняется, что это превышение ограничения UrlFetchApp.

Обходной путь:

Чтобы избежать этой ошибки и получить все значения, в качестве обходного пути, я думаю, что я хотел быпредложить разделить диапазон для извлечения значений из электронной таблицы.Но в вашем вопросе вы хотите скорость.Поэтому я хотел бы предложить следующий пример сценария.

  1. Создание запросов.
  2. Извлечение созданных запросов с использованием UrlFetchApp.fetchAll().
    • По UrlFetchApp.fetchAll() каждый запрос может работать с асинхронной обработкой.
    • В API листов расширенного сервиса Google это использовать нельзя.А также в values.batchGet, поскольку все извлеченные значения превышают ограничение, возникает ошибка.
    • При этом стоимость процесса с использованием UrlFetchApp.fetchAll() становится ниже, чем в Sheets API Advanced Google Service.

Пример сценария:

var ranges = ["'Copie de Feuille 1'!A1:JE500", "'Copie de Feuille 1'!A501:JE1000"]; // This was used from the shared spreadsheet. So please modify this for your environment.
var token = ScriptApp.getOAuthToken();
var requests = ranges.map(function(e) {
  return {
    method: "get",
    url: "https://sheets.googleapis.com/v4/spreadsheets/" + spreadsheetId + "/values/" + e + "?majorDimension=ROWS&valueRenderOption=FORMULA",
    headers: {Authorization: "Bearer " + token},
    muteHttpExceptions: true,
  }
});
var res = UrlFetchApp.fetchAll(requests);
var values = res.reduce(function(ar, e) {
  Array.prototype.push.apply(ar, JSON.parse(e.getContentText()).values);
  return ar;
}, []);
Logger.log(values.length) // 1000
Logger.log(values[0].length) // 265

Примечание:

  • Если вы хотите использовать сценарий, пожалуйста, подтвердите, что листыAPI включен в консоли API.
  • При объединении массивов, если возникает ошибка ограничения массива, используйте каждый массив без объединения массивов.
  • При использовании API листов расширенной службы GoogleКроме того, ошибка не возникает в диапазоне 'Copie de Feuille 1'!A1:JE722, а ошибка возникает в 'Copie de Feuille 1'!A1:JE723.Этот результат совпадает с результатом UrlFetchApp.

Ссылки:

...