#背景
サークルの活動をなるべく多くの人が来られる日に行いたいので,毎週日程調整を行う.
LINEスケジュールや調整さん,ノートにスタンプ押してもらうなどのやり方だと,毎週手動で作るのが面倒.
そこで,スプレッドシートのチェックボックスで出欠を取り,そのリンクを自動で通知するようにした.
#作ったもの
- Google Spreadsheet+GAS+LINE Notifyを利用
- ユーザは日~土までのチェックボックスにチェックを付ける
- チェックが一番多い曜日をハイライトする
- LINEグループに毎週自動でリンクを通知する(このときチェックをすべて外す)
#実装
Spreadsheetの共有リンクを取得し(「リンクを知っている全員が編集可」を選択),それをLINE Notifyで通知します.GASからLINE Notifyを利用する方法は以下の記事を参考にしてください.
- [Google Apps ScriptからLINE NotifyでLINEにメッセージを送る]
(https://qiita.com/tadaken3/items/5f916a12587e42ece814)
以下のようにGASのトリガーを設定します.毎週決まった時間帯にnotifyが実行されてLINEグループに通知を送り,ユーザがチェックを付けたり消したりするとonEditが呼ばれてチェックが最も多い行をハイライトします.
var spreadsheet,
sheet,
lastRow,
lastColumn,
dataRange, //全チェックボックスのセル範囲
checkboxes, //全チェックボックスの状態を格納する2次元配列
daysNum = 6; //選択できる曜日の数
//LINEグループにスプレッドシートのリンクを通知する
function notify(){
clearCheckBox(); //チェックボックスを初期化
var message = "https://docs.google.com/spreadsheets/d/...", //Spreadsheetのリンク
url = "https://notify-api.line.me/api/notify",
token = "hoge", //LineNotifyから取得したトークン
options = {
"method" : "post",
"payload" : "message= " + message,
"headers" : {"Authorization" : "Bearer " + token}
};
UrlFetchApp.fetch(url,options);
}
//各オブジェクトを取得
function initialize(){
spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
sheet = spreadsheet.getActiveSheet();
lastRow = sheet.getLastRow();
lastColumn = sheet.getLastColumn();
dataRange = sheet.getRange(2, 2, lastRow - 1, lastColumn - 1); //チェックボックスのセル範囲を取得
checkboxes = dataRange.getValues(); //全チェックボックスの状態を2次元配列として取得
}
//シートが編集されたら,最もチェックの多い曜日(複数可)の列をハイライトする
function onEdit(e){
var checkCount = Array.apply(null, Array(daysNum)).map(function() {return 0}); //各曜日のチェック数(0で初期化)
var maxCheckNum = 0; //最多のチェック数
var candidates = []; //候補日(参加者が最多の曜日)
initialize();
//日曜から順に各曜日のチェックを数える
for(var day = 0; day < daysNum; day++){
for(var member = 0; member < lastRow - 1; member++) {
if(checkboxes[member][day] === true)
checkCount[day]++;
}
if(checkCount[day] < maxCheckNum) continue;
if(checkCount[day] > maxCheckNum) candidates = []; //最多チェック数を更新したらそれまでの候補日を削除
candidates.push(day); //候補日に追加
maxCheckNum = checkCount[day];
}
//候補日をハイライトする
dataRange.setBackground("#FFFFFF"); //ハイライトを初期化
if(maxCheckNum === 0) return; //チェックが1つもなければハイライトしない
candidates.forEach(function(candidate){
sheet.getRange(2, 2 + candidate, lastRow - 1, 1).setBackground("#B9D8A5");
});
}
//チェックボックスのチェックをすべて外す
function clearCheckBox(){
initialize();
for(var day = 0; day < daysNum; day++){
for(var member = 0; member < lastRow - 1; member++) {
checkboxes[member][day] = false;
}
}
dataRange.setBackground("#FFFFFF"); //ハイライトを初期化
dataRange.setValues(checkboxes);
}
#ポイント
getRange()では行・列が0ではなく1から始まります.
また,getRange()で取得したデータをループで何度も参照すると遅いので,2次元配列に格納しておきます.
#まとめ
GASによる自動化に憧れて,初めて書いてみました.車輪の再発明感は多分にありますが,実際に利用した感じでは,自作なので既存のサービスよりかゆいところに手が届いて便利だと思います.他のメンバーも特に抵抗なく使えているようです.
GASもJSも初めてなので,もっと簡潔な書き方があれば教えていただきたいです.