GASで自分の行動を記録・可視化してみた

# 1. はじめに
ビジネス書を読んでいると、「自分の行動が無駄ではないかと疑ってみる」といったアドバイスを見かけました。そこで、そもそも自分の行動ってなんだ？と思ったので、ここでは行動を可視化するために作ったプログラムを自分へのメモも兼ねて紹介します。なお、初心者ゆえ最適な仕上がりとは思えませんが、ご留意ください。

# 2. 大まかな方針
「どんな行動に」「何分間」費やしたかを手軽に可視化することがゴールです。
本記事では、スプレッドシートとGAS（Google Application Script）にて記録するようにしました。
GASを採用した理由は、以下の２つです。
1. 自分の知る範囲で、手軽に自動実行できる
2. スプレッドシートはスマホから簡単に入力できる

何分間したか、は前回記録したときからの時間差分によって求められそうです。よって、ここでは何をしたか、を記入するだけでデータベースに追加してゆき、グラフ化してくれるようなものを目指しました。

# 3. スクリプト
まず、シートを準備します。以下のスクリプトにて、用意できるようにしました。

```javascript
function insertSheet() {
  // シートを追加する関数。スプレッドシート作るとき、使おう。
  var sheet_name = ["input", "dashboard", "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"];
  for(let i = 0; i < sheet_name.length; i++) {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    ss.insertSheet(sheet_name[i]);
    var activeSheet = ss.getSheets()[i+1];
    var date = new Date();

    if(i===0){
      activeSheet.getRange(1,1).setValue("本日は");
      activeSheet.getRange(1,2).setValue("=TODAY()");
      activeSheet.getRange(1,5).setValue("Last input time：");
      activeSheet.getRange(1,6).setValue(date).setNumberFormat('dd日 H時mm分'); // 現在の時間を書き出す
      activeSheet.getRange(3,3).setValue("今から");
      activeSheet.getRange(3,5).setValue("を始めます");
      activeSheet.getRange(6,1).setValue("昨夜の就寝時間：");
      activeSheet.getRange(7,1).setValue("本日の起床時間：");
    }

    if(i===1){
      activeSheet.getRange(1,1).setValue("2022年 Action Checker")
      activeSheet.getRange(6,1).setValue("日付")
      activeSheet.getRange(6,2).setValue("就寝時間 (min)")
    }

    if(i > 1){
      var activeSheet = SpreadsheetApp.getActiveSheet();
      activeSheet.getRange(1,1).setValue("Date");
      activeSheet.getRange(1,2).setValue("Action");
      activeSheet.getRange(1,3).setValue("Required time (min)");
      activeSheet.getRange(2,1).setValue(date).setNumberFormat('dd日H時mm分');
      activeSheet.getRange(2,2).setValue("先月からの申し送り事項（←はシート作成時の日付）");
    }
  }
}
```
こんな感じのを作れたかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530290/400230a7-f4a1-fcaa-f656-bf307ad3c1df.png)

続いて、3行D列に今からやることを入力していきます。入力した値は今月のシートに追加されていくようにします。なお、スクリプトを実行する前に、タイムゾーンを日本に合わせましょう（詳しくは参考文献を参照してください）。

```javascript
function del_value() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName("input");
  sheet.getRange(3,4).clearContent();
}

function to_table(){
  // この関数は、値を入力した時、今月のシートに追記していく関数
  // 値が更新された時、稼働する関数 

  var date = new Date();
  var month = date.getMonth()+1
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  // 今月のシートを指定
  var month_sheet = spreadsheet.getSheetByName(String(month) + "月");
  var lastRow = month_sheet.getRange(month_sheet.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  var sheet = spreadsheet.getSheetByName("input");

  // 値が空白ならば、実行しない
  if(sheet.getRange(3,4).isBlank()){
    Logger.log("空白のため、処理を終了します");
    return;
  }

  act = sheet.getRange(3,4).getValue();

  // inputシートに値を入れた時、その値と前回更新したときからの累計時間を計測
  pre_time = sheet.getRange(1, 6).getValue().getTime()
  now_time = date.getTime();

  sheet.getRange(1, 6).setValue(date).setNumberFormat('dd日 H時mm分'); // 現在の時間を書き出す
  Logger.log((now_time - pre_time) / (1000) + "秒")

  time = (now_time - pre_time) / (1000*60)
  
  month_sheet.getRange(lastRow+1, 1).setValue(date).setNumberFormat('dd日H時mm分');
  month_sheet.getRange(lastRow+1, 2).setValue(act);
  month_sheet.getRange(lastRow, 3).setValue(time);
  if(act=="就寝"){
    sheet.getRange(6,3).setValue(date).setNumberFormat('H時mm分')
  }else if(act=="起床"){
    sheet.getRange(7,3).setValue(date).setNumberFormat('H時mm分')
    var dash_sheet = spreadsheet.getSheetByName("dashboard");
    var dash_lastRow = dash_sheet.getRange(dash_sheet.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
    date.setDate(date.getDate()-1)
    var yesterday = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
    
    Logger.log(date.getDate());
    Logger.log(yesterday)
    dash_sheet.getRange(dash_lastRow+1, 1).setValue(yesterday);
    dash_sheet.getRange(dash_lastRow+1, 2).setValue(time);
  }else{
    // 何もしない
  }
  del_value()
}
```

すると、こんなふうに転記していくことができます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530290/a404d016-178b-2eba-c04a-b9f5b6ebe6f6.png)

最後に、このデータをグラフ化しましょう。単純な棒グラフを作るだけの些末なものですが…

```javascript
function df2graph(){
  var date = new Date();
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(String(date.getMonth()+1) + "月")
  var dash_sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dashboard")
  var datas = sheet.getDataRange().getValues();
  var today = new Date(date.getFullYear(), date.getMonth(), date.getDate(),3)
  var tommorow = new Date(date.getFullYear(), date.getMonth(), date.getDate()+1,3)
  flag = true
  for(var i = 2; i <= datas.length; i++) {
    // データの日時で、今日書き加えられた値なら抽出
    if(sheet.getRange(i,1).getValue().getTime() <= today.getTime()){
      // 何もしない
    }else if(today.getTime() < sheet.getRange(i,1).getValue().getTime() && sheet.getRange(i,1).getValue().getTime() < tommorow.getTime()){ 
      if(flag){
        start_i = i
        flag = false
      }
    }else{
      Logger.log("end")
      break;
    }
  }
  
  // Make Graph
  var range=sheet.getRange(start_i,2,i-start_i,2);
  Logger.log(start_i)
  var chart = sheet.newChart()
    .addRange(range)
    .setPosition(1,4,0,0)
    .setChartType(Charts.ChartType.BAR)
    .setOption('title',date.getMonth()+1 + '月' + String(date.getDate()+1) +'日の行動内訳')
    .setOption("hAxis", {title:'time (min)'})
    .build();
  sheet.insertChart(chart);
}
```
行動がグラフ化できました！（サッカーしすぎ笑）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530290/261505ba-9bf5-f49a-538b-14ac05355049.png)


# 4. 最後に
最後までお付き合いいただき、ありがとうございました。余談ですが、私の友人はプログラム抜きで行動をデータ化し、なんならABテストまでやって、無駄を削ぎ落としていったそうです。いずれは私も、そこまで徹底したいなぁ。

# 5. 参考文献
・[いまさらGASに入門したのでまとめてみた](https://qiita.com/h_okawa0303/items/d6295fe75b8598f06392)
・[5分で理解する　Google Apps Script](https://qiita.com/Brutus/items/efbd5fda4c9316fc9e3b)