次の方法で共有


Office.js を任意の JavaScript フレームワークに接続する

Office.js はフレームワークに依存せず、クライアント側の JavaScript フレームワークまたはライブラリとシームレスに連携します。 React、Angular、Vue、Svelte、またはその他のフレームワークを使用してビルドする場合でも、統合パターンは同じです。アプリケーションがレンダリングされる前に Office.js を初期化します。

注:

また、ASP.NET、PHP、Java などのサーバー側フレームワークを使用して Office アドインを構築することもできますが、この記事では取り上げません。 この記事では、特にブラウザーで実行されるクライアント側の JavaScript フレームワークに焦点を当てます。

この記事では、クライアント側の JavaScript フレームワークと Office.js を統合するためのユニバーサル パターン、重要な考慮事項、および複数のフレームワークにわたる例について説明します。

ヒント

この記事は、好みの JavaScript フレームワークを使用して Office アドインをゼロから作成したり、Office.js を既存のフレームワーク プロジェクトに統合したりする開発者向けに設計されています。 Office アドインまたは Microsoft 365 Agents Toolkit用 Yeoman ジェネレーターを使用している場合、これらのツールは正しい Office.js 構成を既に提供しています。

前提条件

クイック スタート: ユニバーサル パターン

選択したフレームワークに関係なく、次のパターンを使用します。

  1. HTML <head>の CDN から Office.js を参照します。
  2. Office.onReady()を呼び出し、完了するまで待ちます。
  3. Office.js の準備ができたらフレームワークを初期化します。
// Universal pattern - works with any framework.
Office.onReady((info) => {
  // Office.js is now ready.
  // Initialize your framework here.
  initializeYourFramework();
});

CDN から Office.js を読み込む

HTML ファイルのコンテンツ配信ネットワーク (CDN) から Office JavaScript API を参照する必要があります。 HTML ページの <head> セクションで、他のスクリプト タグまたはフレームワーク バンドル参照の前に、次の<script> タグを追加します。

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My Office Add-in</title>

  <!-- Office.js must be loaded from CDN, not bundled -->
  <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>

  <!-- Your framework bundle loads after Office.js -->
</head>

重要

  • CDN から Office.js を読み込み、HTML ファイルで参照します。 JavaScript または TypeScript コードにインポートしないでください。
  • Office.js 参照は、本文要素が読み込まれる前に API が完全に初期化されるように、 <head> セクションに表示する必要があります。
  • Office.js をアプリケーション コードとバンドルしないでください。 常に CDN から参照します。

プレビュー API や代替 CDN エンドポイントなど、Office.js の参照の詳細については、「 Office JavaScript API ライブラリの参照」を参照してください。

Office.onReady の後にフレームワークを初期化する

Office.js を任意のフレームワークと統合する鍵は、 Office.onReady() コールバック内でアプリケーションを初期化することです。 この方法により、フレームワークのレンダリングを開始する前に Office.js が完全に初期化されます。 この初期化は、次 Office.js 必要があるため重要です。

  • CDN から API ライブラリ ファイルをダウンロードしてキャッシュします。
  • Office ランタイム環境を初期化します。
  • Office アプリケーションとの通信を確立します。

Office.js 準備が整う前にフレームワークがレンダリングされた場合、Office API の呼び出しは失敗します。 Office.onReady()内でアプリケーションを初期化することで、アプリケーション コードの実行時に Office.js の準備が整うことになります。

次の例は、異なるフレームワーク間で同じ統合パターンを示しています。 パターンは同じです。フレームワークの初期化メソッドのみが変更されます。

React

// src/index.tsx
Office.onReady(() => {
  const root = ReactDOM.createRoot(document.getElementById('root'));
  root.render(<App />);
});

Angular

// src/main.ts
Office.onReady(() => {
  platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.error(err));
});

Vue

// src/main.ts
Office.onReady(() => {
  createApp(App).mount('#app');
});

スヴェルト

// src/main.ts
Office.onReady(() => {
  new App({ target: document.getElementById('app') });
});

フレームワークのないシンプルな JavaScript

// src/app.js
Office.onReady((info) => {
  document.getElementById('run-button').onclick = run;

  if (info.host === Office.HostType.Excel) {
    console.log('Running in Excel');
  }
});

アプリケーションで Office.js API を使用する

Office.js 初期化後 ( Office.onReady() が完了したら)、アドイン内の任意の場所で Office API を呼び出すことができます。 必要に応じ、フレームワークのライフサイクル フックまたはイベント ハンドラーを使用して Office API を呼び出します。

// React example: Call an Office JS API in the useEffect lifecycle hook.
import { useEffect, useState } from 'react';

function MyComponent() {
  const [data, setData] = useState('');

  useEffect(() => {
    loadData();
  }, []);

  async function loadData() {
    await Excel.run(async (context) => {
      const range = context.workbook.getSelectedRange();
      range.load('values');
      await context.sync();

      // Update component state with the data from Excel.
      const value = range.values[0][0];
      setData(value);
    });
  }

  return <div>Selected cell: {data}</div>;
}

// Similar patterns for other frameworks:
// Angular: ngOnInit() { this.loadData(); }
// Vue: onMounted(() => { loadData(); })
// Svelte: onMount(() => { loadData(); })

TypeScript のサポート

TypeScript プロジェクトで IntelliSense と Office.js の型チェックを有効にするには、DefinitelyTyped から型定義をインストールします。

npm install --save-dev @types/office-js

TypeScript は、型を自動的に認識します。 Office.js は CDN からグローバルに読み込まれるため、コードに import ステートメントは必要ありません。

// TypeScript automatically recognizes Office types.
Office.onReady((info: Office.OfficeInfo) => {
  if (info.host === Office.HostType.Excel) {
    // TypeScript provides IntelliSense for Excel APIs.
  }
});

詳細については、「 Office JavaScript API ライブラリの参照」を参照してください。

その他の考慮事項

インジケーターの読み込み

Office.js 初期化中に読み込みインジケーターを表示する場合は、 Office.onReady() を呼び出す前に表示し、コールバック内で非表示にします。

// Show loading indicator.
document.getElementById('loading')!.style.display = 'block';

Office.onReady((info) => {
  // Hide loading indicator.
  document.getElementById('loading')!.style.display = 'none';

  // Initialize framework.
  initializeYourFramework();
});

独自の読み込み状態を持つフレームワークのユーザー エクスペリエンスを向上させるには、すぐに表示される単純な HTML/CSS ローダーを使用します。 次に、マウント後にフレームワークを引き継ぐようにします。

ダイアログ API とコンポーネントのライフサイクル

Office ダイアログ API は、別のブラウザー ウィンドウでページを開きます。 この動作は、フレームワーク アプリケーションに重要な影響を与えます。

  • 各ダイアログでは、別のフレームワーク インスタンスを使用して 新しい実行コンテキスト が作成されます。
  • ダイアログでは、アプリケーション コードの独自のコピーが実行されます。
  • ダイアログ ページで Office.onReady() を呼び出す必要があります。
  • メイン ページとダイアログ ウィンドウ は状態を共有しません
  • セッション ストレージ はコンテキスト間で共有されません

フレームワーク ルーターを使用してダイアログ ルートに移動する場合は、ダイアログ ウィンドウによってアプリケーションの完全に新しいインスタンスが作成されることを忘れないでください。 既存のインスタンスは再利用されません。

// Main page - opens a dialog.
Office.context.ui.displayDialogAsync(
  'https://localhost:3000/dialog-route',
  { height: 50, width: 50 },
  (result) => {
    if (result.status === Office.AsyncResultStatus.Succeeded) {
      const dialog = result.value;
      dialog.addEventHandler(Office.EventType.DialogMessageReceived, (arg) => {
        // Handle message from dialog.
      });
    } else {
      // Handle error opening the dialog.
      console.error(result.error);
    }
  }
);

// Dialog page - must also call Office.onReady.
Office.onReady(() => {
  // This is a separate framework instance.
  initializeYourFramework();
});

履歴 API の回避策

Office.js では、既定の Window.history メソッドが replaceState され、 pushStatenullに置き換えられます。 フレームワークまたはルーターがこれらの方法 (React Router、Vue Router、Angular Router などでよく使用される) に依存している場合は、キャッシュして復元する必要があります。

次のコードを HTML ファイルに追加し、Office.js スクリプト タグをラップします。

<head>
  <!-- Cache history methods before Office.js loads -->
  <script type="text/javascript">
    window._historyCache = {
      replaceState: window.history.replaceState,
      pushState: window.history.pushState
    };
  </script>

  <!-- Load Office.js -->
  <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>

  <!-- Restore history methods after Office.js loads -->
  <script type="text/javascript">
    window.history.replaceState = window._historyCache.replaceState;
    window.history.pushState = window._historyCache.pushState;
  </script>
</head>

注:

この回避策は、アプリケーションでクライアント側ルーティング (React Router、Vue Router、Angular Router など) を使用する場合にのみ必要です。 ルーティングのない静的アプリケーションでは、この回避策は必要ありません。

Office アプリケーションの外部でのテスト

Office にサイドローディングすることなく、ブラウザー開発者ツールを使用してアドインの UI を開発およびテストできます。 この方法により、開発中のイテレーションが高速化され、UI コンポーネントのデバッグが容易になります。

通常のブラウザー (Office アプリケーションの外部) でアドインを開くと、 Office.onReady() は引き続き実行されますが、ホストプロパティとプラットフォーム プロパティの両方について null で解決されます。

Office.onReady((info) => {
  if (info?.host) {
    console.log(`Running in ${info.host} on ${info.platform}`);
  } else {
    console.log('Running outside of Office (development mode)');
  }

  // Initialize your framework, regardless of whether the add-in is running inside or outside of Office.
  initializeYourFramework();
});

ツールとバンドルをビルドする

最新の JavaScript フレームワークでは、通常、Webpack、Vite、Rollup、esbuild などのビルド ツールが使用されます。 ビルドを構成する場合:

  • JavaScript または TypeScript コードで Office.jsをインポートまたはバンドルしないでください
  • HTML で <script> タグを使用して CDN から Office.js を読み込みます。
  • Officeをグローバル変数として扱うように bundler を構成します。

例: Vite を使用した TypeScript 構成

TypeScript で Vite を使用する場合、通常、Office.js に特別な Vite 構成は必要ありません。 @types/office-js パッケージには、必要な型定義が用意されています。 ただし、Office.js の種類が使用可能であることを確認する必要がある場合は、 tsconfig.jsonを確認します。

// tsconfig.json
{
  "compilerOptions": {
    "types": ["office-js"]
    // ... your other compiler options ...
  }
}

例: Webpack 構成

// webpack.config.js
module.exports = {
  externals: {
    'office': 'Office'
  }
};

Office アドイン用 Yeoman ジェネレーターによって生成されたアドイン プロジェクトには、既定で正しいビルド構成が含まれています。

ネットワーク のブロックとファイアウォール

ネットワーク フィルター、ファイアウォール、またはブラウザー拡張機能が CDN Office.js をブロックする場合、 Office.onReady() 解決されません。 ネットワーク ポリシーによって CDN がブロックされる可能性があるエンタープライズ シナリオのタイムアウトを実装することを検討してください。

let officeInitialized = false;

// Set a timeout.
setTimeout(() => {
  if (!officeInitialized) {
    console.error('Office.js failed to initialize. Network may be blocking CDN.');
    // Show error message to user.
  }
}, 10000); // 10 second timeout

Office.onReady((info) => {
  officeInitialized = true;
  initializeYourFramework();
});

CDN に関する考慮事項の詳細については、「 Office JavaScript API ライブラリの参照」を参照してください。

フレームワーク固有のゾーンまたは反応性の問題

一部のフレームワークでは、ゾーンまたは反応性システムを使用して状態の変化を追跡します。 まれに、Office API 呼び出しでは、フレームワークの変更検出ゾーンの外部で実行されるため、UI の更新がトリガーされません。

Angular: Office API の呼び出し後に UI が更新されない場合は、コードを NgZone.run() でラップします。

import { NgZone } from '@angular/core';

constructor(private zone: NgZone) {}

async loadDataFromExcel() {
  let cellValue: string;

  // Make Office API call
  await Excel.run(async (context) => {
    const range = context.workbook.getSelectedRange();
    range.load('values');
    await context.sync();
    cellValue = range.values[0][0];
  });

  // Update Angular component state inside zone
  this.zone.run(() => {
    this.myData = cellValue;
  });
}

関連項目