アドイン コマンドを有効または無効にする

アドインの一部の機能を特定のコンテキストでのみ使用可能にする必要がある場合、カスタム アドイン コマンドをプログラムで有効または無効にすることができます。 たとえば、表の見出しを変更する関数は、カーソルが表の中にある場合にのみ有効にする必要があります。

Office クライアント アプリケーションが開いたときにコマンドを有効にするか無効にするかを指定することもできます。

注:

この記事は、以下のドキュメントについて既に理解していることを前提としています。 最近、アドイン コマンド (カスタム メニュー項目とリボン ボタン) を使用してない場合は、ドキュメントをご確認ください。

Office アプリケーションとプラットフォームのサポート

この記事で説明する API は、 RibbonApi 1.1 要件セットの一部として Excel、PowerPoint、Word で使用できます。 現在、Web アプリケーションのリボン API は プレビュー段階です。 要件セットを使用してプラットフォーム サポートをテストする方法については、「 Office のバージョンと要件セット」を参照してください。

共有ランタイムが必要

この記事で説明する API とマニフェスト マークアップでは、アドインのマニフェストで 共有ランタイムを使用するように指定する必要があります。 これを行うには、次の手順を実行します。

  1. マニフェストの Runtimes 要素で、子要素の <Runtime resid="Contoso.SharedRuntime.Url" lifetime="long" /> を追加します。 (マニフェストに <Runtimes> 要素がまだない場合は、<VersionOverrides> セクションの <Host> 要素の下に最初の子として作成します)。

  2. マニフェストの Resources.Urls セクションで、子要素の <bt:Url id="Contoso.SharedRuntime.Url" DefaultValue="https://{MyDomain}/{path-to-start-page}" /> を追加します。ここでは、{MyDomain} はアドインのドメインで、{path-to-start-page} はアドインの開始ページのパスになります (例: <bt:Url id="Contoso.SharedRuntime.Url" DefaultValue="https://localhost:3000/index.html" />)。

  3. アドインに作業ウィンドウ、関数ファイル、または Excel カスタム関数が含まれているかどうかに応じて、次の 3 つの手順のうち 1 つ以上を実行する必要があります。

    • アドインに作業ウィンドウが含まれている場合は、[アクション] のresid属性を設定します手順 1 の <Runtime> 要素のresidに使用したのとまったく同じ文字列に対する SourceLocation 要素。たとえば、Contoso.SharedRuntime.Url。 そうすると要素は <SourceLocation resid="Contoso.SharedRuntime.Url"/> のようになります。
    • アドインに Excel カスタム関数が含まれている場合は、Page のresid属性を設定しますSourceLocation 要素は、手順 1 の <Runtime> 要素のresidに使用したものとまったく同じ文字列です(たとえば、Contoso.SharedRuntime.Url)。 そうすると要素は <SourceLocation resid="Contoso.SharedRuntime.Url"/> のようになります。
    • アドインに関数ファイルが含まれている場合は、FunctionFile 要素のresid属性を、手順 1 の <Runtime> 要素のresidに使用した文字列とまったく同じ文字列に設定します (例: Contoso.SharedRuntime.Url)。 そうすると要素は <FunctionFile resid="Contoso.SharedRuntime.Url"/> のようになります。

既定の状態を無効に設定する

既定では、Office アプリケーションの起動時にすべてのアドイン コマンドが有効になります。 Office アプリケーションの起動時にカスタム ボタンまたはメニュー項目を無効にするには、マニフェストで指定します。 コントロールの宣言の Action 要素の直下 (内部ではない) に、Enabled 要素 (値は false) を追加するだけで無効にすることができます。 基本的な構造を次に示します。

<OfficeApp ...>
  ...
  <VersionOverrides ...>
    ...
    <Hosts>
      <Host ...>
        ...
        <DesktopFormFactor>
          <ExtensionPoint ...>
            <CustomTab ...>
              ...
              <Group ...>
                ...
                <Control ... id="Contoso.MyButton3">
                  ...
                  <Action ...>
                  <Enabled>false</Enabled>
...
</OfficeApp>

プログラムで状態を変更する

アドイン コマンドの有効な状態を変更するには、以下の手順が重要になります。

  1. (1) コマンドとその親グループとタブをマニフェストで宣言された ID で指定する RibbonUpdaterData オブジェクトを作成します。および (2) は、コマンドの有効または無効の状態を指定します。
  2. RibbonUpdaterData オブジェクトを Office.ribbon.requestUpdate() メソッドに渡します。

次に簡単な例を示します。 "MyButton"、"OfficeAddinTab1"、および "CustomGroup111" がマニフェストからコピーされることに注意してください。

function enableButton() {
    Office.ribbon.requestUpdate({
        tabs: [
            {
                id: "OfficeAppTab1", 
                groups: [
                    {
                      id: "CustomGroup111",
                      controls: [
                        {
                            id: "MyButton", 
                            enabled: true
                        }
                      ]
                    }
                ]
            }
        ]
    });
}

また、RibbonUpdateData オブジェクトを簡単に構築できるように、いくつかのインターフェイスも (何種類か) 用意しています。 以下は、TypeScript の同じ例であり、インターフェイスを使用したものです。

const enableButton = async () => {
    const button: Control = {id: "MyButton", enabled: true};
    const parentGroup: Group = {id: "CustomGroup111", controls: [button]};
    const parentTab: Tab = {id: "OfficeAddinTab1", groups: [parentGroup]};
    const ribbonUpdater: RibbonUpdaterData = { tabs: [parentTab]};
    Office.ribbon.requestUpdate(ribbonUpdater);
}

親関数が非同期の場合は requestUpdate() の呼び出しをawaitできますが、Office アプリケーションはリボンの状態を更新するときに制御されることに注意してください。 requestUpdate () メソッドが、更新の要求をキューイングします。 メソッドは、リボンが実際に更新されたときではなく、要求をキューに入れるとすぐに promise オブジェクトを解決します。

イベントに応じて状態を変更する

リボンの状態を変更する一般的なシナリオは、ユーザーが開始したイベントがアドインのコンテキストを変更したときです。

グラフがアクティブになったときにのみボタンを有効にするシナリオを考えます。 まず、マニフェストのボタンの Enabled 要素を false に設定します。 例については上記を参照してください。

次に、ハンドラーを割り当てます。 これは一般的に、次の例のように Office.onReady 関数で実行されます。これは、ワークシート内のすべてのグラフの onActivated イベントと onDeactivated イベントにハンドラー (後の手順で作成) を割り当てます。

Office.onReady(async () => {
    await Excel.run(context => {
        const charts = context.workbook.worksheets
            .getActiveWorksheet()
            .charts;
        charts.onActivated.add(enableChartFormat);
        charts.onDeactivated.add(disableChartFormat);
        return context.sync();
    });
});

そして、enableChartFormat ハンドラーを定義します。 以下は簡単な例ですが、より信頼性の高い方法でコントロールの状態を変更する場合については、後述の「ベスト プラクティス: コントロールの状態エラーのテスト」を参照してください。

function enableChartFormat() {
    const button = {
                  id: "ChartFormatButton", 
                  enabled: true
                 };
    const parentGroup = {
                       id: "MyGroup",
                       controls: [button]
                      };
    const parentTab = {
                     id: "CustomChartTab", 
                     groups: [parentGroup]
                    };
    const ribbonUpdater = {tabs: [parentTab]};
    Office.ribbon.requestUpdate(ribbonUpdater);
}

最後に、disableChartFormat ハンドラーを定義します。 enableChartFormat と同じですが、ボタン オブジェクトの enabled プロパティを false に設定する必要があります。

タブの表示とボタンの有効な状態を同時に切り替える

requestUpdate メソッドは、カスタム コンテキスト タブの表示を切り替えるためにも使用されます。このコードとコード例の詳細については、「Office アドインでカスタム コンテキスト タブを作成する」を参照してください。

ベスト プラクティス: コントロールの状態エラーのテスト

状況によっては、requestUpdate が呼び出された後でもリボンが再描画されず、コントロールのクリック可能な状態が変更されない場合があります。 そこで、アドインのベスト プラクティスとして、コントロールの状態を追跡することが挙げられます。 アドインは、次の規則に準拠している必要があります。

  1. requestUpdate が呼び出された場合はいつでも、コードがカスタム ボタンとメニュー項目の意図した状態を記録する必要があります。
  2. カスタム コントロールがクリックされたら、ハンドラーの最初のコードが、ボタンがクリック可能になっているかどうかを確認する必要があります。 クリック可能でない場合は、コードがエラーの報告または記録を行い、ボタンを意図した状態に設定し直す必要があります。

次の例は、ボタンを無効にし、ボタンの状態を記録する関数を示しています。 chartFormatButtonEnabled は、マニフェスト内のボタンの Enabled 要素と同じ値に初期化されるグローバルなブール変数です。

function disableChartFormat() {
    const button = {
                  id: "ChartFormatButton", 
                  enabled: false
                 };
    const parentGroup = {
                       id: "MyGroup",
                       controls: [button]
                      };
    const parentTab = {
                     id: "CustomChartTab", 
                     groups: [parentGroup]
                    };
    const ribbonUpdater = {tabs: [parentTab]};
    Office.ribbon.requestUpdate(ribbonUpdater);

    chartFormatButtonEnabled = false;
}

次の例は、ボタンのハンドラーがボタンの不正な状態をテストする方法を示しています。 reportError は、エラーを表示または記録する関数です。

function chartFormatButtonHandler() {
    if (chartFormatButtonEnabled) {

        // Do work here

    } else {
        // Report the error and try again to disable.
        reportError("That action is not possible at this time.");
        disableChartFormat();
    }
}

エラー処理

一部のシナリオでは、Office はリボンを更新できず、エラーを返します。 たとえば、アドインがアップグレードされ、アップグレードされたアドインに異なるカスタム アドイン コマンドのセットがある場合は、Office アプリケーションを閉じてから、もう一度開く必要があります。 それまでの間、requestUpdate メソッドは HostRestartNeeded エラーを返します。 このエラーの処理方法の例を次に示します。 この場合、reportError メソッドがユーザーにエラーを表示します。

function disableChartFormat() {
    try {
        const button = {
                      id: "ChartFormatButton", 
                      enabled: false
                     };
        const parentGroup = {
                           id: "MyGroup",
                           controls: [button]
                          };
        const parentTab = {
                         id: "CustomChartTab", 
                         groups: [parentGroup]
                        };
        const ribbonUpdater = {tabs: [parentTab]};
        Office.ribbon.requestUpdate(ribbonUpdater);

        chartFormatButtonEnabled = false;
    }
    catch(error) {
        if (error.code == "HostRestartNeeded"){
            reportError("Contoso Awesome Add-in has been upgraded. Please save your work, close the Office application, and restart it.");
        }
    }
}