FormsとGASを使って既存のカレンダーイベントにゲスト追加する

これは[Google Apps Script Advent Calendar 2018](https://qiita.com/advent-calendar/2018/gas)　- 10日目の記事です。

今回アドベントカレンダー初参加になります。

Google Apps Script(以下GAS)を使っていろんなことをやるのが好きで、ちょいちょい小さなコードを書いて自動化を進めています。
そんな中で今回Google　Formsを利用して、記入者＝申し込み者をカレンダーの既存イベントに追加するということをやろうとしたら、意外に記事がなかったので残しておきたいと思います。

## やりたいこと

- Google Formsを使ってイベント申し込みを受付けたら、Googleカレンダーの既存のイベント予定にゲスト追加する。（これで参加者は同じ予定を確認できるし、他の参加者も確認できるようになる。）

    ※新規イベント作成ではなく、あくまで既存イベントを共有するカタチにしたい。

## そのために実現する必要があること

- 既存カレンダーイベントの取得
- 申し込みした人のメールアドレスの取得
- イベントIDで取得したカレンダー予定にゲスト追加

## 既存カレンダーイベントの取得

Googleカレンダーではカレンダー毎、また登録された予定＝イベント毎に一意なIDが振られています。これを取得することでそのカレンダーやイベントに対してGASを使って操作が可能になります。

スプレッドシードなどはURLの一部がIDとなっているので、それをコピペしてしまえば対象のスプレッドシートを指定できるのですが、Googleカレンダーはそうはいかず、イベントのプロパティなどからイベントIDを取得することができませんでした。（これができるようになると楽なのですが・・・。）

また、イベントIDも直接イベント名などから取得するというのができそうになかったので、以下の手順で取得しました。

- カレンダーIDでカレンダーを取得。
- イベント名からイベントを検索し、その結果のイベントIDを取得。
- 上記をスプレッドーシート上で一旦仮置きする。

順に解説です。

### カレンダーIDでカレンダーを取得。

まず、対象のカレンダーの「設定」を開き、「カレンダーの統合」からカレンダーIDを確認します。
これはGASではなく、設定画面から確認ができます。

### イベント名からイベントを検索し、その結果のイベントIDを取得。＆ スプレッドシートにイベントIDを仮置きする。

次にカレンダーからイベントを検索して、イベントIDを取得します。
※ちなみにイベントIDがなにか確認したかったので一旦スプレッドシートに書き出すやり方にしましたが、Forms内で取得することも可能です。

```javascript:eventIdGet.js
function eventIdGet() {
  var calendar = CalendarApp.getCalendarById('カレンダーID');
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var inputSheet = ss.getSheetByName('イベントIDを出力するシート名');
  var searchEventName = 'イベント名';
  var events = calendar.getEvents(new Date('2018/1/1'), new Date('2018/12/31'), {search:searchEventName});　//　対象イベントが存在する期間を指定
  var eventId = events[0].getId(); // getEvents()では配列が戻り値となるので、その中で対象のイベントを取得する必要があるが、そもそも検索するイベント名が一意であれば1要素のみとなるため、このような指定。
  inputSheet.getRange('出力先セル指定').setValue(eventId);
}
```

これで対象のイベントのイベントIDが取得できました。
※なんだか遠回りしているように感じるので、もっと簡単なやり方があるなら教えてほしい・・・。

## 申し込みした人のメールアドレスの取得

これはFormsの設定で「メールアドレスを収集する」にチェックを入れておきましょう。

その上で、以下のGASでメールアドレスが取得できます。これは簡単ですね。

```javascript:getMailAdress.js
function submitForm(e){ 
  // 申し込みした参加者のメールアドレスを取得
  var registerMail = e.response.getRespondentEmail();
}
```

## イベントIDで取得したカレンダー予定にゲスト追加

追加するゲスト＝メールアドレス、追加する先のイベントの特定＝イベントIDがそれぞれわかったので、これを使って既存イベントへ新規ゲストを追加します。
ここでは例として先程取得した申込みした参加者のメールアドレスを引数にします。

```javascript:addToEvent.js
function addToEvent('追加したい人のメールアドレス'){
  // Googleカレンダーを取得
  var calendar = CalendarApp.getCalendarById('カレンダーID');

  // 該当申し込みカレンダーのイベントIDを取得
  var refSs = SpreadsheetApp.openById('イベントIDを出力しておいたスプレッドーシートのID');
  var refSheet = refSs.getSheetByName('イベントIDを出力したシート名');
  var eventId = refSheet.getRange('イベントIDの値があるセル').getValue(); 
  var event = calendar.getEventById(eventId);

  //参加登録者をイベントへ追加
  event.addGuest('追加したい人のメールアドレス');
}
```
これで既存イベントにFormsから申し込んだ人を新規にゲストとして自動で追加してくれます。

## 全部をGASないだけで完結する場合

こんな感じでしょうか。
指定する期間とイベント名あたりを与えられるとハードコーディングで無くなりそうです。

```javascript:addRegisterToEvent.js
function submitForm(e){
  // 申し込みした参加者のメールアドレスを取得
  var registerMail = e.response.getRespondentEmail();

  // Googleカレンダーを取得
  var calendar = CalendarApp.getCalendarById('カレンダーID');

  // 該当申し込みカレンダーのイベントIDを取得

  var searchEventName = 'イベント名';
  var events = calendar.getEvents(new Date('2018/1/1'), new Date('2018/12/31'), {search:searchEventName});　
  var event = calendar.getEventById(events[0].getId());

  //参加登録者をイベントへ追加
  event.addGuest(registerMail);
}
```

## まとめ

まだ改善の余地がありそうですが、これでFormsから広く申し込みを受付け、同一の予定を共有することが自動化できるようになりました。Formsはアンケートだけでなく、こういった機能を実装することで申し込みフォームとしても活躍できます。
実装方法としては改善余地がありそうなので、より手間をかけずにフォーム作成→カレンダー追加が楽にできるようにしてみたいと思います。

## 補足

カレンダーへの追加時に参加するかどうかのメールは飛びませんでした。なにか設定が別であるのかもしれません。