Использование Office Dialog API в надстройках Office

Используйте API диалогового окна Office для открытия диалоговых окон в надстройке Office. Эта статья содержит инструкции по использованию dialog API в надстройке Office. Попробуйте открыть диалоговое окно из области задач, контентной надстройки или команды надстройки , чтобы сделать следующее:

  • Войдите в систему пользователя с помощью ресурса, например Google, Facebook или удостоверения Майкрософт. Дополнительные сведения см. в статье Проверка подлинности с помощью API диалогового окна Office.
  • предоставить больше места на экране (или даже весь экран) для некоторых задач в надстройке;
  • разместить видео, которое будет слишком маленьким в области задач.

Совет

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

На приведенном ниже изображении показан пример диалогового окна.

Диалоговое окно входа с платформа удостоверений Майкрософт в Word.

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

Примечание.

Если вы разрабатываете надстройку, которая работает в Office в Интернете или новом Outlook в Windows и требует доступа к возможностям устройства пользователя, ознакомьтесь с API разрешений устройства, чтобы узнать, как запрашивать у пользователя разрешения. К возможностям устройства относятся камера пользователя, географическое расположение и микрофон.

Откройте диалоговое окно с главной страницы

Office JavaScript API включает в себя Диалоговый объекта и две функции в Office.context.ui namespace.

Чтобы открыть диалоговое окно, ваш код, обычно страница в панели задач, вызывает метод displayDialogAsync и передает ему URL-адрес ресурса, который вам нужно открыть. Страница, на которой этот метод вызван, называется "главной страницей". Например, если вы вызываете этот метод в скрипте для index.html на панели задач, то index.html - это главная страница диалогового окна, которое открывает метод.

Ресурс, который открывается в диалоговом окне, обычно представляет собой страницу, но это может быть метод контроллера в приложении MVC, маршрут, метод веб-службы или любой другой ресурс. В этой статье "страница" или "веб-сайт" ссылается на ресурс в диалоговом окне. Ниже приведен простой пример кода.

Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html');
  • В случае URL-адреса используется протокол HTTPS, Обязательный для всех страниц, загружаемых в диалоговом окне, а не только для первой страницы.
  • Домен диалогового окна совпадает с доменом главной страницы, которая может быть страницей в панели задач или файлом функции команды надстройки. Необходимо, чтобы страница, метод контроллера или другой ресурс, передаваемый displayDialogAsync в метод, должны находиться в том же домене, что и хост-страница.

Важно!

Главная страница и ресурс, который открывается в диалоговом окне, должны иметь один и тот же полный домен. Если попытаться передать displayDialogAsync поддомен домена надстройки, он не будет работать. Полные доменные имена, включая поддомены, должны совпадать.

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

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

Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', { height: 30, width: 20 });

Пример надстройки, которая делает это, см. в статье Создание надстроек Office для Excel. Дополнительные примеры, использующие displayDialogAsync, см. в разделе Примеры кода.

Установите оба значения равными 100 %, чтобы надстройка открывалась во весь экран. Действующий максимум составляет 99,5 %, а окно по-прежнему перемещается и изменяет размер.

В окне узла можно открыть только одно диалоговое окно. При попытке открыть другое диалоговое окно возникает ошибка. Например, если пользователь открывает диалоговое окно из области задач, он не может открыть второе диалоговое окно с другой страницы в области задач. Однако при открытии диалогового окна из команды надстройки команда открывает новый (но невидимый) HTML-файл каждый раз при его выборе. При этом создается новое (невидимое) основное окно, поэтому каждое такое окно может запускать собственное диалоговое окно. Дополнительные сведения см. в разделе Ошибки из displayDialogAsync.

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

displayInIframe — дополнительное свойство в объекте конфигурации, которое можно передать displayDialogAsync. Когда этому свойству присвоено значение true, а надстройка запущена для документа в Office в Интернете, диалоговое окно будет открываться быстрее, потому что будет выступать как плавающий фрейм iframe. Ниже приведен пример.

Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', { height: 30, width: 20, displayInIframe: true });

Значение по умолчанию: false. Его использование равнозначно пропуску всего свойства. Если надстройка не запущена в Office в Интернете, displayInIframe она игнорируется.

Примечание.

Не следует использовать, displayInIframe: true если диалоговое окно будет в любой момент перенаправлять на страницу, которая не может быть открыта в iframe. Например, страницы входа многих популярных веб-служб, таких как Google и учетная запись Майкрософт, не могут быть открыты в iframe.

Отправка сведений из диалогового окна главной странице

Код в диалоговом окне использует функцию messageParent для отправки строкового сообщения на хост-страницу. Строка может быть словом, предложением, BLOB-объектом XML, строкифицированным JSON или другими объектами, которые можно сериализовать в строку или привести к строке. Чтобы использовать messageParent метод , диалоговое окно должно сначала инициализировать API JavaScript для Office.

Примечание.

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

В следующем примере показано, как инициализировать Office JS и отправить сообщение на хост-страницу.

Office.onReady(() => {
   // Add any initialization code for your dialog here.
});

// Called when dialog signs in the user.
function userSignedIn() {
    Office.context.ui.messageParent(true.toString());
}

В следующем примере показано, как вернуть строку JSON, содержащую сведения о профиле.

function userProfileSignedIn(profile) {
    const profileMessage = {
        "name": profile.name,
        "email": profile.email,
    };
    Office.context.ui.messageParent(JSON.stringify(profileMessage));
}

Эта messageParent функция является одним из двух API Office JS, которые можно вызвать в диалоговом окне. Другой API JS, который можно вызвать в диалоговом окне, — .Office.context.requirements.isSetSupported Дополнительные сведения см. в статье Указание приложений Office и требований к API. Однако в диалоговом окне этот API не поддерживается в корпоративной лицензированной бессрочной Outlook 2016 (то есть в версии MSI).

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

let dialog; // Declare dialog as global for use in later functions.
Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', { height: 30, width: 20 },
    (asyncResult) => {
        dialog = asyncResult.value;
        dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
    }
);

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

  • Для свойства value объекта asyncResult задан объект Dialog, который существует на главной странице, а не в контексте выполнения диалогового окна.
  • processMessage — это функция, которая обрабатывает событие. Вы можете присвоить ей любое имя.
  • Переменная dialog объявляется в более широком контексте, чем обратный вызов, так как на нее также ссылается processMessage.

Ниже приведен простой пример обработчика для события DialogMessageReceived.

function processMessage(arg) {
    const messageFromDialog = JSON.parse(arg.message);
    showUserName(messageFromDialog.name);
}

Office передает объект arg в обработчик. Его message свойство представляет собой строку, отправляемую вызовом messageParent в диалоговом окне. В этом примере это строковое представление профиля пользователя из службы, например учетной записи Майкрософт или Google, поэтому он десериализируется обратно в объект с JSON.parseпомощью . Реализация showUserName не отображается. Она может отображать персонализированное приветствие в области задач.

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

function processMessage(arg) {
    dialog.close();
    // Add code to process the message here.
}

Объект dialog должен быть таким же, как объект, который возвращается при вызове displayDialogAsync. Необходимо объявить dialog объект как глобальную переменную. Или можно область объект к dialog вызову displayDialogAsync с анонимной функцией обратного вызова, как показано в следующем примере. В примере не нужно закрывать диалоговое окно, processMessage так как close метод вызывается в функции анонимного обратного вызова.

Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html', { height: 30, width: 20 },
    (asyncResult) => {
        const dialog = asyncResult.value;
        dialog.addEventHandler(Office.EventType.DialogMessageReceived, (arg) => {
            dialog.close();
            processMessage(arg);
        });
      }
    );

Если надстройка должна открыть другую страницу области задач после получения сообщения, можно использовать метод window.location.replace (или window.location.href) в последней строке обработчика. Ниже приведен пример.

function processMessage(arg) {
    // Add code to process the message here.
    window.location.replace("/newPage.html");
    // Alternatively, use the following:
    // window.location.href = "/newPage.html";
}

Пример подобной надстройки см. в статье Вставка диаграмм Excel с помощью Microsoft Graph в надстройке PowerPoint.

Условные сообщения

Так как из диалогового окна можно отправить несколько вызовов messageParent, но на главной странице есть только один обработчик для события DialogMessageReceived, обработчику необходимо использовать условную логику, чтобы различать сообщения. Например, если диалоговое окно предлагает пользователю войти в поставщик удостоверений, например учетную запись Майкрософт или Google, оно отправляет профиль пользователя в виде сообщения. В случае сбоя проверки подлинности диалоговое окно отправляет сведения об ошибке на хост-страницу, как показано в следующем примере.

if (loginSuccess) {
    const userProfile = getProfile();
    const messageObject = { messageType: "signinSuccess", profile: userProfile };
    const jsonMessage = JSON.stringify(messageObject);
    Office.context.ui.messageParent(jsonMessage);
} else {
    const errorDetails = getError();
    const messageObject = { messageType: "signinFailure", error: errorDetails };
    const jsonMessage = JSON.stringify(messageObject);
    Office.context.ui.messageParent(jsonMessage);
}

Что касается предыдущего примера, обратите внимание:

  • Переменная loginSuccess будет инициализирована после считывания отклика HTTP от поставщика удостоверений.
  • Реализация getProfile функций и getError не отображается. Они получают данные из параметра запроса или ответа HTTP.
  • В зависимости от того, удалось ли выполнить вход, отправляются анонимные объекты различных типов. Оба содержат свойство messageType, но один содержит свойство profile, а другой — свойство error.

Код обработчика на главной странице использует значение свойства messageType для разветвления, как показано в приведенном ниже примере. Обратите внимание на то, что здесь используется та же функция showUserName, что и в примере выше, а функция showNotification отображает сообщение об ошибке в элементе пользовательского интерфейса на главной странице.

function processMessage(arg) {
    const messageFromDialog = JSON.parse(arg.message);
    if (messageFromDialog.messageType === "signinSuccess") {
        dialog.close();
        showUserName(messageFromDialog.profile.name);
        window.location.replace("/newPage.html");
    } else {
        dialog.close();
        showNotification("Unable to authenticate user: " + messageFromDialog.error);
    }
}

Реализация showNotification не отображается. Состояние может отображаться на панели уведомлений в области задач.

Обмен сообщениями между доменами в среду выполнения узла

После открытия диалогового окна диалоговое окно или родительская среда выполнения может уйти из домена надстройки. Если произойдет одно из этих действий, вызов messageParent завершится ошибкой, если в коде не указан домен родительской среды выполнения. Для этого добавьте параметр DialogMessageOptions в вызов messageParent. Этот объект имеет targetOrigin свойство, указывающее домен, в который должно быть отправлено сообщение. Если параметр не используется, Office предполагает, что целевой объект является тем же доменом, который сейчас размещается в диалоговом окне.

Примечание.

Для messageParent отправки междоменного сообщения требуется набор обязательных элементов Dialog Origin 1.1. Параметр DialogMessageOptions игнорируется в более старых версиях Office, которые не поддерживают набор требований, поэтому поведение метода не влияет на его передачу.

Ниже приведен пример использования для messageParent отправки междоменного сообщения.

Office.context.ui.messageParent("Some message", { targetOrigin: "https://resource.contoso.com" });

Если сообщение не содержит конфиденциальные данные, можно задать для targetOrigin параметра значение "*", что позволяет отправлять его в любой домен. Ниже приведен пример.

Office.context.ui.messageParent("Some message", { targetOrigin: "*" });

Совет

  • Параметр DialogMessageOptions был добавлен в метод в качестве обязательного messageParent параметра в середине 2021 года. Старые надстройки, отправляющие междоменные сообщения с помощью метода, больше не работают, пока не будут обновлены для использования нового параметра. Пока надстройка не будет обновлена, только в Office в Windows пользователи и системные администраторы могут разрешить этим надстройкам продолжать работу, указав доверенные домены с параметром реестра :HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\AllowedDialogCommunicationDomains. Для этого создайте файл с расширением .reg , сохраните его на компьютере с Windows, а затем дважды щелкните его, чтобы запустить его. Ниже приведен пример содержимого такого файла.

    Windows Registry Editor Version 5.00
    
    [HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\AllowedDialogCommunicationDomains]
    "My trusted domain"="https://www.contoso.com"
    "Another trusted domain"="https://fabrikam.com"
    
  • В Office в Интернете и новом Outlook в Windows, если домен вашего диалога отличается от домена надстройки и применяет заголовок ответа Cross-Origin-Opener-Policy: same-origin-origin response, надстройка будет заблокирована для доступа к сообщениям из диалогового окна, а пользователи получат сообщение об ошибке 12006. Чтобы избежать этого, необходимо задать для заголовка Cross-Origin-Opener-Policy: unsafe-none значение или настроить надстройку и диалоговое окно в одном домене.

Передача данных диалоговому окну

Надстройка может отправлять сообщения с главной страницы в диалоговое окно с помощью Dialog.messageChild.

Использование messageChild() с главной страницы

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

let dialog; // Declare as global variable.
Office.context.ui.displayDialogAsync('https://www.contoso.com/myDialog.html',
    (asyncResult) => {
        dialog = asyncResult.value;
        dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
    }
);

function processMessage(arg) {
    dialog.close();

    // Add code to process the message here.

}

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

Рассмотрим сценарий, в котором пользовательский интерфейс диалогового окна связан с текущим активным листом Excel и положением этого листа относительно других листов. В следующем примере worksheetPropertiesChanged отправляет свойства активного листа в диалоговое окно. Данные строчены таким образом, что они могут быть переданы в messageChild.

await Excel.run(async (context) => {
    const worksheet = context.workbook.worksheets.getActiveWorksheet();
    worksheet.load();
    await context.sync();
    worksheetPropertiesChanged(worksheet);
});

...

function worksheetPropertiesChanged(currentWorksheet) {
    const messageToDialog = JSON.stringify(currentWorksheet);
    dialog.messageChild(messageToDialog);
}

Дескриптор DialogParentMessageReceived в диалоговом окне

В JavaScript диалогового окна зарегистрируйте обработчик для DialogParentMessageReceived события с помощью метода UI.addHandlerAsync . Обычно это выполняется с помощью функции Office.onReady или Office.initialize, как показано ниже. (Более надежный пример приведен далее в этой статье.)

Office.onReady(() => {
    Office.context.ui.addHandlerAsync(Office.EventType.DialogParentMessageReceived,onMessageFromParent);
});

Затем определите onMessageFromParent обработчик. Следующий код продолжает пример из предыдущего раздела. Обратите внимание, что Office передает аргумент обработчику, message а свойство объекта argument содержит строку с главной страницы. В этом примере сообщение перевернуто в объект, а jQuery используется для задания верхнего заголовка диалогового окна в соответствии с новым именем листа.

function onMessageFromParent(arg) {
    const messageFromParent = JSON.parse(arg.message);
    document.querySelector('h1').textContent = messageFromParent.name;
}

Рекомендуется проверить правильность регистрации обработчика. Это можно сделать, передав обратный вызов методу addHandlerAsync . Он выполняется по завершении попытки регистрации обработчика. Используйте обработчик для регистрации или отображения ошибки, если обработчик не был успешно зарегистрирован. Ниже приведен пример. Обратите внимание, что reportError это функция, не определенная здесь, которая регистрирует или отображает ошибку.

Office.onReady(() => {
    Office.context.ui.addHandlerAsync(
        Office.EventType.DialogParentMessageReceived,
        onMessageFromParent,
        onRegisterMessageComplete
    );
});

function onRegisterMessageComplete(asyncResult) {
    if (asyncResult.status !== Office.AsyncResultStatus.Succeeded) {
        reportError(asyncResult.error.message);
    }
}

Условное обмен сообщениями с родительской страницы в диалоговое окно

Так как можно выполнить несколько messageChild вызовов с главной страницы, но в диалоговом окне для DialogParentMessageReceived события есть только один обработчик, обработчик должен использовать условную логику для различения разных сообщений. Это можно сделать таким образом, который точно соответствует структуре условного обмена сообщениями, когда диалоговое окно отправляет сообщение на хост-страницу, как описано в разделе Условные сообщения.

Примечание.

В некоторых ситуациях messageChild API, который входит в набор требований DialogApi 1.2, может не поддерживаться. Например, messageChild не поддерживается в корпоративных бессрочных Outlook 2016 и в Outlook 2019 с корпоративным бессрочным сроком. Некоторые альтернативные способы обмена сообщениями между родительскими окнами описаны в разделе Альтернативные способы передачи сообщений в диалоговое окно с его главной страницы.

Важно!

Набор требований DialogApi 1.2 нельзя указать в <разделе Требования> манифеста надстройки. Вам потребуется проверка для поддержки DialogApi 1.2 во время выполнения с помощью isSetSupported метода, как описано в разделе Проверка среды выполнения для поддержки метода и набора требований. Поддержка требований манифеста находится в разработке.

Обмен сообщениями между доменами в среду выполнения диалога

После открытия диалогового окна диалоговое окно или родительская среда выполнения может уйти из домена надстройки. Если произойдет одно из этих действий, вызовы к messageChild завершатся ошибкой, если в коде не указан домен среды выполнения диалога. Для этого добавьте параметр DialogMessageOptions в вызов messageChild. Этот объект имеет targetOrigin свойство, указывающее домен, в который должно быть отправлено сообщение. Если параметр не используется, Office предполагает, что целевой домен является тем же доменом, который сейчас размещает родительская среда выполнения.

Примечание.

Для messageChild отправки междоменного сообщения требуется набор обязательных элементов Dialog Origin 1.1. Параметр DialogMessageOptions игнорируется в более старых версиях Office, которые не поддерживают набор требований, поэтому поведение метода не влияет на его передачу.

Ниже приведен пример использования для messageChild отправки междоменного сообщения.

dialog.messageChild(messageToDialog, { targetOrigin: "https://resource.contoso.com" });

Если сообщение не содержит конфиденциальные данные, можно задать для targetOrigin параметра значение "*", что позволяет отправлять его в любой домен. Ниже приведен пример.

dialog.messageChild(messageToDialog, { targetOrigin: "*" });

Так как среда выполнения, в которой размещено диалоговое окно, не может получить доступ к разделу <AppDomains> манифеста и тем самым определить, является ли домен, из которого поступает сообщение , доверенным, необходимо использовать DialogParentMessageReceived обработчик, чтобы определить это. Объект, передаваемый обработчику, содержит домен, который в настоящее время размещен в родительском объекте в качестве свойства origin . Ниже приведен пример использования свойства .

function onMessageFromParent(arg) {
    if (arg.origin === "https://addin.fabrikam.com") {
        // Process the message.
    } else {
        // Signal the parent page to close the dialog.
        const messageObject = { messageType: "untrustedDomain" };
        Office.context.ui.messageParent(messageObject);
    }
}

Например, код может использовать функцию Office.onReady или Office.initialize для хранения массива доверенных доменов в глобальной переменной. Затем arg.origin свойство можно проверить с этим списком в обработчике.

Совет

Параметр DialogMessageOptions был добавлен в метод в качестве обязательного messageChild параметра в середине 2021 года. Старые надстройки, отправляющие междоменные сообщения с помощью метода, больше не работают, пока не будут обновлены для использования нового параметра. Пока надстройка не будет обновлена, только в Office в Windows пользователи и системные администраторы могут разрешить этим надстройкам продолжать работу, указав доверенные домены с параметром реестра :HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\AllowedDialogCommunicationDomains. Для этого создайте файл с расширением .reg , сохраните его на компьютере с Windows, а затем дважды щелкните его, чтобы запустить его. Ниже приведен пример содержимого такого файла.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\WEF\AllowedDialogCommunicationDomains]
"My trusted domain"="https://www.contoso.com"
"Another trusted domain"="https://fabrikam.com"

Закрытие диалогового окна

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

function closeButtonClick() {
    const messageObject = { messageType: "dialogClosed" };
    const jsonMessage = JSON.stringify(messageObject);
    Office.context.ui.messageParent(jsonMessage);
}

Обработчик главной страницы для DialogMessageReceived вызовет dialog.close, как показано в этом примере. (См. предыдущие примеры, в которых показано, как dialog инициализируется объект).

function processMessage(arg) {
    const messageFromDialog = JSON.parse(arg.message);
    if (messageFromDialog.messageType === "dialogClosed") {
       dialog.close();
    }
}

Даже если у вас нет собственного пользовательского интерфейса для закрытия диалогового окна, пользователь может закрыть диалоговое окно, выбрав X в правом верхнем углу. Это действие запускает событие DialogEventReceived. Чтобы главная область могла реагировать на это событие, для нее должен быть объявлен обработчик этого события. Дополнительные сведения см. в разделе Ошибок и события в диалоговом окне.

Примеры кода

Во всех следующих примерах используется displayDialogAsync. Некоторые из них имеют серверы на основе NodeJS, а другие — серверы ASP.NET/IIS-based, но логика использования метода одинакова независимо от того, как реализована серверная часть надстройки.

См. также