LoginSignup
6
10

More than 5 years have passed since last update.

SpreadsheetとLINE Notifyで日程調整

Last updated at Posted at 2018-11-06

背景

サークルの活動をなるべく多くの人が来られる日に行いたいので,毎週日程調整を行う.
LINEスケジュールや調整さん,ノートにスタンプ押してもらうなどのやり方だと,毎週手動で作るのが面倒.
そこで,スプレッドシートのチェックボックスで出欠を取り,そのリンクを自動で通知するようにした.

作ったもの

  • Google Spreadsheet+GAS+LINE Notifyを利用
  • ユーザは日~土までのチェックボックスにチェックを付ける
  • チェックが一番多い曜日をハイライトする
  • LINEグループに毎週自動でリンクを通知する(このときチェックをすべて外す)


※木曜がないのはサークルの都合です

実装

Spreadsheetの共有リンクを取得し(「リンクを知っている全員が編集可」を選択),それをLINE Notifyで通知します.GASからLINE Notifyを利用する方法は以下の記事を参考にしてください.

以下のようにGASのトリガーを設定します.毎週決まった時間帯にnotifyが実行されてLINEグループに通知を送り,ユーザがチェックを付けたり消したりするとonEditが呼ばれてチェックが最も多い行をハイライトします.
5.PNG

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も初めてなので,もっと簡潔な書き方があれば教えていただきたいです.

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10