ENGINEER BLOG

ENGINEER BLOG

Microsoft Graphを使ってExcel Online(Microsoft 365)のデータを読み書きする その2

こんにちは、イノベーション本部の朝日です。

前回の続きです。 前回はGraphエクスプローラーを使ってExcel Onlineのデータを読み書きできることを確認しました。
今回は実際にWebページ(JavaScript)から利用してみます。

【おまけ】SharePointでHTMLを表示できるようにする

まずWebサーバーを用意しますが、せっかくなのでMicrosoft365を活用し、SharePointをWebサーバーとして使ってみます。
通常だとHTMLをドキュメントライブラリにアップロードしてもうまく表示できないので、SharePoint管理者による以下の作業が必要になります。

以下はご自分の環境に合わせて読み替えてください。

  1. SharePoint Online Management Shellをインストールします
    https://www.microsoft.com/ja-jp/download/details.aspx?id=35588
    からダウンロードして、インストールしてください。

  2. 管理者アカウントでSharePoint管理センターにアクセスして、SharePoint管理サイトのURLを確認します
    通常、SharePointサイトのURLが

    https://***.sharepoint.com/sites/~

    の場合は、管理サイトのURLは
    https://***-admin.sharepoint.com/

    になるはずです。

  3. Windowsのスタートメニューから「SharePoint Online Management Shell」を実行し、SharePointに接続します
    ここでの指定に先ほど確認したSharePoint管理サイトのURLが必要になります。

Connect-SPOService -Url https://***-admin.sharepoint.com
  1. 接続できたら念のためにサイト一覧を表示して正しく接続できていることを確認します
Get-SPOSite
  1. 対象のサイトに対してカスタムスクリプトを許可します
Set-SPOSite <SiteURL> -DenyAddAndCustomizePages 0

以上です。

確認用に以下のようなHTMLを作成し、ドキュメントライブラリに拡張子aspxで格納します。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    </head>
    <body>
        テストページです。
        <pre id="msg"></pre>
        <script>
            document.getElementById("msg").textContent = "JavaScriptが動作しています!";
        </script>
    </body>
</html>

正しく設定できていれば、ドキュメントライブラリに格納したaspxファイルをクリックした際に別タブで以下のように表示されるはずです。

テストページです。
JavaScriptが動作しています!

SharePointによるアクセス制御も可能なので、今回のようにMicrosoft365のリソースにアクセスしたいWebページを作りたい場合や社内用システムを構築したい場合には有用なのではないでしょうか。

Webページ(JavaScript)からMicrosoft Graphを利用する

さて本題です。

公式ドキュメントに沿って実装、と行きたいところですが結構情報が散在していたり、シンプルなものがなかったりするので主に以下の情報を参考にミニマムなものを作ってみます。

ドキュメントでは、npmで導入したりポップアップウィンドウでの認証のサンプルが多いのですが、やってみたところポップアップブロックに気づきにくかったりして実運用ではトラブルの元になりそうなので、今回はscriptタグでの導入、リダイレクトによる認証で作ることにします。

利用するライブラリは

の2つです。

Azure Active Directryでアプリ登録してクライアントIDを取得

Azureポータルにアクセスして、
[Azure Active Directory] > [アプリの登録] > [新規登録] の順に選択します。

適当な名前を入力し、「リダイレクトURI」の項目は「シングルページアプリケーション(SPA)」を選択して、用意したHTMLページへのURLを記入し「登録」します。

その後表示される「アプリケーション(クライアント)ID」を使いますので、記録しておきます。

コードと解説

今回のコードは以下のようになります。 先ほど作成した動作確認用のHTMLのscriptを変更しただけです。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    </head>
    <body>
        テストページです。
        <pre id="msg"></pre>

        <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.28.1/js/msal-browser.min.js"></script>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@microsoft/microsoft-graph-client/lib/graph-js-sdk.js"></script>
        <script>
            const CLIENT_ID = '********-****-****-****-************';
            const PATH = "/me/drive/items/{drive-item-id}/workbook/tables/{table-id}/rows";

            async function getGraphClient() {
                const authProvider = {
                    getAccessToken: getAccessToken
                };

                const graph = MicrosoftGraph.Client.initWithMiddleware({ authProvider });
                return graph;
            }

            async function getAccessToken() {
                const msalConfig = {
                    auth: {
                        clientId: CLIENT_ID,
                        authority: 'https://login.microsoftonline.com/organizations',
                    }
                };

                const msalClient = new msal.PublicClientApplication(msalConfig);
                const redirectResponse = await msalClient.handleRedirectPromise();
                if (redirectResponse !== null) {
                    console.info(redirectResponse);
                    return redirectResponse.accessToken;
                } else {
                    const accounts = msalClient.getAllAccounts();
                    const account = (accounts.length > 0) ? accounts[0] : "";
                    const accessTokenRequest = {
                        scopes: ["User.Read", "Files.ReadWrite.All"],
                        account: account
                    }
                    return await msalClient.acquireTokenSilent(accessTokenRequest).then(function (res) {
                        return res.accessToken
                    }).catch(async function (e) {
                        await msalClient.acquireTokenRedirect(accessTokenRequest);
                    });
                }
            }

            getGraphClient().then(client => {
                client.api(PATH).get().then( res => {
                    res.value.forEach(value => {
                        document.getElementById("msg").textContent += value.values[0] + '\n';
                    })
                }).catch( e => {
                    console.error(e);
                });
            }).catch(e => {
                console.error(e)
            });
        </script>
    </body>
</html>

前回の最後に書き込みしたExcel

からテーブルデータを取得するリクエストを設定して実行すると以下のように

取得できていることがわかります。

クライアントIDの設定

            const CLIENT_ID = '********-****-****-****-************';

には、先ほどアプリ登録して取得したクライアントIDを記載してください。

Graph リクエストの設定

            const PATH = "/me/drive/items/{drive-item-id}/workbook/tables/{table-id}/rows";

には、Graphへのリクエストを記載しますが、Graphエクスプローラーで使ったリクエストが

https://graph.microsoft.com/v1.0/me/drive/items/{drive-item-id}/workbook/tables/{table-id}/rows

の場合、

https://graph.microsoft.com/v1.0 

より後ろを記載すればOKです。

Graph SDKの導入とクライアントの作成

Microsoft Graph JavaScript Client Library – Via Script Tag
に従って、Graph SDKを導入しています。

Graphクライアントを取得するコードは以下の部分になりますが、

            async function getGraphClient() {

Graphの初期化時にアクセストークンを渡す必要があります。

MSALを使った認証とアクセストークンの取得

Microsoft Authentication Library for JavaScript (MSAL.js) 2.0 for Browser-Based Single-Page Applications – Via CDN
に従って認証ライブラリを導入しています。

Graphの初期化に使うアクセストークンを取得するコードは以下の部分になります。

            async function getAccessToken() {

この部分は、

Creating an instance of AuthCodeMSALBrowserAuthenticationProvider for a browser application
によると、MSGraphAuthCodeMSALBrowserAuthProviderを使ってもっと簡単に実装できそうなんですがリダイレクトでうまく動かせなかったので、今回は
シングルページ アプリケーション:API を呼び出すトークンを取得する – リダイレクトを使用してトークンを取得する
を参考に独自に実装しています。

Graph クライアントを使ってGraph APIにアクセス

あとは、取得したGraphクライアントを通してリクエストするだけです。 今回はテーブルデータを取得したかったのでget()を使っていますが、他のリクエストの場合は
Microsoft Graph SDK を使用して API 呼び出しを作成するを参考に実装してみてください。

さいごに

今回はJavaScriptからGraph APIを呼び出し、Excel Onlineのデータにアクセスできることを確認しました。
複雑なものでなければPower AppsやPower Automate等で事足りることが多いとは思いますが、Web開発に慣れている方はこちらのやり方の方が分かりやすかったりするかもしれません。
構築したいシステムやスキルに応じて適したサービスを活用して開発していきたいものですね。