出退勤管理ソフトを作ってみた～その２～ Google Spreadsheet編

# シリーズ目次

- [出退勤管理ソフトを作ってみた ～その１～ 監視サーバー編](https://qiita.com/sasaco/items/fe3afb25790cf9482cea)
- 出退勤管理ソフトを作ってみた ～その２～ Google Spreadsheet編



# 仕組み

[前回](https://qiita.com/sasaco/items/fe3afb25790cf9482cea)の続き

面倒な出退勤管理、全部自動でできたらいいですよね。
職場についたら出勤記録、出たら退勤記録が自動で付くやつ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/142847/71f8f61a-56fb-495d-4b23-27c6adeb3bac.png)

作ってみました。

今回は 
**通知を受け取った Google Apps Script が、Google Spreadsheet に打刻する** 部分の解説です。

サンプルは[ここ](https://docs.google.com/spreadsheets/d/1AGqbhUiSy47sXSsmDnfQkApGEGq_cVDKpxQFU0ZON-M/edit?usp=sharing)に公開します。

<iframe src="https://docs.google.com/spreadsheets/d/e/2PACX-1vSpWlO0qbPNwdCEFMAhFePe6MRLXPcpuLDBVvqvBUlqyc3h7jmmCR1G0TAQup0ZWEVSkmUMsSUlElCa/pubhtml?widget=true&amp;headers=false"></iframe>

## Google Apps Scriptの書き方

GAS側のスクリプトの書き方を見ていきましょう。

まずスプレッドシートの編集画面を開いて、ツールから「スクリプトを編集」をクリックします。すると以下のようなコードの編集画面が現れます。

```javascript
function doPost(e){

  var name = e.parameters["value"][0];          //IFTTTから名前を受け取る1

  var id = '1AGqbhUiSy47sXSsmDnfQkApGEGq_cVDKpxQFU0ZON-M/edit#gid=0';          //スプレッドシートファイルのID（URL）
  var ss = SpreadsheetApp.openById(id);                             
  var sheet = ss.getSheetByName(name);
  
  var day = new Array('日', '月', '火', '水', '木', '金', '土');
  var date = new Date();                        //日時の取得
  var year = date.getFullYear();
  var mon = date.getMonth()+1;
  var d = date.getDate();
  var min = date.getMinutes();
  var time = date.getTime();

  var lm25 = ((mon!=1)?year:year-1)+'/0'+((mon>26)?mon:mon-1)+'/'+25;
  var llm25 = ((mon!=1&&mon!=2)?year:year-1)+'/0'+((mon>26)?mon-1:mon-2)+'/'+25;
  
  var row = sheet.getLastRow();
  var ld = sheet.getRange('A'+row).getValue();                      //最後の行の日付を取得（Date型？）
  var ldy = ld.getFullYear();
  var ldm = ld.getMonth();
  var ldd = ld.getDate();
  var ldt = ld.getTime();
  var lds = ld.getFullYear()+'/'+(mon>=10?mon:'0'+mon)+'/'+ld.getDate();
  var l25, ll25;
  
      //新たに取得した日付が最終行の日付と一致しないかどうかで分岐
    if(mon != ldm+1 || d != ldd){                     //一致しなければ出勤扱い、新しい行に打刻
        var range = sheet.getRange('A'+(row+1)+':D'+(row+1));
        range.setValues([[year+'/'+(mon>9?mon:'0'+mon)+'/'+d, day[date.getDay()], "", date.getHours()+':'+(min>=10?min:'0'+min)]]);
    }

    else{                                           //一致すれば終了時刻に上書き
        var range = sheet.getRange('E'+row+':F'+row);
        range.setValues([[date.getHours()+':'+(min>9?min:'0'+min), '=E'+row+'-D'+row]]);
    }

}
```
欲しい情報は「誰が」「いつ」「出勤したのか退勤したのか」です。

e.parameterで通知する側の`value=`に入力した値を受け取れますから、ここで誰の出退勤なのかを区別できます。

日時はプログラムが実行された時に、javascriptの標準関数Date()を使って取得しています。

どのスプレッドシート（ファイル）なのかを識別するのにid、シートを識別するのにnameを使っていますが、ここでの**idはスプレッドシートのURL**なので注意してください。スプレッドシートの編集画面を開くとアドレスバーに表示されるURLの下のd/ディレクトリ以下の部分です。先ほど使ったwebアプリケーションのURLではありあません。

![123.jpg](https://qiita-image-store.s3.amazonaws.com/0/142847/58c66c1c-a640-d94f-c871-d9d931ec4313.jpeg)

また書き込むセルの位置は、getLastRow関数でシートに値が書き込まれている最後の行を取得することで、出勤と退勤の区別は、LastRowのE列が空かどうかで見ています。

ところで、出社した後も 15分毎にPOSTリクエストが送信されてプログラムが実行されます。
そこで出勤時間はその日最初の実行時をとり（if文のところ）、2回目以降の実行時間を退勤時間のセルに上書きすることで対処してます（else文のところ）。

## テスト実行の仕方

プログラムを試験的に走らせたい時にいちいち「公開」→「ウェブアプリケーションとして導入」の流れをやるのは大変ですので、doPostTest関数を書いて実行すればテストできます。

```javascript
function doPostTest(){
  var e = new Object();
  var postData = new Object();
  postData.type = "application/json";
  postData.contents = "{\"key\":0}";
  e.postData = postData;
  doPost(e);
}
```