Googleカレンダーの予定から出席簿とSlackメンション用のリストを作成するスクリプトを作った話 ~ある飲み会幹事の苦悩~

# TL:DR
- 飲み会の幹事をやる上で面倒なのは出欠確認。
- googleカレンダーから参加者、参加未確定者をスプレッドシートに出力するGASを書いた。
- 単に出力するだけでなくSlackでメンションしやすいようにもした。

# 事の発端
会社で送別会とか新忘年会その他諸々の飲み会の幹事になった時、何が一番大変か。
お店決め？予約？お金の徴収？
それも確かに大変。でももっと大変だと思うのは**「出欠の確認」**。
勤め先では予定をgoogleカレンダーで管理しており、MTGを開催するときとかは招待を送るようになっている。
参加するときは参加ボタン、欠席のときは欠席ボタンを押すことで出欠を取るのだが、飲み会の予定もまたその形式で出欠を取るようになっている（少なくとも弊社ではそう。総人数の確認が楽だし）。
そこで何が起きるのか。
それは**「出欠ボタンを押さない人がいることで最終人数が確定しない」**ことだ。
そうするとお店にも人数の連絡ができない。でも予定日は待ってくれない。
もし予定した人数と間違うとお金の精算金額も変わってくる。その事も参加者に伝えないといけない。幹事って本当に大変。
10人くらいだったらSlackで個別にメンションしたり席に行って直接聞いたりしてなんとかなるけど、
これが20人30人、はたまた100人近くの人が参加対象になった時、実際に出欠ボタンを押してくれるのは何%か。
ついこの前企画した送別会でいうとおよそ40%しか押してくれてなかった。つまりおよそ60人は参加未確定。
60人に対してヒアリングしに席に向かう？めんどいからSlackでメンションする？それでも60人を？
これが超めんどかったので少しだけ楽にしてくれるスクリプトを作りました。

# やりたいこと
- 参加する人、未確定の人を一覧で出してリスト化する。
    - すでに欠席の人は連絡しなくてもいいから考えない。
    - 後々、お金徴収したかメモるように使いたい。
- コピペするだけでSlackで複数人にメンションできるようにする。
    - チャンネル作成時にまとめて招待する時とか、参加未確定の人にのみメンションつけてpostするときとかに楽したい
- いい感じに再利用できるようにしたい
    - 幹事をやるのは一回とは限らない。一回幹事をやった人間はその後何回も頼まれるのが世の常。

# 前提
- スプレッドシートを作成し、「ツール」からスクリプトエディタを開いておく

# スクリプト
```コード.gs
var TARGET_DATE = 'yyyy-mm-dd'
var EVENT_NAME = 'hogehogehoge'
var CALENDER_ID = 'xxxxx@example.jp'

var STATUS_YES = "YES"
var STATUS_INVITED = "INVITED"

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet(); 
  var calendar = CalendarApp.getCalendarById(CALENDER_ID);
  var date = new Date(TARGET_DATE)
  var target_event;

  // 全イベントを配列にして取得しフィルタリングする
  var events = calendar.getEventsForDay(date)
  for (var i in events) {
    if (events[i].getTitle() == EVENT_NAME) {
      target_event = events[i]
      break;
    }
  }
  
  if (!target_event) {
    throw new Error("指定した予定がないよ")
  }
 
  // スクリプトを複数回実行することを考えて一回リセットする
  sheet.clear()
  
  sheet.getRange(1, 1).setValue(EVENT_NAME)
  sheet.getRange(2, 1).setValue("参加者")
  sheet.getRange(3, 1, 1, 4).setValues([["名前", "メルアド", "Slackメンション用", "お金もらった？"]])
  
  var guests = target_event.getGuestList(true)
  var startRow = 4
  write_guests(sheet, guests, STATUS_YES, startRow)
  
  var lastRow = sheet.getLastRow()
  sheet.getRange(lastRow + 1, 1).setValue("未回答者")
  write_guests(sheet, guests, STATUS_INVITED, lastRow + 2)
}

function write_guests(sheet, guests, target_status, startRow) {
  var cnt = 0;
  for (var j in guests) {
    if (guests[j].getGuestStatus() == target_status) {
      var name = guests[j].getName()
      var email = guests[j].getEmail()
      // Slackメンション用
      var mention = "@" + guests[j].getEmail().slice(0, guests[j].getEmail().indexOf("@"))
      
      var values = [[name, email, mention]]
      sheet.getRange(startRow + cnt, 1, 1, 3).setValues(values)
      cnt++
    }
  }
}

```

```
var TARGET_DATE = 'yyyy-mm-dd'
var EVENT_NAME = 'hogehogehoge'
var CALENDER_ID = 'xxxxx@example.jp'
```
基本的にこの３種類を変更するだけです。
それぞれの説明は以下。

| 変数名       | 説明                 |
|------------------|-------------------|
| TARGET_DATE      | 参加者を出したい予定がある年月日 |
| EVENT_NAME       | googleカレンダーに記載してある予定の名前 |
| CALENDER_ID      | googleカレンダーのID。自分の予定から取得したい場合は自分のメールアドレスで問題ないです。 |

# 出力イメージ
<img width="540" alt="スクリーンショット 2020-02-15 12.31.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100993/84ba1277-fb21-da47-da44-bdeb13192c59.png">

（個人情報保護観点より値は適当なものに変換してあります。）
今は未回答者も見せるため人数を少なくしていますが、実際はこれの倍くらい人数がいたり殆どが未回答者でした。
例えばSlackで送別会用のチャンネルを作成したいときは、「Slackメンション」列にある値たちをコピペしてあげるだけで、一気に招待できます。
また、未回答の人だけメンションしたいのなら「未回答者」にある「Slackメンション」列の値をコピペするだけで一気にメンションを送れます。未回答者にはどんどんメンションしていきましょう。

# まとめ
幹事にはならないほうが一番楽なのですが、そうは言ってられない時もあります。
そのときに少しでも助けになれれば、これ以上の幸せはありません。
（そんな時間かけて作ったものじゃないので、なにか気になるところとかあったら個人で修正していい感じにしてあげてください。）