
【GAS活用術⑤-1】前日にGoogleフォームから登録された件数をLINEで通知
Google Apps Script (GAS)を、もっと身近に、日々の暮らしに。
前々回の【GAS活用術④-1】、前回の【GAS活用術④-2】では、Googleフォームから送信される度に、内容をLINEで通知する方法をご紹介しました。
送信される度にLINE通知するのは便利ですが、すべてのGoogleフォームに適しているわけではありません。Googleフォームから送信される頻度が高いと、当然、通知が多すぎる!という問題が発生します。
例えば、PTAや学校関係のGoogleフォームに保護者が入力するような場合、生徒の人数分となかなかの大量データが登録されることになりますよね。
また、管理者側として通知して欲しいのは、リアルタイムに「誰がどんな回答をしたか」ではなくて、「一日に合計で何件登録があったか」だけ、という場合があると思います。
そこで今回は、前日にGoogleフォームから登録された件数をLINEで通知する方法についてご紹介していきます。
スプレッドシート側にGASを設定
前々回の【GAS活用術④-1】、前回の【GAS活用術④-2】では、Googleフォームから送信されるタイミングで通知をしていたため、Googleフォーム側にGASを設定しました。
今回は、蓄積された回答データを元に件数を通知するので、スプレッドシート側にGASを設定していきましょう。
Googleフォームを作成後、スプレッドシートを連携すると、A列に「タイムスタンプ」の列が自動作成され、フォームから回答した日時が設定されますよね。

今回はこのA列のタイムスタンプの値が昨日の日付のデータを抽出し、その件数をLINEに通知していきましょう。
では、さっそく下記のスクリプトをコピーします。
function notifyCount(){
//指定のシート上のデータがある範囲の表示値を表形式(正しくは二次元配列)ですべて取得
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; //一番左のシートを取得
const table = sheet.getDataRange().getDisplayValues().slice(1); //ヘッダー行を除く
//昨日の日付を取得
const date = new Date(); //現在時刻を取得
date.setDate(date.getDate() -1); //昨日の日付に変更( 2日前なら-2に変更)
const yesterday = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd'); //日付書式を設定
//「A列の値の0文字目から10文字分(yyyy/MM/dd)が昨日の日付と同じもの」を条件にフィルターをかける
const regs = table.filter(row => row[0].slice(0,10) == yesterday);
//msgHeaderに二次元配列のlength(行数)= 登録件数をセットする
const msgHeader = "\n昨日、" + yesterday + "の登録数は" + regs.length + "件でした"
+ "\n現在の登録総件数は"+ table.length + "件です";
console.log(msgHeader);
const token = "★トークンをここに設定★"; //トークンを設定
//sendLine(msgHeader, token); //sendLine関数でmsgHeaderをtoken宛にLINE通知
}
function sendLine(msg,token){
let options = {
"method": "post",
"Content-Type" : "application/x-www-form-urlencoded",
"payload": "message=" + msg,
"headers":{"Authorization" : "Bearer " + token}
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}
スプレッドシートのメニューバーから、拡張機能 > Apps Script を選択しスクリプトエディタを起動します。

スクリプトエディタを初めて起動した場合は、コード.gsファイルに、「function myFunction() { }」が書かれていると思います。初めから記載されている「function myFunction ( ) { }」の部分を消して、上記のコードをペーストします。
既にGASを登録済みの方は、登録済みのスクリプトを消さないように一番上に上記のコードをペーストします。
これまでの【GAS活用術】のスクリプトを登録済みの方で、2つ目の関数定義、function sendLineがある場合は、1つ目のfunction notifyCountのみを追加するだけで大丈夫です。
ペーストが終わったら、以下の二点を確認してください。
対象のシートが一番左側にあること。
フォームと連携してスプレッドシートを作成した場合は、シートが複数あっても一番左のシートがフォームと連携しているケースがほとんどだと思います。

シートのA列にタイムスタンプ列があること。
これもさきほどもいったように、Googleフォームを作成してスプレッドシートを連携すると、A列に「タイムスタンプ」の列が自動作成されていると思います。

この二つをクリアしていれば、この時点でのスクリプト修正は不要です。修正が必要な場合、上の画像のキャプションを参考に変更してみましょう。
まだ名前を付けていない場合は、「無題のプロジェクト」をクリックして、プロジェクト名に変更しておきます。そして、ツールバーの保存アイコンで保存します。

スクリプトエディタから実行する
では、さっそくNotifyCount関数を実行してみましょう。スクリプトエディタのツールバーに、NotifyCount関数が表示されていることを確認したら、実行ボタンをクリックします。

はじめてそのプロジェクトを実行しようとした場合は、「承認が必要です」と言われます。その場合は、【GAS活用①-3】のページを参考にして「実行権限の承認」を行ってください。その後、再度、実行ボタンをクリックしてみましょう。
既にプロジェクトを実行済みの方は、「承認が必要です」とは言われずに、すぐにログが表示されると思います。
スクリプトの下部に、下記のようなログが表示されるか確認をしてみてください。

昨日の登録数が0件と表示された場合は、対象の昨日のデータが存在しなかったようなので、次のどちらかの方法で登録数がカウントされるようにしてみてください。
シート側に、テストデータとして昨日の日付のデータを新しく作るか、もしくは、既存のデータのタイムスタンプ列の日付を昨日に変更する
スクリプト側で、一時的に、以下の部分の-1の値を変更してみる(2日前なら-2に変更、3日前なら-3に変更)
date.setDate(date.getDate() -1); //昨日の日付に変更( 2日前なら-2に変更)
上記の方法を使って、昨日もしくは数日前の登録件数がカウントされるか、いくつかのパターンを試してみましょう。
LINE通知するようにスクリプトを修正する
それでは、ログで正しく昨日の登録数と登録総件数が取得できていることが確認できたら、これをLINEで通知するようにスクリプトを変更します。
以前同様、修正する箇所は以下の2行だけです。
const token = "★トークンをここに設定★"; //トークンを設定
//sendLine(msgHeader, token); //sendLine関数でmsgHeaderをtoken宛にLINE通知
トークンの設定
" "で囲まれた中(★~★)を上書きするように、LINE通知の送り先のトークンをペーストします。既に登録済みの既存のトークンがあれば、それでも大丈夫です。
トークンを取得していない方は、【GAS活用術①-2】LINEグループへリマインド通知を自動送信・その2を参考に、通知を送りたいLINEグループ、または自分自身に通知するためのトークンを取得してください。
注:トークンは文字列になるので、両端を "(ダブルクォーテーション)で囲む必要があります。" "は消さないようにしてください。
sendLineの前についている // を消す
sendLine関数をコールすることで実際にLINEに通知しますが、例によって「まずログで確認し、それからLINE通知」の手順を踏んで進めていくため、sendLine関数のコールをコメントアウトしてあります。
// を消して、sendLine関数をコールし、LINEが通知されるようにします。

これでスクリプトの修正は完了です。スクリプトは自動保存ではないので、ツールバーの保存ボタンでプロジェクトを保存するのを忘れないようにしましょう。

では、さっそくLINE通知を送るように修正した、NotifyCount関数を再度実行してみましょう。

LINE通知が届いたか、確認します。

もし、LINE通知の[ ]の中のトークン名を変更したい場合は、新規トークンを取得して、そのトークンをスクリプトに貼りつけてください。
また、今回は昨日の登録件数が0件でもLINE通知をするようなスクリプトの記述にしています。もし、昨日の登録件数が0件なら、ログを出力し、0件以外ならLINE通知する、という風にしたいなら、以下のようにif文を使った記述に変更してみてください。
if (regs.length == 0){
console.log(msgHeader); //msgHeaderをログに出力
}else{
const token = "★トークンをここに設定★"; //トークンを設定
sendLine(msgHeader, token); //sendLine関数でmsgHeaderをtoken宛にLINE通知
}
トリガーを設定する
最後に、NotifyCount関数を毎日自動的に実行されるようにトリガーを設定していきましょう。スクリプトエディタの画面左端のメニューバーで「トリガー」を選択します。

「トリガーを追加」をクリックします。

トリガーを追加の画面で、「実行する関数の選択」でNotifyCount、「イベントのソースを選択」で時間主導型、「時間ベースのトリガーのタイプ」で日付ベースのタイマーを選択すると、毎日、1時間単位でどの時間帯に実行するのか選択できます。

時刻は、前日の登録数ということなので、日付が変わってすぐの「午前0時~1時」も選択できますが、その時間のLINE通知が気になるのであれば、朝の時間帯でしょうか。
「時刻の選択」は、ご事情とお好みにより、設定していただければ。
最後にトリガーの保存をすれば、毎日、同じ時間帯に、昨日の登録件数がLINE通知されるようになります。GASはほぼコピペでしたし、思った以上に簡単にできたのではないでしょうか。
コード解説
さて、最後に、改めてコード解説をしていきたいと思います。
filterメソッドでギュッと絞り込んだ配列を生成する
notifyCount関数の前半の処理、シート上にデータが存在する範囲(Range)をgetDataRangeでガツッと取得して、そのまま二次元配列として読み込んでいるところは、【GAS活用術①-7】と同じです。
また、A列の日付の値を文字型として取得するために、getValuesメソッドではなく、表示上の値を取得する、getDisplayValuesメソッドを使用している点も一緒です。
ただ、今回は件数をカウントするので、slice(1)をつけて、ヘッダー行(見出し行)を除いた、データ行のみを二次元配列にしています。
そして、今回は、notifyCount関数の中間あたりで、filterメソッドを使っています。
filterメソッドは、「条件に該当する要素を抽出する」、「配列の各要素を条件判定して、新しい配列を生成する」などと固い表現で説明されたりしますが、簡単にいうと、条件にあった、欲しいデータだけにギュッと絞り込んでくれる、ということです。
イメージはこんな感じです。

今、欲しいデータは、「昨日、フォームから送信されたデータ」、つまり「タイムスタンプ列(A列)に昨日の日付が設定されている行」なので、それを条件にfilterメソッドをこのように記述しています。

スプレッドシート側でフィルターをかけた時と同じような動作を、二次元配列側に対して行っている、ということです。スプレッドシートでフィルターをかける場合は、以下のような手順となります。




例えば、NotifyCount関数のログに、「昨日の登録数は5件でした」と表示されて、本当かいな?とスプレッドシート側で確認する場合は、このフィルター機能が使えそうですね。
登録件数(行数)は「二次元配列名.length」で取得
さて、filterメソッドでギュッと絞り込んで、昨日回答されたデータのみの二次元配列:regsができました。ここまで来たら、今回の目的、「昨日回答された件数」を確認するのは簡単です。
二次元配列の行数は、配列名.lengthで取得できます。
lengthプロパティは「要素の数」とか「配列の長さ」を返します、という説明がされたりしますが、二次元配列の場合、lengthプロパティは「行数」を返してくれる、と考えると理解しやすいと思います。
二次元配列をマンションにたとえるなら、何階まであるか?をlengthプロパティが教えてくれるということです。
二次元配列の行数の取得は
二次元配列名.length
例) 二次元配列名:tableの行数は、table.length で取得できる
ちなみに、配列のインデックス番号は0から始まりますが、lengthプロパティは1行なら1を返します。行のインデックス番号の最大値+1を返してくれる、ということですね。

今回の例では、配列名:tableにシートの全データが、配列名:regsに昨日、回答されたデータが入っているので
table.length でシートに登録されているヘッダー行を除く件数(行数)
→上図の場合、126が戻されるregs.length で昨日の回答件数(行数)
→上図の場合、5が戻される
ことになります。これらの件数をメッセージの中に組み込んでいるわけです。
//msgHeaderに二次元配列のlength(行数)= 登録件数をセットする
const msgHeader = "\n昨日、" + yesterday + "の登録数は" + regs.length + "件でした"
+ "\n現在の登録総件数は"+ table.length + "件です
終わりに
最後にコード解説があって、少し長くなってしまいましたが、いかがだったでしょうか。
今回は件数だけでしたが、次回はその日(当日)に登録された内容をまとめてLINE通知する方法をご紹介していきたいと思います。
今回、件数だけ調べるのにわざわざfilterメソッドを使うの?と疑問に思われた方もいらっしゃるかもしれませんが、次回もfilterメソッドを使うので、その前振りとでも思ってください。
次回作成する関数の前半部分は、今回の前半部分とほぼ同じになりますよ。