Избегайте повторной отрисовки пользовательской функции

Вопрос или проблема

Я определяю пользовательскую функцию в Google Apps Script, которая вызывает внешний API для возврата определенного значения в ячейке. Похоже, что эта функция продолжает вызываться через определенные интервалы или при повторном открытии таблицы.

Пример: =FETCH_DATA(A1)

function FETCH_DATA(input) {
  var url = "https://example.com/test-endpoint";
  var response = UrlFetchApp.fetch(url, {
     'method' : 'post',
     'payload': {
      input: input
    }
  }).getContentText();
  
  data = JSON.parse(response)["data"]

  return data;
}

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

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

Ответ или решение

Проблема, с которой вы столкнулись, связана с тем, что пользовательские функции в Google Sheets вызываются автоматически при пересчете таблицы. Это может происходить при открытии документа или при изменении любого значения в таблице. Если вы хотите избежать повторных вызовов вашей функции FETCH_DATA, вам нужно использовать другой подход.

К сожалению, невозможно полностью отключить автоматическое пересчитывание пользовательских функций. Однако вы можете использовать свойство CacheService в Google Apps Script для хранения значений и их последующих извлечений. Таким образом, вы сможете снизить количество обращений к внешнему API и обновлять данные только при явном запросе.

Вот пример, как это можно реализовать:

function FETCH_DATA(input) {
  var cache = CacheService.getScriptCache();
  var cachedData = cache.get(input);

  // Проверяем, есть ли данные в кеше
  if (cachedData !== null) {
    return cachedData; // Возвращаем данные из кеша
  }

  // Если данных в кеше нет, делаем запрос к API
  var url = "https://example.com/test-endpoint";
  var response = UrlFetchApp.fetch(url, {
     'method' : 'post',
     'payload': {
      input: input
    }
  }).getContentText();

  var data = JSON.parse(response)["data"];

  // Сохраняем данные в кеш с временем истечения 1 час
  cache.put(input, data, 3600);

  return data;
}

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

Вот пример создания пользовательского меню:

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Fetch Data')
      .addItem('Обновить данные', 'updateData')
      .addToUi();
}

function updateData() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var range = sheet.getRange("A1"); // Укажите диапазон, который нужно обновить
  var input = range.getValue();

  var url = "https://example.com/test-endpoint";
  var response = UrlFetchApp.fetch(url, {
    'method': 'post',
    'payload': {
      input: input
    }
  }).getContentText();

  var data = JSON.parse(response)["data"];

  // Записываем данные в ячейку
  range.setValue(data);
}

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

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

Оцените материал
Добавить комментарий

Капча загружается...