Получение и обработка данных с помощью пользовательских функций

Одним из способов, которыми пользовательские функции расширяют возможности Excel, является получение данных из расположений, отличных от книги, таких как веб-сайт или сервер (через WebSocket). Внешние данные можно запрашивать с помощью API, например FetchXmlHttpRequestXHR, стандартного веб-API, который отправляет HTTP-запросы для взаимодействия с серверами.

Важно!

Обратите внимание, что настраиваемые функции доступны в Excel на следующих платформах.

  • Office в Интернете
  • Office для Windows
    • Подписка на Microsoft 365
    • Розничный бессрочный Office 2016 и более поздних версий
    • корпоративные бессрочные Office 2021 и более поздних версий
  • Office для Mac

Пользовательские функции Excel в настоящее время не поддерживаются в следующих приложениях:

  • Office для iPad
  • корпоративные бессрочные версии Office 2019 или более ранних версий в Windows

GIF пользовательской функции, которая передает время из API.

Функции, которые возвращают данные из внешних источников

Если пользовательская функция извлекает данные из внешнего источника, например, сайта, она должна:

  1. Возвращает JavaScript Promise в Excel.
  2. Разрешите Promise с окончательным значением с помощью функции обратного вызова.

Пример получения данных

В следующем примере webRequest кода функция обращается к гипотетическому внешнему API, который отслеживает количество людей, которые в настоящее время находятся на Международной космической станции. Функция возвращает JavaScript Promise и использует fetch для запроса информации из гипотетического API. Полученные данные преобразуются в JSON, names а свойство преобразуется в строку, которая используется для разрешения обещания.

При разработке собственных функций может потребоваться выполнение действия, если веб-запрос не завершается своевременно. Также можно рассмотреть совмещение нескольких запросов API.

/**
 * Requests the names of the people currently on the International Space Station.
 * Note: This function requests data from a hypothetical URL. In practice, replace the URL with a data source for your scenario.
 * @customfunction
 */
function webRequest() {
  let url = "https://www.contoso.com/NumberOfPeopleInSpace"; // This is a hypothetical URL.
  return new Promise(function (resolve, reject) {
    fetch(url)
      .then(function (response){
        return response.json();
        }
      )
      .then(function (json) {
        resolve(JSON.stringify(json.names));
      })
  })
}

Примечание.

При использовании метода fetch не создаются вложенные обратные вызовы, что в некоторых случаях может быть предпочтительнее, чем использование метода XHR.

Пример XHR

В следующем примере кода функция вызывает API GitHub для обнаружения количества звезд, getStarCount предоставленных репозиторию конкретного пользователя. Это асинхронная функция, которая возвращает JavaScript Promise. При получении данных из веб-вызова выполняется разрешение обещания, которое возвращает данные в ячейку.

/**
 * Gets the star count for a given Github organization or user and repository.
 * @customfunction
 * @param userName string name of organization or user.
 * @param repoName string name of the repository.
 * @return number of stars.
 */
async function getStarCount(userName: string, repoName: string) {

  const url = "https://api.github.com/repos/" + userName + "/" + repoName;

  let xhttp = new XMLHttpRequest();

  return new Promise(function(resolve, reject) {
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState !== 4) return;

      if (xhttp.status == 200) {
        resolve(JSON.parse(xhttp.responseText).watchers_count);
      } else {
        reject({
          status: xhttp.status,

          statusText: xhttp.statusText
        });
      }
    };

    xhttp.open("GET", url, true);

    xhttp.send();
  });
}

Создание функции потоковой передачи

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

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

  • Тег @streaming JSDoc.
  • Параметр CustomFunctions.StreamingInvocation вызова.

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

  • Excel отображает каждое новое значение автоматически с помощью метода setResult.
  • Второй параметр ввода, invocation, не отображается для конечных пользователей в Excel, когда они выбирают функцию в меню "Автозаполнение".
  • Обратный onCanceled вызов определяет функцию, которая выполняется при отмене функции.
  • Потоковая передача не обязательно связана с выполнением веб-запроса. В этом случае функция не выполняет веб-запрос, но по-прежнему получает данные через заданные интервалы, поэтому для нее требуется использовать параметр потоковой передачи invocation .
/**
 * Increments a value once a second.
 * @customfunction INC increment
 * @param {number} incrementBy Amount to increment
 * @param {CustomFunctions.StreamingInvocation<number>} invocation
 */
function increment(incrementBy, invocation) {
  let result = 0;
  const timer = setInterval(() => {
    result += incrementBy;
    invocation.setResult(result);
  }, 1000);

  invocation.onCanceled = () => {
    clearInterval(timer);
  };
}

Примечание.

Пример возврата динамического массива разлива из функции потоковой передачи см. в разделе Возврат нескольких результатов из пользовательской функции: примеры кода.

Отмена функции

Excel отменяет выполнение функции в следующих ситуациях.

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

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

Примечание.

Существует также категория функций, называемых отменяемыми функциями @cancelable , которые используют тег JSDoc. Отменяемые функции позволяют завершить веб-запрос в середине запроса.

Функция потоковой передачи @cancelable не может использовать тег, но функции потоковой передачи могут включать функцию обратного onCanceled вызова. Только асинхронные пользовательские функции, возвращающие одно значение, могут использовать @cancelable тег JSDoc. Дополнительные сведения о теге см. в @cancelable этой Autogenerate JSON metadata: @cancelable статье.

Использование параметра вызова

Параметр invocation является по умолчанию последним в любой пользовательской функции. Параметр invocation предоставляет контекст ячейки (например, ее адрес и содержимое) и позволяет использовать setResult метод и onCanceled событие, чтобы определить, что функция делает при потоковой передаче (setResult) или отмене (onCanceled).

Обработчик вызова должен иметь тип CustomFunctions.StreamingInvocation или CustomFunctions.CancelableInvocation для обработки веб-запросов.

См. раздел Параметр вызова , чтобы узнать о других потенциальных возможностях использования аргумента invocation и о том, как он соответствует объекту Вызова .

Получение данных через WebSockets

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

Пример WebSockets

Следующий примера кода устанавливает соединение WebSocket, а затем заносит в журнал каждое входящее сообщение от сервера.

let ws = new WebSocket('wss://bundles.office.com');

ws.onmessage(message) {
    console.log(`Received: ${message}`);
}

ws.onerror(error){
    console.err(`Failed: ${error}`);
}

Дальнейшие действия

См. также