GASとGoogleFormでイベント参加ボタンを作る

# 自己紹介

Qiita初投稿になります。

社会人2年目の新米エンジニアです。

既存事業担当チームにて開発業務をしています。

# イベント参加ボタンをなぜ作った？

自分は社内でLT大会を運営しており、今まで参加者を募る際は

スプレッドシートで作った名簿に記入してもらっていました。

今回、GoogleSiteを使ったイベントページを作って頂いたので

イベントページから直接参加できる仕組みを作ろうと思います。

# 実装方法

以下の記事を踏襲します。

[FormsとGASを使って既存のカレンダーイベントにゲスト追加する - Qiita](https://qiita.com/gohh56/items/496b4c0b0ddbb20fd7d6)

イベントページにグーグルフォームを埋め込み、回答してもらうことでLT大会のカレンダーイベントにゲスト追加されます。

また、追加要件として

2. キャンセルできるようにする
3. 次回以降も使い回せるフォーマットにする

以上を満たすように実装します。



## 概要

以下の手順で処理を行います。

1. フォームが回答される
2. Submitイベントにより以下を取得
   1. 申し込みした人のメールアドレス
   2. イベント名
   3. 開催日時
   4. 参加可否
3. イベント名と開催日時でカレンダー内を検索し、イベントを取得
4. 参加可否により分岐
   1. メールアドレスを使いイベントにゲストを追加
   2. メールアドレスを使いイベントからゲストを削除

------

次回以降、GASに変更を加えずに済むよう

- イベント名
- 開催日時

をフォームから取得できるようにします。
## 作成したフォーム

![フォーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/e8efe9b6-8d97-76cb-2077-4f4e3cd22923.png)
「タイトルと説明を追加」を使うことで開催日時の情報をフォームに持たせました。
イベント名も同様にフォームに持たせます。
また、「メールアドレスを収集する」オプションを有効にします。


## 作成したGAS

```javascript
function submitForm(e){
  // 申し込みした参加者のメールアドレスを取得
  var registerMail = e.response.getRespondentEmail();
  
  //フォームを取得
  var formItem = e.source.getItems();
  //フォームからタイトルに設定していた開催日を取得
  var searchEventDate = formItem[0].getTitle();
  
  //レスポンスを取得
  var itemResponses = e.response.getItemResponses();
  //レスポンスから質問タイトルに設定していたイベント名を取得
  var searchEventName = itemResponses[0].getItem().getTitle();
  
  // イベントを登録しているGoogleカレンダーを取得
  var calendar = CalendarApp.getCalendarById('イベントを登録しているカレンダーのID');
  
  //指定した日付かつイベント名で検索し、イベントを取得。
  var events = calendar.getEventsForDay(new Date(searchEventDate), {search: searchEventName})
  //イベントのIDを取得
  var event = calendar.getEventById(events[0].getId());

  //回答結果を取得
  var answer = itemResponses[0].getResponse()
  
  if(answer == '参加する'){
    //参加登録者をイベントへ追加
    event.addGuest(registerMail);
  }else{
    //参加登録者をイベントから削除
    event.removeGuest(registerMail);
  }  
}
```

上から順に解説します。
### 情報取得

```javascript:情報取得
  // 申し込みした参加者のメールアドレスを取得
  var registerMail = e.response.getRespondentEmail();
  
  //フォームを取得
  var formItem = e.source.getItems();
  //フォームからタイトルに設定していた開催日を取得
  var searchEventDate = formItem[0].getTitle();
  
  //レスポンスを取得
  var itemResponses = e.response.getItemResponses();
  //レスポンスから質問タイトルに設定していたイベント名を取得
  var searchEventName = itemResponses[0].getItem().getTitle();
```

eは[Event Objects](https://developers.google.com/apps-script/guides/triggers/events#form-submit_4)を指します。
質問とタイトルは参照するクラスが違います。（[Class FormResponse](https://developers.google.com/apps-script/reference/forms/form-response)と[Class Form](https://developers.google.com/apps-script/reference/forms/form)）

### カレンダー取得

```javascript:カレンダー取得
  // イベントを登録しているGoogleカレンダーを取得
  var calendar = CalendarApp.getCalendarById('イベントを登録しているカレンダーのID');
  
  //指定した日付かつイベント名で検索し、イベントを取得。
  var events = calendar.getEventsForDay(new Date(searchEventDate), {search: searchEventName})
  //イベントのIDを取得
  var event = calendar.getEventById(events[0].getId());
```
カレンダーのIDは対象のカレンダーの「設定」を開き、「カレンダーの統合」からカレンダーIDを確認します。
参考元のソースで使われているイベント取得メソッドが何故か動かなかったので、日付指定のもので代用しました。
`getEvents → getEventsForDay`
また、日付部分をフォームの情報から参照します。

```javascript:参考元
var events = calendar.getEvents(new Date('2018/1/1'), new Date('2018/12/31'), {search:searchEventName});　//　対象イベントが存在する期間を指定
```
### ゲスト操作
```javascript:ゲスト操作
  //回答結果を取得
  var answer = itemResponses[0].getResponse()

  if(answer == '参加する'){
    //参加登録者をイベントへ追加
    event.addGuest(registerMail);
  }else{
    //参加登録者をイベントから削除
    event.removeGuest(registerMail);
  } 
```
回答結果を取得し、その結果によってイベントに追加or削除をさせます。
`answer == '参加する'`はダサいので変えたほうが良いと思います。

# まとめ
まだまだ改良の余地がありそうなコードですが無事に完成させられてよかったです。
GASによる連携は強力で、簡単にやりたい機能を実装できて感動しました。
GoogleSiteに直で埋め込むとどうしても浮いてしまうので、以下記事のように溶け込ませたいなぁと思いました。
[Googleフォームを自在にカスタマイズする - Qiita](https://qiita.com/sota6412/items/fa077cbf820faca30598)