今回は Google Apps Script で Web アプリを作ります。
Web アプリは、コンテンツが固定されている単純な Web ページに対して、 アプリのようにコンテンツが変化したり、投稿・編集などができたりするもののことを言います。 Web アプリでは次図のように、Web ページを見たいというリクエストが送られてきたときに Web ページのデータを送り返します。 これを Google Apps Script で行うことができる仕組みが用意されています。
GAS で作ったプログラムは実行ボタンかトリガーによって実行することが多いですが、 Web アプリを作る場合には実行の仕方が変わります。
doGet()
関数が実行されるdoGet()
関数ではまず Web ページを作るのに必要なデータを Spreadsheet から読み込むなどの準備をするdoGet()
関数の最後で HTML 文書を return
すると、それがブラウザへのレスポンスとして送られるWeb アプリは様々な言語・環境で作ることができますが、Google Apps Script はその中でも特に初心者におすすめです。 完全無料であることに加え、データベースの代わりに Spreadsheet を使うのでデータの様子が見えて理解しやすいです。 Spreadsheet は共同編集できるので、サークルのページに必要なデータ(例:試合の勝敗記録)を分担して更新するようなことが専門知識不要でできます。
まずは具体例として、Spreadsheet に書いた情報をもとにリンク集ページを表示する Web アプリを示します。
こちらのページ が Google Apps Script で作成したものです。 元となるデータが記入されている Spreadsheet を授業中だけ編集可能にしますので共同で編集作業をしてみましょう。 (エラー処理をちゃんとしていないので下手に編集すると動かなくなってしまうかも)
続いて作り方を見ていきましょう。まずはスプレッドシートを作成してください。 先ほどの例で使用したデータと同じ構造でデータをいくらか入力して用意しておきましょう。
次にスクリプトエディタを開いてください。
作成する関数 doGet()
は短くてシンプルです。
// (1) リクエストを受け取ると doGet が実行される
function doGet() {
// (2) Spreadsheet からデータを読み込む
let sheet = SpreadsheetApp.getActive().getActiveSheet();
let values = sheet.getDataRange().getValues();
// (3) テンプレートを使ってHTML文書を作って return
let template = HtmlService.createTemplateFromFile("list");
template.links = values; // こうしておくとテンプレートの方で links という変数に値が入った状態で使える
return template.evaluate();
}
データの読み込みについては、前回までにも出てきたのと同じやり方です。
次に読み込んだデータを使って HTML 文書を作って return します。
return HtmlService.createHtmlOutput('<b>Hello, world!</b>');
のように書くこともできますが、
この方法で長い HTML 文書を作成するのは大変なので、テンプレートという仕組みを使って作成することが多いです。
テンプレートというのは、あらかじめ HTML 文書のひな形を別のファイルとして用意しておいて、変化しうるデータ部分を後から穴埋めできるようにしておくことです。
テンプレートはスクリプトエディタの「ファイル」の横にある+ボタンから作成できます。
ここでは list.html という名前で次のようなテンプレートのファイルを作成しました。テンプレートはだいたい HTML です。
は通常の HTML には無い書き方で、テンプレートを穴埋めするためのプログラムを書くことができます。
通常の HTML にもプログラムを書く場合がありますので、それと区別がつくように特別な書き方が用意されているのだと思ってください。
evaluate()
を実行したときにテンプレート内のプログラムが実行されて、その結果がテンプレートに埋め込まれ、埋め込み後のデータがブラウザに送信されます。
埋め込みを行うためのプログラムはブラウザに送信されるデータには含まれません。
補足すると:
(イコールがある場合)実行結果がそこに埋め込まれます。
(イコールがない場合)埋め込まれません。繰り返しのための for 文を書くためなどに使います。doGet()
で読み込んだデータをテンプレートの方で使えるように受け渡しする方法は上記のプログラムに倣ってください。 links
という変数名で使えるように代入しています。
テンプレート中に書くプログラムは HTML と混ざっているせいで読みづらくなってしまいがちですし、書くのもより一層難しく感じると思います。
コツはまずできあがりのHTMLを自分で書いてみて、穴埋めしたい部分を にすることです。
今回の場合は完成した Web アプリがありますので、ブラウザに届いた HTML (=埋め込み後) と埋め込み前のテンプレートを見比べてみると理解しやすくなると思います。
次にプログラムが正しくできたかどうか Web アプリの動作確認をします。 右上にある青い「デプロイ」ボタンから「デプロイをテスト」をクリックします。 URLが発行されるのでクリックして開いてください。 最初に示した例と同じようなページが開くはずです。 実際の開発工程ではこまめに動作確認を行った方がいいでしょう。
プログラムが完成して動作確認もできたら Web アプリとして公開します。注:テストURLは開発に使っている Google アカウントでしか開けません
右上にある青い「デプロイ」ボタンから「新しいデプロイ」の画面を開きます。 種類の選択で「ウェブアプリ」を選択すると下の図のような画面になります。
いつも通り動作の承認を求められた後に Web アプリとして公開され、アクセスするための URL が用意されます(下図)。クリックしてアクセスしてみてください。
プログラムを書き換えるだけでは公開されたアプリは変更されないので注意してください。 プログラムを書き換えるごとにこまめに動作確認をするときにはテスト用のURLを使うのが便利です。 公開アプリを更新するには「デプロイを管理」から「編集(鉛筆アイコン)」する必要があります。 編集画面ではバージョンのプルダウンリストで「新バージョン」を選択して右下の「デプロイ」ボタンを押すと更新が完了します。
デプロイ作業について以下にまとめます。
説明した手順通りに作業して Web ページの動作確認と公開をしてみましょう。 また、テンプレートを少し書き換えてテスト用URLと公開URLの挙動の違いを確認してみましょう。
iframe
を使うと、他のWebページの一部として別のページを埋め込むことができます。
GAS で作ったページを埋め込むことができてうれしい状況にはどのようなものがあるでしょうか。 たとえば神戸大学の情報基盤センターが提供している 個人Webページサービス では機能制限が強く、 訪問者がデータを送信できる掲示板のような機能を持ったページを作ることができません。 無料でホームページが作成できることをうたうサービスは多いですが、同様に機能制限が強いものが多いです。 そのようなサービス上に所属サークルのページが作られていて、不便だけど全体を引っ越すのは大変という場合などもあるでしょう。
そのような状況でたとえば、みんなで編集したいところだけ GAS で作成して埋め込むと更新作業が楽になるなどの活用方法が思い浮かびます。
このテキストにも先ほどのリンク集を埋め込んでみました。埋め込み部分は少し遅れて表示されると思います。
-------- 埋め込みここから --------
-------- ここまで --------
セキュリティの都合上、他のページに埋め込めるようにするには埋め込んでもいいよという許可をする必要があります。
埋め込んで使いたい場合は doGet()
の最後の部分を次のように書き換えてください。
// これを
return template.evaluate();
// こう書き換える
return template.evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
あとは次のように埋め込む方のページで埋め込みたいところにコンテンツの URL を指定するだけで完了です。 このタグをどこにどう書けばいいかわからないと思う方は、このページに実際に埋め込んでいますので、その部分の HTML を探して真似してみてください。
Web アンケート や SNS のように、Web ページからサーバー側にデータを送信(投稿)するようなページを作ることもできます。ここまでできるとかなり使い勝手があります。
ここでは、4択問題の答えを選択するたびに「ファイナルアンサー?」と聞いてくるウザいクイズページを作ってみます。まずは 実物 を触ってみてください。ウザいですね。問題と回答が記録される Spreadsheet は こちら。 質問と回答を別のシートに記録するようにしています。
プログラムは doGet()
に加えてもうひとつ、送られてきたデータを処理する関数を作ります。
こちらは自由に名前を付けていいので checkAnswers(answers)
という名前にしました。
// doGet はあまり変わりません
function doGet(){
let sheet = SpreadsheetApp.getActive().getSheetByName("質問"); // 「質問」シートから読み込み
let template = HtmlService.createTemplateFromFile("show");
template.qs = sheet.getDataRange().getValues();
return template.evaluate();
}
// 送信された回答を記録して、正解数を返す関数
function checkAnswers(answers){
let sheet = SpreadsheetApp.getActive().getSheetByName("質問"); // 「質問」シートから読み込み
let values = sheet.getDataRange().getValues();
let row = [new Date()];
let n = 0; // 正解数をカウントするための変数
for(let i = 1; i < values.length; i++){
let input = answers["Q" + i]; // 送信された回答
let answer = values[i][5]; // 「質問」シートにある正解
if(input == answer) n++;
row.push(input);
}
SpreadsheetApp.getActive().getSheetByName("回答記録").appendRow(row);
return n;
}
次にテンプレート (show.html) です。
show.html には二種類のプログラムが含まれています。
に囲まれた、テンプレートを穴埋めするプログラム。サーバから送信される前に Google のサーバ上で実行されます。前者ではスプレッドシートに用意されているクイズデータの問題数分だけ繰り返しを行って HTML を作成しています。 選択肢の数分だけ繰り返しを行っている部分もあります。 最初の例よりも複雑になっていますが、やはり完成 Web アプリがありますのでその HTML (=埋め込み後) と埋め込み前を見比べてみると理解しやすくなると思います。
ブラウザ側で動くプログラムではいろいろなことをしています。3つある関数がそれぞれ指定のタイミングで動作するよう指定されていることに注意してください。
function ask(e)
:選択肢をクリックしたときに動作するように onclick イベントに登録(14行目)function sendAnswers()
:回答を送信ボタンをクリックしたときに動作するように onclick イベントに登録(20行目)function success(e)
:回答を送信して、それに対する返信を受け取ったときに動作するように withSuccessHandler で指定(31行目)
選択肢をクリックしたときには confirm("ファイナルアンサー?")
でダイアログを表示しています。confirm はユーザーが選んだボタンによって true か false を返しますので if 文に入れることで条件分岐できます。
ユーザーが「キャンセル」を選んだときには e.preventDefault()
でデフォルトの動作(=ラジオボタンをクリックしたら選択される)をキャンセルするようにしています。
データの送受信を行うプログラムは一般に以下のように2つの処理を組み合わせて書く場合が多いです。
たいていの場合、送信→受信、返信→返信を受信というように往復で通信しますので、4つの処理を組み合わせることになって書くのが大変です。
GAS ではこのような処理を少し簡潔に書ける仕組み google.script.run
が用意されています。
データの送受信ではなく、関数呼び出しの引数としてデータを渡しているように書けるので、プログラムの見た目が簡潔になります。
google.script.run.withSuccessHandler(success).checkAnswers(answers);
で実際に裏で何が起きるかをかみ砕くと
answers
の内容をサーバに送信するcheckAnswers(answers)
が実行されるn
の内容をブラウザに返信するsuccess(n)
が実行される裏で起きていることはデータの送受信なのですが、ただの関数呼び出しのように書けるということです。
架空のサークルの試合結果ページを作ってみましょう。 対戦相手、勝敗、スコア、試合日時などをスプレッドシートに記録して、それを表示するページを作ります。 勝敗によって表示(色など)が変わるようにしてみてください。
物足りない人向け:投稿内容をスプレッドシートに保存できて(後半のクイズのように)、スプレッドシートの内容をウェブページにできる(前半のリンク集のように)ということは、ウェブ掲示板も作れるということですね。 がんばれば「いいねボタン」なんかも作れるでしょう。普通のSNSにはないような機能を考えるのもワクワクしませんか?ぜひ挑戦してみましょう。