Google Apps Scriptを色々なアプリから実行する【GAS】
Google Apps Scriptにて2015年11月に新機能として実装された「Apps Script API」というものがあります(以前は、Google Apps Script Execution APIと呼ばれていました)。これは、Google Apps Scriptで用意してある関数を外部の環境(Javaや.NET、Node.jsなど)から実行できるようにするというものです。別途Google APIの認証用の手続きが必要ですが、この機能を利用するとG Suiteの利便性と利用範囲が格段に向上します。
- Googleアカウントを持つものであれば、認証をしてそのGoogle Apps Scriptの関数を直接実行する事が出来る
- ローカル環境(例えばイントラネット)に用意したHTML内でGoogle Apps Scriptの実行環境を利用してアプリケーションを作れる
- Javaや.NET、VBA(Access VBAとの連携事例を参考)やNode.jsといった言語で使用する事が出来る。
- アクセス権限を極特定の関数に絞る事が出来る
- iOSやAndroidのアプリからももちろん実行する事が可能になる。
- doGet()やdoPost()で同じような事が出来ましたが、1プロジェクト内で1個しか用意出来ない。Execution APIはダイレクトに関数を叩けるので、その制限がない。
- ただし、doGetのようにURLにつなげてパラメータを渡すわけではないので、基本POSTで送信する
- 通常、doGetのようなものを使って、REST APIを作った場合、実行後にURLがリダイレクトされて結果が出力されます。しかし、Apps Script APIは他のWeb API同様URLは固定なので、リダイレクトされると困るケースには重宝します(例えば、Amazon Echoから使うような場合)
目次
準備するもの、使用するメソッド
- 今回使用するスプレッドシート
- 今回用意したHTMLファイル
- ローカルPCに用意したWebサーバ
- Google API Client Library for JavaScript
事前準備
事前にスプレッドシートのメニューにある「セットアップ」内にある「初期化」を実行しておいて下さい。この作業により、スプレッドシートのIDがスクリプトプロパティに格納されます。この作業はデータの塊を返す関数内でopenByIdにてスプレッドシートを指定してる為で、getActiveSpreadsheetでは指定が出来ない為です。意外と嵌まりやすいポイントですので注意して下さい。
概要
Apps Script APIを利用できるようにする為には事前準備が必要です。今回のサンプルは特定のスプレッドシートのシートにあるデータの塊を取得して、HTML側にテーブルとして表示するというサンプルです。必要なものは
- Cloud ConsoleにてOAuth2.0クライアントIDを作成する
- Google Apps Script側で用意したデータの塊を返す関数
- 今回使用するスプレッドシートを実行可能APIとして導入した際に発行される現在のAPI ID
- スプレッドシートのスコープを取得する
デスクトップに置いたHTMLをそのまま実行では取得が出来ないので、別途Webサーバやアプリが必要です。自分は仮想環境内にUbuntu Linuxを入れ、手軽にWebサーバを作れるxamppを導入して環境を用意しました。WindowsでもMac OS Xでもxamppを利用できますので、通常はお使いのPCにxamppをインストールしてサーバを実行するだけでOKです。
プロジェクトを移動
Developer ConsoleにてOAuthクライアントIDを取得する
今回使用するスプレッドシートをコピーした後、まずはスクリプトエディタの画面に入ります。その後以下の手順でクライアントIDを取得します。
- メニューより「リソース」⇒「Googleの拡張サービス」を開きます。
- 出た画面の下にある「 Google Cloud Platform API ダッシュボード」をクリックします。
- 上記の▼をクリックして、選択元は自分のドメインを選び、新しいプロジェクトをクリックします。
- APIライブラリを開き、「Apps Script API」を検索して、有効にします。
- 次に認証情報を開き、「認証情報を作成」をクリックし、「必要な認証情報」を選択します。APIを呼び出す場所は「ウェブブラウザ」でOKです。
- 再度、認証情報をクリックし、認証情報を作成⇒OAuthクライアントIDを選択します。
- アプリケーションの種類は「ウェブアプリケーション」を選択し、作成します。
- 承認済みの JavaScript 生成元には、http://localhostと入力すればOKです。
- 承認済みのリダイレクト URIは、空っぽのままでOKです。
- これで作成すると、クライアントID、クライアントシークレットが発行されますので、コピーして置きます。
- 次にOAuth同意画面というタブをクリックします。この画面は新規でプロジェクトを作成した場合には、利用範囲を内部に制限することが可能です。GASから作った場合には、少し画面が異なるので注意。今回はプロジェクトをつくった場合として進めます。
- アプリケーションの種類は「内部」にし、ドメイン内のユーザに限定します。
- Google APIのスコープには今回追加で、../auth/spreadsheetsを選び追加します。
- 認証ドメインは自分のドメインのWebサーバからのみ呼び出せるようにする場合に使います。今回は空で良いです。保存をクリック。
図:Apps Script APIを有効にする
図:認証情報を追加する
図:OAuthクライアントを作成する
図:クライアントIDとシークレットが作成される
実行可能APIとして導入する
クライアントIDが取得できたら、まずは関数を用意しておきます。実行可能APIとして導入するという機能は、ウェブアプリケーションとして導入と同じく、ソースコードを変更する度に発行し直さないと行けないので注意が必要です。ソースコードを変更後に再度導入をせずに実行しても、以前のソースコードのままで返ってくるので嵌るポイントです。今回のスプレッドシートは、イチゴのデータベースを用意しそのデータの塊を取得してそのまま帰すberryget()という関数を用意しました。
実行可能APIとして導入する手順は以下の通りです。
- スクリプトエディタのメニューより、「公開」⇒「実行可能APIとして導入」を実行します
- 適当にバージョンの説明を入力して、配置ボタンを押し、続行すると現在の API IDが取得できます。アクセスできるユーザは全員で良いでしょう。
これだけです。
図:配置ボタンを押すと完了
スコープを取得する
スコープとは、アクセスするGoogleのサービスを差し、アクセスを許可するサービスを限定する事が出来ます。今回はスプレッドシートと一部のサービスのみですので、例えばGoogle Driveなどはhttps://www.googleapis.com/auth/driveとなっています。今回のスクリプトでのスコープは以下の手順で取得できます。
- どれでも良いのでとりあえず、1つ関数を実行しておき、認証を済ませておく。
- スクリプトエディタのメニューより「ファイル」⇒「プロジェクトのプロパティ」を開く
- 出てきた画面の「スコープ」を開く
- 出てきたスコープをメモしておく
HTMLファイルにID類を記述する
ここまで取得してきた各種ID等をHTMLファイルに記述します。
- CLIENT_IDにクライアントIDを記述します。シングルコーテーションで括るのを忘れずに。
- SCOPESに取得したスコープを記述します。配列の形で記述するので、複数指定が可能です。今回のケースで言えば、['https://www.googleapis.com/auth/script.storage','https://www.googleapis.com/auth/spreadsheets'];といった形で記述をします。
- scriptIdに現在の API IDで取得したIDを記述します。
GAS側の実行する関数を記述する
最後にGAS側で用意した関数を記述します。HTMLファイルの中盤にあるrequestがソレですが、関数名を記述します。今回のケースで言えば、'function': 'berryget'と記述します。しかし、関数に引数を渡したいこともあるでしょう。其の場合には、追加でparametersという項目を追加して、配列の形で引数を記述すると関数に引数として渡せます。具体的には以下のような形になります。
GAS側コード
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('▶セットアップ')
.addItem('初期化', 'getMySheetId')
.addToUi();
}
//自分自身のIDを取得するコード
function getMySheetId(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var myid = sheet.getId();
var Properties = PropertiesService.getScriptProperties();
Properties.setProperty("mysheetid", myid);
return myid;
}
//イチゴデータベースを取得して返す
function berryget() {
var Properties = PropertiesService.getScriptProperties();
var sheetid = Properties.getProperty("mysheetid");
var sheet = SpreadsheetApp.openById(sheetid);
var ss = sheet.getSheetByName("berrymaster").getRange("A2:E").getValues();
return ss;
}
HTML側コード
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<script type="text/javascript">
//Developer Consoleで設定したクライアントIDを入力
var CLIENT_ID = 'ここにクライアントIDを記述する';
//必要としてるスコープ(カンマ区切りで複数設定)
var SCOPES = ['ここにスコープを記述する'];
//認証を実行するルーチン
function checkAuth() {
gapi.auth.authorize(
{
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true
}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeDiv = document.getElementById('authorize-div');
if (authResult && !authResult.error) {
authorizeDiv.style.display = 'none';
callScriptFunction();
} else {
authorizeDiv.style.display = 'inline';
}
}
function handleAuthClick(event) {
gapi.auth.authorize(
{client_id: CLIENT_ID, scope: SCOPES, immediate: false},
handleAuthResult);
return false;
}
//Execution APIを実行してスクリプト側の関数を叩くルーチン
function callScriptFunction() {
//現在のAPI IDを入力する
var scriptId = "ここに現在のAPI IDを記述する";
// スクリプト側の関数(引数を必要とする場合は、'parameters': [sheetId]といった具合に渡せる)
var request = {
'function': 'ここにGAS側関数名を記述する'
};
// APIリクエストを組み立てる
var op = gapi.client.request({
'root': 'https://script.googleapis.com',
'path': 'v1/scripts/' + scriptId + ':run',
'method': 'POST',
'body': request
});
//リクエストの実行と結果の受け取り
op.execute(function(resp) {
if (resp.error && resp.error.status) {
//APIの実行に失敗した場合の処理
appenddiv('APIの呼び出し失敗:');
appenddiv(JSON.stringify(resp, null, 2));
} else if (resp.error) {
//APIの実行結果、エラーが発生した場合の処理
var error = resp.error.details[0];
appenddiv('スクリプトエラーメッセージ: ' + error.errorMessage);
if (error.scriptStackTraceElements) {
appenddiv('スクリプトエラー:');
for (var i = 0; i < error.scriptStackTraceElements.length; i++) {
var trace = error.scriptStackTraceElements[i];
appenddiv('\t' + trace.function + ':' + trace.lineNumber);
}
}
} else {
//APIの実行に成功し、帰ってきた値を処理するルーチン
var data = resp.response.result;
var length = data.length;
var clength = data[0].length;
if (length == 0) {
appenddiv('データがないよ');
} else {
appenddiv('<p><b>見つかったデータの詳細</b></p>');
var html = "<table border='1'>";
for(var i = 0;i<length;i++){
html += "<tr>";
for(var j = 0;j<clength;j++){
html += "<td>" + data[i][j] + "</td>";
}
html += "</tr>";
}
html += "</table>";
appenddiv(html);
}
}
});
}
//idがoutputのタグに結果を書き込む関数
function appenddiv(message) {
var pre = document.getElementById('output');
pre.innerHTML = pre.innerHTML + message;
}
</script>
<script src="https://apis.google.com/js/client.js?onload=checkAuth">
</script>
</head>
<body>
<div id="authorize-div" style="display: none">
<span>Apps Script APIを実行する</span>
<button id="authorize-button" onclick="handleAuthClick(event)" class="action">
認証実行
</button>
</div>
<div id="output"></div>
</body>
</html>
Webサーバ上に配置して実行する
作成が完了したHTMLファイルをWebサーバに配置します。Ubuntu Linuxにインストールしたxamppでは、/opt/lampp/htdocs以下が配置場所になりますので、ここにtestというフォルダを自分は作りました。testフォルダ内にstart.htmlを配置して、Webサーバを起動します。xamppの場合の起動コマンドは、







