LINE NotifyとGoogleAppsScriptを使ってイベント通知アプリを作成してみた

# 環境
macOS
GoogleAppsScript
GoogleSpreadSheet
LINE Notify

# 概要
LINEに自分の予定やイベントを自動で通知できるアプリを作りました。
備忘録として残しておきたいと思います。

# 達成したいゴール
GoogleAppsScript（以下：GAS）を使用してGoogleスプレッドシートに書いた内容をLINEに送れるようになること。

# 解決したい問題
GASとスプレッドシートについての知識や理解が乏しいこと。
まずは、GASとは何かから初めていきたいと思います。

# GoogleAppsScriptとは
「Google Apps」とは、Googleが提供する、Gmail、Googleカレンダー、Google ドライブ、ハングアウト、Googleドキュメントなどのサービスを指します。
最近になって、企業向けのものは「G suite」と改称されました。
「Google Apps Script（以下：GAS）」とは、GoogleのサービスをJavaScriptで操作するための環境を指します。 Googleのサービスを使いやすくするため、JavaScriptにAPIを追加したものです。
そのため、JavaScriptの知識が必要になります。
一般的なJavaScriptは、フロントサイドを操作するためのプログラミング言語です。
一方、Node.jsのようなサーバーサイドを操作するためのJavaScriptがあります。

GASは、サーバーサイドのスクリプト言語という立ち位置になります。
そのため、Webブラウザに用意されているJavaScriptのAPIは基本的に使用できません。
alertやgetEventListener、windowなどのオブジェクトは使用できません。

以上が大まかなGASの概要です。

# Googleスプレッドシートのオブジェクト
GASでは、Googleスプレッドシートは「SpreadsheetApp」オブジェクトとして用意されています。
下記の①から④の順に階層構造でオブジェクトが用意されています。

①スプレッドシートアプリケーション（アプリケーション本体）
「SpreadesheetApp」オブジェクト

②スプレッドシート（スプレッドシートのドキュメント本体）
「Spreadsheet」オブジェクト

③シート（各シート）
「Sheet」オブジェクト

④レンジ（セルの範囲を示したもの）
「Range」オブジェクト

次に、各オブジェクトを取得する方法について解説していきます。  

# オブジェクトを取得するメソッド
■SpreadsheetApp.getActiveSheetメソッド
選択されたシートを取得するコードの書き方は下記になります。

```js
var sheet=SpreadsheetApp.getActiveSheet();
```

■getRangeメソッド
Range（セルの範囲）を取得するコードです。

```js
var range=sheet.getRange("｛セルの番地｝") 
var range=sheet.getRange("｛セルの番地（始まり）｝:｛セルの番地（終わり）｝") 
var range=sheet.getRange(｛行番号｝,｛列番号｝) 
var range=sheet.getRange(｛行番号｝,｛列番号｝,｛行数｝) 
var range=sheet.getRange(｛行番号｝,｛列番号｝,｛行数｝,｛列数｝)
```

■getValueメソッド
1つのセルを取得するコードです。

```js
var ｛戻り値｝=range.getValue();
```

■getValuesメソッド
指定したセル全てを取得するコードです。

```js

var ｛戻り値｝=｛Rangeオブジェクト｝.getValues();
```
セルが複数なので、getValuesと複数形となっています。

■setValueメソッド
セルに値を入力するコードです。

```js
var ｛戻り値｝=｛Rangeオブジェクト｝.setValue(｛入力値｝);
```

■getCellメソッド
Rangeオブジェクトには、さらに相対位置で1つのセルを選択できるgetCellメソッドがあります。

```js

var ｛Rangeオブジェクト｝=｛Rangeオブジェクト｝.getCell(｛行番号｝,｛列番号｝)
```

■getNumRowsメソッド
行数を取得するコードです。

```js
var ｛戻り値｝=｛Rangeオブジェクト｝.getNumRows()
```

■列数を取得するgetNumColumnsメソッド

```js
var ｛戻り値｝=｛Rangeオブジェクト｝.getNumColumns()
```

ここまで、基本的なGASの基本文法について解説してきました。
次に機能実装に必要なオブジェクトをみていきたいと思います。

# 機能実装に必要なオブジェクト
■Utilities.formatDate(date, “JST”,”yyyy/MM/dd”);
日付の文字列を成型するオブジェクト。
スプレッドシートに記載した日付と実際の日付を比較する際に同じ文字列になっている必要があります。

■getLastLow();
GASでスプレッドシートの最終行を取得するオブジェクトです。

■new Date();
括弧内に引数を指定しない場合は、現在の日時を取得できます。

■for(初期化式; 条件式; 増減式) {// 繰り返す処理}
GASで繰り返し処理をしたいときにfor文を使用します。
◎例文

```js
//繰り返し処理(1行ずつ処理し、行の数だけ繰り返す) 
for(var i = begin_row; i <= last_row; i++)
```
i++は省略した形です。
省略しない形は、i = i + 1となります。
つまり、変数iに1づつ足していくという意味になります。

以上の内容を組み合わせて完成したコードを下記に記載したいと思います。

# 完成したコード

```js
//スプレッドシートの内容を取得 
function postContent() { 
//1. 現在のスプレッドシートを取得 
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 
//2. 現在のシートを取得 
var sheet = spreadsheet.getActiveSheet(); 
//最後の行を取得（繰り返し処理の回数） 
var last_row = sheet.getLastRow(); 
//処理を開始する行（１行目は項目のため2行目から開始） 
var begin_row = 2; 
//今日の日付を取得し文字列を成型 
var today = new Date(); 
var formatDate = Utilities.formatDate(today, "JST","yyyy/MM/dd"); 
//繰り返し処理(1行づつ処理し、行の数だけ繰り返す) 
for(var i = begin_row; i <= last_row; i++) { 
//それぞれのセルの中身を取得していく 
//日付 
var sell1 = "A"+i; 
var value1 = sheet.getRange(sell1).getValue(); 
var value1 = Utilities.formatDate(value1, "JST","yyyy/MM/dd"); 
//予定 
var sell2 = "B"+i; 
var value2 = sheet.getRange(sell2).getValue(); 
//準備期間 
var sell3 = "C"+i; var value3 = sheet.getRange(sell3).getValue(); 
//メモ 
var sell4 = "D"+i; var value4 = sheet.getRange(sell4).getValue(); 
//項目名とvalue2-4をまとめて変数で取得 
var value = "\n【予定】" + value2 + "\n【準備期間】" + value3 + "\n【メモ】" + value4; 
//もし、日付と実際の日付が合致した際、LINEを送る 
if(formatDate == value1) { sendPostContent(value); } } } 
//GASからLINE Notifyに通知するメソッド 
function sendPostContent(value) { var token = ['ここにLINE Notifyで発行したアクセストークンを記載']; 
var options = { "method": "post", 
"payload" : {"message": value }, 
"headers": {"Authorization": "Bearer " + token} 
}; 
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options); 
}
```
そして、スプレッドシートを下記のように作成。
自分の予定を入力します。
![スプレッドシート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655322/6e51b05a-d507-37c6-f4cc-13ba07189364.png)

最後にGASの編集からトリガー設定を行います。
そうすることで、下記のように自分が指定した時間にLINEへ通知が届くようになります（今回はLINE Notifyの設定については省略させていただきます）。

![LINE Notify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655322/fd5132b1-20da-775a-f759-cbf3244e35ef.png)

これで大事な予定を忘れずに済みますね。

# LINEだけでなく、Gmailへの送信も可能
LINEだけでなく、Gmailへの送信も当然できます！

```js
//GASからLINE Notifyに通知するメソッド 
function sendPostContent(value) { 
var token = ['ここにLINE Notifyで発行したアクセストークンを記載']; 
var options = { "method": "post", "payload" : {"message": value }, 
"headers": {"Authorization": "Bearer " + token} }; 
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options); 
}
```
上記の内容を下記に変更することでGmailにも送信できるようになります。

```js
function sendPostContent(value) {
  GmailApp.sendEmail("送信先", "内容"); 
}
```
GASは汎用性が非常に高く、Googleのサービスをはじめとして様々なツールと連携することができます。

# 参考
https://www.atmarkit.co.jp/ait/articles/1702/09/news021.html
https://www.atmarkit.co.jp/ait/articles/1702/09/news021_2.html
https://design-remarks.com/gas-spred-mailalert/

# まとめ
いかがだったでしょうか。
私自身、わからないことばかりで調べては考えての繰り返しでなんとか完成までたどり着くことができました。

GASやLINE Notifyは一度扱えるようになると、様々なことにも応用できるためおすすめです。

興味のある方はぜひ、一度チャレンジしてみてください。

最後まで読んでいただき、有り難うございました。 この記事がお役に立てる内容となっていれば嬉しいです。 
質問がありましたら、コメントお待ちしております。