Google Apps ScriptとMicrosoft Graph APIの連携 - 準備編【GAS】
G Suiteには、Google Driveというクラウドストレージサービスがあるので、通常は他のオフィスサービス(Microsoft365)と連携する必要がありませんが、G Suiteをアプリケーションの環境、通常はMicrosoft365を使って、Excelのファイル類などについては、OneDriveやSharepointを利用している事もあるでしょう。
そんな時にGAS側からMicrosoft365とりわけExcelファイルの読み書きができたら非常に便利になると思います。今回はGoogle Apps Scriptにて、Microsoft365側のExcelファイルへアクセスする手順を残しておきたいと思います。
目次
準備するもの・使用するファイル
- 連携用Googleスプレッドシート
- Microsoft365側のExcelファイル
- Microsoft Graph API
- OAuth2 for Apps Script ライブラリ
- Application Registration Portal
事前準備
今回のスクリプトはOAuth2.0認証が必要となるため、その為の簡単設定ライブラリとして、OAuth2 for Apps Scriptライブラリを利用させていただきます。また、Microsoft365側では、Application Registration Portalにてアプリの作成を登録し、アプリケーションIDとアプリケーションシークレット等の情報を入手する必要があります。
GAS側の事前準備
ライブラリの追加
以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。
- スクリプトエディタを開きます。
- メニューより「リソース」⇒「ライブラリ」を開きます。
- ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
- 現時点ではバージョンは30が最新ですので、それを選択しておきます。
- 保存ボタンを押して完了
これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。
図:ライブラリを追加した様子
コールバックURLを取得する
コールバックURLとは、認証を完了しAccess Tokenを取得したら戻るべきURLを指定するものです。これは、スクリプトIDをもとに作られているので、スクリプトIDを取得して組み立てます。
- スクリプトエディタのメニューより「ファイル」⇒「プロジェクトのプロパティ」を開く
- 情報の中にある「スクリプトID」を控えておく。
- https://script.google.com/macros/d/スクリプトID/usercallback として組み立てる。これがコールバックURLとなる。
図:スクリプトIDはファイル毎に異なるのです。
Microsoft365側の事前準備
続いて、Microsoft365側での処理を行います。ここでは、アプリケーションの作成を行い、アプリケーションIDとアプリケーションシークレット等を生成します。
- Application Registration Portalにログインする。
- アプリの追加ボタンを押す。
- Application Nameを入力しCreateボタンを押します。アルファベット以外も使えますよ。
- この段階でアプリケーションIDはすでに生成されているので、控えて置きます。
- アプリケーションシークレットにて、「新しいパスワードを生成」をクリックし、パスワードを発行します(このパスワードはこの時の1回しか表示されません)。
- 「プラットフォームの追加」にて、追加ボタンを押し、Webを選択。
- ここで、GAS側で取得したコールバックURLをリダイレクトURLに入力します。
- Microsoft Graphのアクセス許可では、スコープを設定します。User.Read、Files.ReadWrite、offline_accessを追加します。offline_accessを入れないと「リフレッシュトークン」が取得できないので、注意。
- 保存ボタンを押して完了です。
図:スコープの設定で許可するアクションを選びます。
認証を行う処理を作成する
OAuth2 for Apps Scriptのページの「Create the OAuth2 Service」にあるコードを元に、Google Apps Script側で構築をします。この時、Microsoft365側で取得したアプリケーションIDやシークレットを使います。
GAS側コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//メニューを構築する function onOpen(e) { var ui = SpreadsheetApp.getUi(); ui.createMenu('▶OAuth認証') .addItem('認証の実行', 'startoauth') .addSeparator() .addItem('ログアウト', 'reset') .addToUi(); } //認証用の各種変数 var appid = 'ここにアプリケーションIDを入れます'; var appsecret='ここにアプリケーションシークレットを入れます。'; var scope = "User.Read Files.ReadWrite offline_access" var endpoint = "https://graph.microsoft.com/v1.0" var targetfile = "ここにターゲットとなるxlsxファイル名を入れます。" var tokenurl = "https://login.microsoftonline.com/common/oauth2/v2.0/token" var authurl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize" function startoauth(){ //UIを取得する var ui = SpreadsheetApp.getUi(); //認証済みかチェックする var service = checkOAuth(); if (!service.hasAccess()) { //認証画面を出力 var output = HtmlService.createHtmlOutputFromFile('template').setHeight(310).setWidth(500).setSandboxMode(HtmlService.SandboxMode.IFRAME); ui.showModalDialog(output, 'OAuth2.0認証'); } else { //認証済みなので終了する ui.alert("すでに認証済みです。"); } } //アクセストークンURLを含んだHTMLを返す関数 function authpage(){ var service = checkOAuth(); var authorizationUrl = service.getAuthorizationUrl(); var html = "<center><b><a href='" + authorizationUrl + "' target='_blank' onclick='closeMe();'>アクセス承認</a></b></center>" return html; } //認証チェック function checkOAuth() { return OAuth2.createService("Microsoft Graph") .setAuthorizationBaseUrl(authurl) .setTokenUrl(tokenurl) .setClientId(appid) .setClientSecret(appsecret) .setScope(scope) .setCallbackFunction("authCallback") //認証を受けたら受け取る関数を指定する .setPropertyStore(PropertiesService.getScriptProperties()) //スクリプトプロパティに保存する .setParam("response_type", "code"); } //認証コールバック function authCallback(request) { var service = checkOAuth(); Logger.log(request); var isAuthorized = service.handleCallback(request); if (isAuthorized) { return HtmlService.createHtmlOutput("認証に成功しました。ページを閉じてください。"); } else { return HtmlService.createHtmlOutput("認証に失敗しました。"); } } //ログアウト function reset() { checkOAuth().reset(); SpreadsheetApp.getUi().alert("ログアウトしました。") } |
HTML側コード
template.htmlというダイアログ用のファイルを用意します。ここでアクセス承認を実行し、ログインをすると、アクセストークンその他が取得可能になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css"> <script type="text/javascript" src="https://apis.google.com/js/api.js"></script> <script> google.script.run.withSuccessHandler(onSuccess).authpage(); function onSuccess(data){ document.getElementById("kinoko").innerHTML = data; } </script> <style type="text/css"> /* --- ボックス --- */ div.section { width: 480px; /* ボックスの幅 */ background-color: #ffffff; /* ボックスの背景色 */ border: 1px #c0c0c0 solid; /* ボックスの境界線 */ font-size: 100%; /* ボックスの文字サイズ */ } /* --- 見出し --- */ div.section h3 { margin: 0; /* 見出しのマージン */ padding: 6px 10px; /* 見出しのパディング(上下、左右) */ background-color: #f5f5f5; /* 見出しの背景色 */ border-bottom: 1px #c0c0c0 solid; /* 見出しの下境界線 */ font-size: 120%; /* 見出しの文字サイズ */ } /* --- ボックス内の段落 --- */ div.section p { margin: 1em 10px; /* 段落のマージン(上下、左右) */ } </style> <div class='section'> <img border="0" src="http://blog.movereem.nl/images/oauth.png" alt="oauth2"> <h3 id='header'>OAuth認証の許可が必要です。</h3> <hr> <div id="info"> <p> このスクリプトは、Microsoft Graph APIにアクセスするために、特別なログイン処理を利用しています。<br> 既に特別なログインに関する設定はなされており、承認がされるとプログラムを実行することが出来ます。この承認がなされない場合、プログラムの実行に制限が掛かり、 処理が続行できません。<br><br> <div id="kinoko"></div> </div> <p> <script> function closeMe(){ if(google && google.script && google.script.host){ google.script.host.close(); } else if(window && window.close){ window.close(); } } </script> </div> |
- 実際にこれらのコードで、startoauthを実行すると、スプレッドシート上で認証用のダイアログが出ます。
- 認証でMicrosoft365アカウントにログインします。
- 取得したAccess Tokenほかはスクリプトプロパティのoauth2.Microsoft Graphという項目にガッツリ値が格納されます。ここにはAccess Token, Refresh Token, expire_inのタイムなどが入っています。
- reset関数はログアウトされて、再度認証ができるようになります。
図:Microsoft側でのOAuth認証画面