Исследование нового JavaScript API for Office

Стивен Оливер, Эрик Шмидт

Продукты и технологии:
JavaScript API for Office

В статье рассматриваются:

  • обзор JavaScript API for Office;
  • шаблон асинхронного программирования;
  • иерархия объектной модели;
  • проверка наличия какой-либо возможности в хост-приложении.

Эта статья посвящена рассмотрению JavaScript API for Office, появившемся в Microsoft Office 2013. Мы исходим из того, что вы знакомы с приложениями для Office. Благодаря этому вы будете хорошо понимать, как работают приложения для Office API.

Обзор JavaScript API for Office

JavaScript API for Office охватывает полную объектную модель. Этот API содержится в наборе JavaScript-файлов, начиная с файла office.js. Приложение должно включать ссылку на файл office.js, чтобы задействовать JavaScript API for Office. При загрузке файл office.js загружает остальные скрипты, необходимые для его работы, в том числе скрипты для хост-среды и локализованные строки. К счастью, вы можете добавить ссылку на файл office.js, используя сеть доставки контента (content delivery network, CDN), поэтому вам нет нужды развертывать копию файла office.js вместе со своим приложением. Вот пример:

  1. <!-- При развертывании приложения вы должны всегда
  2.   загружать CDN версию файла office.js -->
  3. <script src=
  4.   "https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js">
  5. </script>

Объектная модель спроектирована с учетом нескольких целей.

  1. "Пишется один раз, работает везде" Она должна быть расширяемой без привязки к определенному хост-приложению, но построена с учетом возможностей, доступных в разных хост-приложениях. Приложения единообразно обращаются к специфичной для конкретного хоста функциональности.
  2. Кросс-платформенность Совместимость занимает в этом списке одно из первых мест; таким образом, объектная модель не привязана к конкретной версии Office. Кроме того, один и тот же код работает с Web App-версиями клиентских приложений Office, где такая поддержка предусмотрена. Например, приложение для Excel может работать в Excel Web App точно так же, как в клиентском приложении Excel.
  3. Производительность и безопасность Объектная модель должна быть максимально производительной, чтобы дополнительные приложения по возможности не сказывались на работе пользователя. Кроме того, JavaScript API был спроектирован так, чтобы напрямую взаимодействовать с контентом документов без использования механизма автоматизации приложений Office, а это повышает стабильность и безопасность решений.

Другой основной целью создания JavaScript API было стремление привлечь внимание веб-разработчиков к платформе Office. Таким образом, объектная модель была построена с учетом современного веб-программирования. При создании приложений в комбинации с JavaScript API for Office вы можете использовать свои текущие навыки и знания других JavaScript-библиотек, таких как jQuery.

Шаблон асинхронного программирования

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

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

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

  • общая сигнатура асинхронных функций в приложениях для Office API;
  • использование дополнительных (необязательных) параметров в асинхронных функциях;
  • роль объекта AsyncResult в асинхронных функциях.

Обсудим по очереди каждый из этих моментов.

Общая сигнатура асинхронных функций в приложениях для Office API Все асинхронные функции в таких приложениях имеют одинаковое соглашение об именовании и одну и ту же базовую сигнатуру. Имя каждой асинхронной функции заканчивается "Async", например Document.getSelectedDataAsync.

Сигнатура всех асинхронных функций соответствует следующему базовому шаблону:

  1. functionNameAsync(requiredParameters,  [, options], [callback]);

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

Необязательные параметры в асинхронных функциях Дополнительный JavaScript-объект в сигнатуре асинхронных функций является набором пар "ключ-значение", разделяемых двоеточием, где ключ - это имя параметра, а значение - данные, которые вы хотите использовать для этого параметра. Порядок пар "ключ-значение" неважен при условии правильности имени параметра. В документации MSDN по каждой асинхронной функции детально описывается, какие параметры доступны в ней для использования в объекте options.

Например, метод Document.setSelectedDataAsync имеет ту же базовую сигнатуру, общую для всех асинхронных функций в приложениях для Office:

  1. Office.context.document.setSelectedDataAsync(data [, options], callback);

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

Как и все асинхронные функции в этом API, Document.setSelectedDataAsync принимает объект options, содержащий дополнительные параметры, но эти параметры для его объекта options отличаются от тех, которые используются для других асинхронных функций в API, так как предназначение этой функции - присваивать данные. Поэтому дополнительные параметры Document.setSelectedDataAsync связаны с присваиванием данных:

  • coercionType - перечисление, которое указывает формат вставляемых вами данных (text, HTML, OOXML, table или matrix);
  • asyncContext - пользовательский объект, который возвращается неизменным в объекте AsyncResult, переданном в функции обратного вызова как ее единственный параметр.

Та же концепция применяется ко всем остальным асинхронным функциям.

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

Передача параметра options, подставляемого в строку:

  1. function setData(data) {
  2.   Office.context.document.setSelectedDataAsync(data, {
  3.   coercionType: Office.CoercionType.Text }  
  4.   );
  5. }

Передача параметра options в JavaScript-объекте:

  1. function setData(data) {
  2.   var options = { coercionType: Office.CoercionType.Text };
  3.   Office.context.document.setSelectedDataAsync(data, options );
  4. }

Роль объекта AsyncResult в асинхронных функциях Третий параметр в общей сигнатуре асинхронных функций в JavaScript API for Office - необязательный callback. Смысл этого параметра callback точно соответствует тому, как он назван: это передаваемая вами функция, которая вызывается по окончании выполнения асинхронной операции. Конечно, вы можете указать либо именованную функцию, либо анонимную функцию, подставляемую в строку вызова асинхронной функции. Здесь важно отметить роль объекта AsyncResult в отношении этой функции обратного вызова.

Когда исполняющая среда вызывает вашу функцию обратного вызова, она передает ей объект AsyncResult в качестве единственного аргумента. Объект AsyncResult содержит информацию об асинхронной операции, например, успешно ли выполнена операция, были ли ошибки и какие, возвращаемое значение асинхронной функции, если таковое есть. По сути, во всех асинхронных функциях, возвращающих какие-либо данные или объект, AsyncResult - единственный способ получения вами возвращаемого значения. Для этого используется свойство AsyncResult.value.

Так, в следующем фрагменте кода вы получаете размер документа и отображаете его в указанном HTML-элементе в UI приложения. Чтобы получить размер файла, вы сначала получаете объект файла, возвращаемый методом Document.getFileAsync через свойство AsyncResult.value. Вот как это делается:

  1. function getFileData(elementId) {
  2.   Office.context.document.getFileAsync(Office.FileType.Text,
  3.   function (asyncResult) {
  4.     if (asyncResult.status === 'succeeded') {
  5.       var myFile = asyncResult.value;
  6.       $(elementId).val(myFile.size);
  7.     }
  8.   });
  9. }

Функция getFileData вызывает метод Document.getFileAsync, указывая, что он должен вернуть контент файла как текст. Затем она использует свойство value объекта AsyncResult, переданного анонимной функции обратного вызова, чтобы получить ссылку на объект File. Далее она отображает размер файла в заданном элементе, используя свойство size объекта File. Аналогичным образом вы будете использовать свойство AsyncResult.value для получения возвращаемого значения любой асинхронной функции в приложениях для Office API.

Подробнее о методе Document.getFileAsync мы поговорим в следующей статье из этой серии.

Иерархия объектной модели

JavaScript API for Office нацелен на обеспечение совместимости между разными версиями Office и разными хост-приложениями. Для достижения этих целей JavaScript API предоставляет компактную объектную модель с четкой иерархией, не связанную напрямую ни с одним конкретным хост-приложением. Вместо этого объектная модель содержит адресный набор средств для взаимодействия с документами Office, соответствующих типу использующего данные документы приложения (область задач, контент или почтовое приложение).

На рис. 1 дана сокращенная схема иерархии объектов верхнего уровня в JavaScript API for Office (заметьте, что здесь не показана полная объектная модель). В частности, эта схема демонстрирует взаимосвязи между объектами Office, Context, Document, Settings, Mailbox и RoamingSettings.

Иерархия объектной модели в JavaScript API for Office
Рис. 1. Иерархия объектной модели в JavaScript API for Office

Extends Document object Расширяет объект Document

Каждое хост-приложение (Word, Excel, Excel Web App, PowerPoint, Project, Outlook и Outlook Web App) может использовать подмножество возможностей, включенных в этот API. Например, около 40% объектной модели отводится исключительно почтовым приложениям, которые могу быть задействованы только в Outlook и Outlook Web App. Другая часть объектной модели позволяет взаимодействовать с Custom XML Parts (собственными XML-фрагментами), доступными лишь в Word 2013. В табл. 1 перечислены возможности, доступные в конкретных хост-приложениях.Табл. 1. Возможности JavaScript API for Office, доступные в конкретных хост-приложениях

Возможность  Word  Excel/Excel Web App  PowerPoint  Outlook/Outlook Web App  Project 
Получение/задание данных как текста, таблицы, матрицы Все Все Только текст   Только текст
Объект Settings Все Все Все (RoamingSettings)  
Получение файла Все   Только в сжатой форме    
Привязки Все Все      
Собственные XML-фрагменты Все        
HTML и OOXML Все        
Почтовый ящик       Все  

Общие объекты в объектной модели В JavaScript API for Office есть строго определенная точка входа - объект Office, доступный приложениям всех типов и во всех хост-приложениях. Объект Office представляет определенный экземпляр приложения и вставляется в документ, рабочую книгу, презентацию, проект, почтовое сообщение или назначение (appointment). Ему доступны привязки между приложением и документом через метод select. (О привязках мы поговорим подробнее в следующей статье.) Самое важное, что объект Office предоставляет событие initialize для приложения, которое позволяет вам создавать логику инициализации приложения (об этом - тоже в следующей статье). Наконец, объект Office содержит ссылку на объект Context для приложения.

Объект Context, также доступный приложениям всех типов и во всех хост-приложениях, содержит информацию об исполняющей среде, в которой размещено приложение. Помимо хранения языковых настроек для приложения, объект Context предоставляет точку входа для использования возможностей JavaScript API for Office, специфичных для хоста, в котором было активировано приложение.

Например, вы можете обращаться к документу (объекту Document), сопоставленному с приложением, через свойство Context.document. Однако это свойство возвращает значение, только когда вызывается из хост-приложения, которое поддерживает его, т. е. из приложения области задач или контента. Если попытаться обратиться к свойству Context.document из почтового приложения, будет получена ошибка "undefined object" (неопределенный объект). Аналогично дело обстоит и со свойством Context.mailbox: в почтовом приложении оно возвращает почтовый ящик (объект Mailbox), открытый в хост-приложении. В приложении области задач оно будет неопределенным.

Поддержка приложений области задач и контента в объектной модели В случае приложений области задач и контента объект Document представляет документ, рабочую книгу, презентацию или проект, в который было вставлено приложение. Объект Document обеспечивает высший уровень доступа к контенту файла - фактически это основная точка контакта между приложением и документом Office.

Почти все способы доступа к контенту в документе Office требуют использования объекта Document. По этой причине вам может понадобиться получение ссылки на объект Document при инициализации приложении, как показано на рис. 2.

Рис. 2. Сохранение ссылки на объект Document при инициализации приложения

  1. // Проверка доступности объекта Settings в хост-приложении
  2. if (Office.context.document.settings) {
  3.   // Здесь реализация, использующая объект Settings
  4. }
  5. else {
  6.   // Переключаемся на другой способ сохранения собственных
  7.   // свойств, например localStorage, sessionStorage или cookie
  8. }

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

Объектом Document также предоставляется объект Settings, который представляет "контейнер свойств" ("property bag") для приложения. Приложение может хранить и сохранять собственные свойства между сеансами выполнения в том же документе, используя объект Settings. Эти свойства "путешествуют" вместе с документом: если вы используете какой-то файл Office, содержащий приложение, совместно с кем-то еще, то собственные свойства, хранящиеся в приложении, будут доступны, когда другое лицо откроет этот файл.

Сохранять и получать настройки с помощью контейнера свойств довольно просто. Метод Settings.set создает настройку в памяти как пару "ключ-значение". Чтобы получить свойства из контейнера, мы используем метод Settings.get, передавая имя (ключ) настройки; это дает нам соответствующее значение. Оба метода (set и get) синхронные. Для сохранения настроек между сеансами нужно вызывать метод Settings.saveAsync, который сохраняет все собственные свойства, содержащиеся в приложении, при сохранении документа.

В образце кода "Apps for Office: Persist custom settings" (bit.ly/UEiZff) вы найдете дополнительные примеры того, как использовать объект Settings и как сохранять данные в приложении.

Поддержка почтовых приложений в объектной модели Объект Mailbox предоставляет точку входа для доступа к данным и функциональности, специфичным для почтовых приложений. Как и подразумевает его имя, объект Mailbox соответствует почтовому ящику текущего пользователя и передается любым пользователям, читающим его сообщения электронной почты либо в клиентском приложении Outlook, либо в Outlook Web App. Кроме доступа к индивидуальным сообщениям электронной почты и назначениям (через свойство Mailbox.item), объект Mailbox обеспечивает приложению возможность создавать новые назначения, обращаться к профилю локального пользователя и даже получать местное время для этого пользователя.

Как и в случае объекта Document для приложений области задач и контента, вам может потребоваться получение ссылки на объект Mailbox при инициализации приложения (рис. 3).

Рис. 3. Сохранение ссылки на объект Mailbox в глобальной переменной при инициализации приложения

  1. // Добавляем обработчик к событию initialize в объекте Office
  2. Office.initialize = function (reason) {
  3.   $(document).ready(function () {
  4.     app.get_Mailbox(Office.context.mailbox);
  5.      // Здесь размещается остальная логика инициализации
  6.   })
  7. }
  8. // Используем немедленно вызываемую анонимную функцию, которая
  9. // инкапсулирует функциональность, задействованную приложением
  10. var app = (function () {
  11.   var _mailbox;
  12.   function get_Mailbox(mailbox) {
  13.     _mailbox = mailbox;
  14.   }
  15.   // Остальные поля и функции, связанные с приложением
  16.  return {
  17.     get_Mailbox: get_Mailbox
  18.     // Другие предоставляемые члены
  19.   };
  20. })()

Объект RoamingSettings, также доступный только в почтовых приложениях, аналогичен объекту Settings для приложений, ориентированных на документы (приложений области задач и контента). Он позволяет приложениям сохранять собственные свойства между сеансами как пары "имя-значение". Однако в отличие от объекта Settings, который сохраняет собственные свойства в файле хоста Office, объект RoamingSettings сохраняет настройки в почтовом ящике текущего пользователя. Благодаря этому собственные свойства доступны приложению независимо от того, какое сообщение просматривает пользователь или каким способом пользователь обращается к своему почтовому ящику (в Outlook или Outlook Web App).

Подробнее об иерархии объектной модели в JavaScript API for Office см. страницу "Understanding the JavaScript API for Office" (bit.ly/UV2POY) в документации MSDN.

Проверка наличия какой-либо возможности в хост-приложении

Как мы ранее упоминали, одна из сильных сторон JavaScript API for Office заключается в основном принципе приложений для Office: "Пишется один раз, работает везде". Например, одно и то же приложение области задач можно активировать в Word, Excel, Project и PowerPoint (при условии, что его манифест разрешает все эти возможности).

Однако, поскольку не всем приложениям доступен одинаковый список возможностей, в хост-приложение могло бы быть включено приложение, требующее тех возможностей, которых нет в этом хосте. Так, Project в настоящее время не предоставляет доступа к объекту Settings. Приложение, которое пытается обратиться к объекту Settings, при вставке в Project приведет к ошибке "undefined object".

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

  1. // Проверка доступности объекта Settings в хост-приложении
  2. if (Office.context.document.settings) {
  3.   // Здесь реализация, использующая объект Settings
  4. }
  5. else {
  6.   // Переключаемся на другой способ сохранения собственных
  7.   // свойств, например localStorage, sessionStorage или cookie
  8. }

Итак, в этой статье мы обсудили суть JavaScript API for Office. Мы описали высокоуровневую иерархию объектной модели и рассмотрели асинхронный шаблон, реализованный в этой модели. Мы также объяснили, как проверять доступность той или иной возможности в хост-приложении.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=36600