新卒一年目がGASで日報自動出力アプリケーションを作るまで（1/2）

## 問題
「毎日提出する日報を毎日タイピングするのが面倒」
シンプルな問題ですね。可能な限り記入箇所を自動入力できるようにしたいです。

## 前提
弊社日報のフォーマットは
- やったことの名前
- 予定時間
- 実績時間
- 実績時間の合計
という感じになってます（一応内部情報なんでぼやかします）

そして私は**Googleカレンダーで予定管理を行ってます**。
タスクをこなす前に予定をGoogleカレンダーに記入し、終わったら超過した時間をカレンダーに反映させ、次の予定の開始時間調整をし**最終的にGoogleカレンダーに実績が記録されます**

## 開発要件
つまり…Googleカレンダーと連携して**始業時にタスクごとに予定時間を保存**し**終業時に実績時間を保存**し最終的に**日報のフォーマットで出力される**ことが出来れば完璧です。

## 出来上がるイメージ
Webアプリケーションで
始業時に「予定記録」ボタンをクリックし予定時間を記録し
終業時に「実績記録」ボタンをクリックし実績時間を記録し
「日報出力」ボタンで日報を自動出力

## 技術選定
Googleカレンダー連携が簡単なため、GoogleAppsScriptを使用

## 開発の流れ
- GASでWebアプリケーションを公開する
- Googleカレンダーから今日の予定を吸い上げる
（今回ここまで）
- Googleカレンダーの予定をSpreadSheetに保存
- SpreadSheetの内容を読み取ってWebアプリケーションに出力

## GASでWebアプリケーションを公開する
以下2ファイルを新規にスクリプトファイルを作成して生成

```Javascript:nippo.gs
// アクセス時にindex.htmlを読み込む
function doGet(){
  return HtmlService.createHtmlOutputFromFile('index').setTitle('nippo').addMetaTag('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0');
}
```


```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
  <!-- とりあえずHello World -->
    Hello World
  </body>
</html>
```

- スクリプトエディタの「公開」→「ウェブアプリケーションとして導入」
- 「プロジェクトバージョンを指定」
- 次のユーザーとしてアプリケーションを実行「ウェブアプリケーションにアクセスしているユーザー」
- アプリケーションにアクセスできるユーザー「全員（匿名ユーザーを含む）」
- 「導入」をクリック
- 生成されたURLを開いてみる

Googleアカウントでログインすると見れます
![スクリーンショット 2017-12-02 19.13.52.png](https://qiita-image-store.s3.amazonaws.com/0/217058/146aa794-8771-7454-644a-0a2d89b655c1.png)


## Googleカレンダーから今日の予定を吸い上げる

### GAS上で吸い上げる
GoogleAppsScriptでGoogleカレンダーから予定を吸い上げるためには以下の通りにします。

```Javascript
// アクセス時にindex.htmlを読み込むよー
function getCal(){
  var cal_id = "★カレンダーID"
  //基本的にカレンダーのIDはメールアドレスですが、複数カレンダーを作成して運用している場合は「Googleカレンダー」→「取得したいカレンダーの『設定と共有』」→「カレンダーの統合」→「カレンダーのID」と探します
  var cal = CalendarApp.getCalendarById(cal_id);
  var now = new Date();
  var events = cal.getEventsForDay(new Date(now.getFullYear(), now.getMonth(), now.getDate()));
  
  for(var i=0; i < events.length; i++){
    //終日イベントかどうか判別
    if (events[i].isAllDayEvent()) {
    //終日イベントの場合はなにもしない
    } else {
      Logger.log(events[i]);
    }
  }
}
```

これではgetCalを実行して、ログを見てもイベントがいくら出力されるだけです
![スクリーンショット 2017-12-02 17.46.57.png](https://qiita-image-store.s3.amazonaws.com/0/217058/f675f9e4-0f3d-f476-4529-dcb1127750f5.png)


それでは、それぞれの「イベント名」「開始時間」「終了時間」「所要時間」「イベントのID」を出力してみましょう

```Javascript:nippo.gs
function getCal(){
  var cal_id = "★カレンダーID"
  //基本的にカレンダーのIDはメールアドレスですが、複数カレンダーを作成して運用している場合は「Googleカレンダー」→「取得したいカレンダーの『設定と共有』」→「カレンダーの統合」→「カレンダーのID」と探します
  var cal = CalendarApp.getCalendarById(cal_id);
  var now = new Date();
  var events = cal.getEventsForDay(new Date(now.getFullYear(), now.getMonth(), now.getDate()));
  
  for(var i=0; i < events.length; i++){
    //終日イベントかどうか判別
    if (events[i].isAllDayEvent()) {
    //終日イベントの場合はなにもしない
    } else {
      Logger.log(events[i].getTitle()) //イベント名
      Logger.log(events[i].getId()) //イベントID
      Logger.log(events[i].getStartTime()) //イベント開始時間
      Logger.log(events[i].getEndTime()) //イベント終了時間
      Logger.log(events[i].getEndTime() - events[i].getStartTime()) //イベント所要時間
    }
  }
}
```

![スクリーンショット 2017-12-02 18.02.45.png](https://qiita-image-store.s3.amazonaws.com/0/217058/32565df6-c7c1-258f-9f6f-af5bb140f1ed.png)


## 結果をHTMLに書き出し
とりあえずイベント一覧をHTMLに書き出して見ましょう。
HTMLを以下のように変更して

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
    function getdata(){
      google.script.run.withSuccessHandler(result).getCal();
      function result(data){
        document.getElementById("events").innerHTML = data;
      }
    }
   </script>
  </head>
  <body>
<button onclick="getdata();">今日の予定を出力</button>
<p id="events">ここに今日の予定が出力されます</p>
  </body>
</html>
```

JavascriptをHTML出力できるよう調整・返り値を設定

```Javascript:nippo.gs
function getCal(){
  var cal_id = "★カレンダーID"
  //基本的にカレンダーのIDはメールアドレスですが、複数カレンダーを作成して運用している場合は「Googleカレンダー」→「取得したいカレンダーの『設定と共有』」→「カレンダーの統合」→「カレンダーのID」と探します
  var cal = CalendarApp.getCalendarById(cal_id);
  var now = new Date();
  var events = cal.getEventsForDay(new Date(now.getFullYear(), now.getMonth(), now.getDate()));
  var event_list_str = "";
  
  for(var i=0; i < events.length; i++){
    //終日イベントかどうか判別
    if (events[i].isAllDayEvent()) {
    //終日イベントの場合はなにもしない
    } else {
      event_list_str = event_list_str + "イベント名：" + events[i].getTitle() + "<br>";
      event_list_str = event_list_str + "イベントID：" + events[i].getId() + "<br>";
      event_list_str = event_list_str + "開始時間：" + events[i].getStartTime() + "<br>";
      event_list_str = event_list_str + "終了時間：" + events[i].getEndTime() + "<br>";
      event_list_str = "<p>" + event_list_str + "所要時間：" + ((events[i].getEndTime() - events[i].getStartTime())/3600000) + "h</p>";
    }
  }
  return event_list_str
}
```

これでHTMLのボタンクリックすると今日の予定が一覧になって返ってくると思います。
![スクリーンショット 2017-12-02 19.00.46.png](https://qiita-image-store.s3.amazonaws.com/0/217058/e08b6a4e-43c2-9fb3-fc20-f0454560e250.png)



次回で予実の計算までできるようにしたいと思います。

[スローガン株式会社のAdventCalendar](https://qiita.com/advent-calendar/2017/slogan)