Google Apps Scriptでの申請フォームの作成とハングアウトチャットとの連携

今回こういった機会をいただいたのですが、
わたしにはサーバのことを書くのはまだまだ…と思い、
実際に業務で使っているGoogle Apps Scriptのことを書くことにしました。
※普段はサーバエンジニアとして働いています。

## きっかけ
社内向けのフォームを移行することになったのですが、Googleフォームだとできない要件が増えてきてしまい…
どうしたものかと思っていたらGoogle Apps Scriptでいけそう！となったのがきっかけです。

フォームを送信した人への自動返信、部内への申請通知も行いたかったので、
そういった機能も含めたフォームを作ることにしました。

## プロジェクトの準備
まずはGoogle Apps Script（以降GAS）の新規プロジェクトを用意しましょう。
立ち上げの方法はいろいろあると思うのですが、
私は業務上Googleドライブを使うことが多いので、［新規］ボタンからすぐに作成できるようにしています。

出てこない！という場合は［その他］から［アプリを追加］で追加することが可能です。
![2018-12-11_18h58_19.png](https://qiita-image-store.s3.amazonaws.com/0/96973/e2f15b38-5790-34be-1b80-2ef496767362.png)

用意したプロジェクトは名前を付けておきましょう！

## ファイルの準備
プロジェクトを立ち上げた時点で```コード.gs```というファイルがありますが、
そのほかにHTML , CSS , Javascriptの役割を持たせたファイルを用意します。
ファイル→新規作成→HTMLファイルでファイルの作成ができます。

![2018-12-12_11h43_03.png](https://qiita-image-store.s3.amazonaws.com/0/96973/2c8beaf3-067d-6e4b-bf13-bcefec721344.png)

HTMLファイルを立ち上げると一部のコードが入力された状態のファイルができます。

今回は下記のような命名でファイルを3つ用意しました。

```
index.html → htmlを書き込むファイル
style.html → cssを書き込むファイル
scripts.html → javascriptを書き込むファイル
```

## コード
それでは実際にコードを書いていこうと思います。
※普段業務で扱っていないので、おや・・・？なところがあっても暖かく見守ってください。。。

### index.html
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <base target="_top">
    <?!= include('style'); ?>
    <meta charset="utf-8">
    <link href="https://fonts.googleapis.com/earlyaccess/mplus1p.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>

<body>
  <header>
    <h1>AdventCalendar</h1>
  </header>
  <div id="all">
  <form onsubmit="handleFormSubmit(this)">
  <div id="description">
    <p>Advent Calendar用のフォームを作ります。</p>
    <hr>
  </div>
  <div id="q1">
    <p>送信先のメールアドレスを入力してください。<input type="text" name="mail" class="mail" maxlength="32" required></p>
    <p class="q1">Advent Calendarのような記事を書いたことが</p>
      <fieldset class="q1">
        <label><input type="radio" name="q1" value="ある">ある</label>
        <label><input type="radio" name="q1" value="ない">ない</label>
      </fieldset>
  </div>
  <div id="q2">
    <p class="q2">書いたことがある回数は？</p>
      <fieldset class="q2">
        <label><input type="radio" name="q2" value="はじめて">今回はじめて</label>
        <label><input type="radio" name="q2" value="その他">その他</label>
      </fieldset>
  </div>
  <div id="submit">
    <input type="submit" name="btn" value="登録">
  </div>
  </form>
  </div>
<?!= include('scripts'); ?>  
</body>
</html>
```
GASで作成したHTMLファイルで外部ファイルを読み込むときは、下記のように記載します。

```<?!= include('ファイル名'); ?>```
GASで用意したHTMLファイルの中で、別ファイルを読み込むおまじないです。※スクリプトレットタグ。
今回は```style.html```と```scripts.html```のファイルを読み込んでいます。
ちなみにこれだけだとうまくいきません。

ちなみに```<title>```タグは```<head>~</head>```の間に書いても適用されません…
こちらの設定方法はこの後にご説明します。

### style.html
※CSSは全体が長くなってしまったので、割愛させていただきました…（´･_･`）

```css:style.html
<style>
/*---- 内容は割愛しますが、<style>タグの中に書き込みます ---*/
</style>
```

### scripts.html
```javascript:scripts.html
<script>
function handleFormSubmit(formObject) {
      google.script.run.withSuccessHandler().processForm(formObject);
}
</script>
```
登録ボタンが押されたあとの処理を記載しています。

## index.htmlの呼び出し
さて、ここまで終えたらWEBページとして表示させる準備をします。
GASはプロジェクトの中にHTMLファイルを用意しただけでは表示はされず、
htmlファイルを呼び出してあげる必要があり、```doGet```関数を使用します。

また、index.htmlの中で記述したincludeのおまじないの効力を発揮させるには
おなじく呼び出しをしてあげる必要があります。

※デフォルトの```myFunction```の記述は削除して大丈夫です。

```javascript:コード.gs
//inde.htmlファイルの呼び出し
function doGet() {
  return HtmlService.createTemplateFromFile('index')
     .evaluate()
     .setSandboxMode(HtmlService.SandboxMode.IFRAME)
     .setTitle('AdventCalendar');
}

//includeしたhtmlファイルの呼び出し
function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}
```
先ほど```<title>```タグは```<head>~</head>```の間に書いても～～、と書きましたが、
GASでWEBページを作るときは、```doGet```関数の中に記載します。
※```.setTitle('AdventCalendar');```です。


## フォーム送信後の処理
一番はじめにも書きましたが、今回のフォームは送信後に

- フォームを送信した人への自動返信
- 部内への申請通知

を行いたかったので、それぞれの処理を組み込みます。
ちなみにフォームを送信した人への返信はメールで、
部内への通知はHangouts Chatのチャットルームに投げ込む形です。

これらの処理も```コード.gs```に記載します。

```javascript:コード.gs
/* submit後の動作 */
function processForm(formObject) {
  
  //フォームの回答
  var range1 = 'Advent Calendarのような記事を書いたことが: ' + formObject.q1;
  var range2 = '書いたことがある回数は？: ' + formObject.q2;
  var payload_message1 = range1 + '\n' + range2;
  
  //POSTの設定
  var posturl = 'https://chat.googleapis.com/v1/spaces/AAAAzhOaP_Q/messages?key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  var payload = {
    "text": 'フォームが送信されました。\n\n' + payload_message1
  }
  
  var options = {
    "method" : "POST",
    "payload" : JSON.stringify(payload),
    "headers" : {
      "Content-Type" : "application/json; charset=UTF-8"
    },
    "muteHttpExceptions": true
  };
  
  //chatroomにPOST
  var result = UrlFetchApp.fetch(posturl, options);
  Logger.log(result.getContentText());
  
  //回答者にメールを送付
  var subject = 'フォームを送信しました。';
  var sentence = 'ご回答ありがとうございます。'; 
  var to_mail = formObject.mail;
  GmailApp.sendEmail(to_mail, subject, sentence);
}
```

```posturl``` にはハングアウトチャットのチャットルームで発行したwebhookのURLを入れます。
```GmailApp.sendEmail``` はGASでメールを送るときに使うメソッドです。
そのほか、フォームの回答を抜き出したり、文言を追加したりなどしています。

## 実際にWEBページとして表示させる。
さて、ここまででGASのプロジェクト内容用意すべきファイルの準備を終えました。
ということでいよいよWEBページとして表示させます。
とくに記載しませんでしたが、すべてのファイルの保存しておきましょう！

メニューバーの［公開］から［ウェブ アプリケーションとして導入...］を選択します。
![2018-12-12_16h33_08.png](https://qiita-image-store.s3.amazonaws.com/0/96973/a7e90462-78d3-22a9-dd42-4e0333943f37.png)

下記の表示が出てくるので、良しなに選択を変えてもらい、［導入］を選択します。
![2018-12-12_16h33_28.png](https://qiita-image-store.s3.amazonaws.com/0/96973/a319f42c-8b2e-3cd6-58f8-ec1e0a12860b.png)

初回時には必ず承認が求められますので、［許可を確認］で次に進みます。
![2018-12-12_16h33_35.png](https://qiita-image-store.s3.amazonaws.com/0/96973/3445dc43-6d0e-b8cd-1081-866fc0884550.png)

念のため内容を確認し、［許可］を選択してください。
![2018-12-12_16h34_09.png](https://qiita-image-store.s3.amazonaws.com/0/96973/4da3799b-92ca-1bf0-ca61-0785e169ba58.png)

これでようやくウェブアプリケーションとして導入できました！
現在のウェブアプリケーションのURLと書かれたURLを開きます。
![2018-12-12_16h34_18.png](https://qiita-image-store.s3.amazonaws.com/0/96973/ead98bb9-07d0-c4b9-d841-c2453738a20e.png)

WEBページとして表示させることができました！
![2018-12-12_17h15_07.png](https://qiita-image-store.s3.amazonaws.com/0/96973/4bd46d2a-a8a2-6a02-e5f4-ec39eec4a4c6.png)

## やってみよう、と思う方へ
### メールのformアドレスはファイルを作ったアカウントになる
GASからメールを送る```GmailApp.sendEmail```メソッドですが、
fromアドレスはファイルを作った人のGoogleアカウントとなります。
もちろん指定をすることも可能ですが、Gmailアカウントのエイリアスを設定する必要があり、
状況によってはハードルが高いかもしれません。。。
（なお、社内で私が作成したフォームはすべてfromアドレスが私のアカウントですｗ）

### フォーム送信後の処理
この記事内ではフォーム送信後のWEBページでの処理をとくにいれていないため、
登録ボタンを押すとWEBページが真っ白になってしまいます。
ページ上部に戻る、ラジオボタンの選択を解除などの処理を入れておくのがよいかと思います。

## まとめ
書き始めたらとても長くなってしまいましたが、

- Googleアカウントを利用している
- フォームを作りたいけど、Googleフォームだとちょっと要件的にむずかしい…
- Googleフォームより見た目にこだわりたい！
- HTML,CSS,Javascriptを触れる
- Googleのサービス（ハングアウトチャットやスプレッドシートなど）と連携させたい

といった条件に当てはまれば、GASを利用してみるものありかなあ、と思います。
もちろん自前でサーバをたてなくてもWEBサイトを表示させることができます！

[:christmas_tree: FORK Advent Calendar 2018](/advent-calendar/2018/fork)
:arrow_left: 12日目 [単層ニューラルネットワークをPythonで実装する](/fork_fujisawa/items/94d3d2b0e5362510e042) @fork_fujisawa
:arrow_right: 14日目 [Vue.js のサイト上での使用は NG だけど、Vue.js での開発はあきらめなかった話](/megurock/items/517c0d21b0aa4f0ed3b6) @megurock