GoogleForm × GoogleCalendar × GAS で 動的に日付の選択肢を作る

## 目的
名古屋のアプリ開発団体jackという団体を運営しており、jackに遊びに行きたい！といってくれる方の管理をするのが大変だったので、「いつの活動に来るか？」をきくGoogleFormを作ろうとなった。
しかし、フォームを送るたびに活動日を書き込むのは面倒だったので、「GoogleCalendarの活動日程から選択肢を自動で生成したろ」となったのが経緯。

## 完成図
こんな感じのフォームで、日付の部分がGoogleCalendarと連動するようにした。
<img width="869" alt="スクリーンショット 2019-06-23 15.47.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211192/f42ff445-17ec-af92-3c7d-4bfd9734350f.png">


## 方法
### 1. GoogleCalendarに予定をかき入れる
ここはもうすでにやっている人はすっ飛ばして良い

### 2. GoogleFormを作成する
元となるGoogleFormを作成する

### 3. GASとGoogleFormを連携
GoogleFormの右上のテンテンテンから「スクリプトエディタ」を選択し、GASを開こう

### 4. GoogleFormにGASから質問を追加
以下のスクリプトを組み、updateFormDate()関数を実行することでGASからGoogleFormに質問を追加できる。
(GoogleFormとGoogleCalendarのidの取得方法は下に補足しておいたのでそちらを参照してください)

```js:追加.js
DATE_QUESTION_TITLE = "遊びに来れる日程を選んでください！"

// 実際に実行する関数
function updateFormDate() {
  var form = FormApp.openById("googleFormのId")
  addDateMultipleChoiceItem(form)
}

// 受け取ったフォームに、活動日の選択肢をつっこんっだラジオボタンの質問を追加する
function addDateMultipleChoiceItem(form) {
  var item = form.addMultipleChoiceItem()
  var options = activitiesDateStrs()
  options.push("これら全て都合が悪い")
  item.setTitle(DATE_QUESTION_TITLE).setChoiceValues(options)
}

// 選択肢を生成する
function activitiesDateStrs(){
  var calendar = CalendarApp.getCalendarById('googleCalendarのID');
  var today = new Date()    
  var after2w = new Date()
  after2w.setDate(today.getDate() + 14)
  var events = calendar.getEvents(today, after2w);
  var dateStrs = []
  
  events.forEach(function(event){
    var date = event.getStartTime()
    dateStrs.push(getDateStr(date))
  })
  return dateStrs
}

// 日付文字列を作成
DAYS = [ "日", "月", "火", "水", "木", "金", "土" ]
function getDateStr(date){
  var dateStr = (date.getMonth() + 1) + " / " + date.getDate() + "(" + DAYS[date.getDay()] + ") " + date.getHours() + ":" + date.getMinutes() + " ~"
  return dateStr
}
```

### 5. 選択肢のupdateができるようにする
このままのスクリプトだと、質問が追加されるだけなので、質問が無駄に増えていってしまう。
もともとある質問を消してから追加をするようにすればこれは解決！

```js:完成.js
DATE_QUESTION_TITLE = "遊びに来れる日程を選んでください！"

// 実際に実行する関数
function updateFormDate() {
  var form = FormApp.openById("googleFormのId")
  removeDateMultipleChoiceItem(form) /* 追加 */
  addDateMultipleChoiceItem(form)
}

/* 追加 */
// もともと合った選択肢を消す
function removeDateMultipleChoiceItem(form) {
  form.getItems().forEach(function(item){
    if (item.getTitle() == DATES_ITEM_TITLE){
      form.deleteItem(item)
    }
  })
}

// 受け取ったフォームに、活動日の選択肢をつっこんっだラジオボタンの質問を追加する
function addDateMultipleChoiceItem(form) {
  var item = form.addMultipleChoiceItem()
  var options = activitiesDateStrs()
  options.push("これら全て都合が悪い")
  item.setTitle(DATE_QUESTION_TITLE).setChoiceValues(options)
}

// 選択肢を生成する
function activitiesDateStrs(){
  var calendar = CalendarApp.getCalendarById('googleCalendarのID');
  var today = new Date()    
  var after2w = new Date()
  after2w.setDate(today.getDate() + 14)
  var events = calendar.getEvents(today, after2w);
  var dateStrs = []

  events.forEach(function(event){
    var date = event.getStartTime()
    dateStrs.push(getDateStr(date))
  })
  return dateStrs
}

// 日付文字列を作成
DAYS = [ "日", "月", "火", "水", "木", "金", "土" ]
function getDateStr(date){
  var dateStr = (date.getMonth() + 1) + " / " + date.getDate() + "(" + DAYS[date.getDay()] + ") " + date.getHours() + ":" + date.getMinutes() + " ~"
  return dateStr
}
```

### 6. 毎日実行する設定をする
最後に日付が変わるとともにこのupdateFormDateを実行するようにトリガーを指定しておけば良い。
自分は毎日0~1時にこの関数を実行するようにした。
(トリガーの指定方法は補足にあります)

## 感想
デフォルトでカレンダーから値取ってくるようなGoogleFormの仕組みあったりしないかなぁ
あんま探さないで作ってしまった。
もし今なくてもそのうち出てきそうな気がした。

## 補足
##### GoogleCalendarのIDの取り方
→ http://www.sukicomi.net/2018/07/google-calendarid.html
##### GoogleFormのIDの取り方
GoogleFormのURLをみて
`https://docs.google.com/forms/d/{ここがIDになってるよ}/edit`
上の{}で囲まれた部分がidになっている
##### トリガーの指定方法
→　https://reasonable-code.com/gas-trigger/