LoginSignup
1
3

More than 5 years have passed since last update.

Google Apps Scriptでスプレットシートで管理しているタスクをslackにリマインドしてくれるbotを作ってみた

Last updated at Posted at 2018-04-18

Google Apps Scriptでスプレレットシートのタスクをslackにリマインドしてくれるbotを作ってみた

背景

  • スプレットシートのチームのタスクを管理していたのだが、タスクの期限切れが多く、タスク自体を失念しているケースが多かったため、出社時と退社時にリマンドしてくれるボットを作った。

結果

  • タスク確認のMTGがなくなった。
  • 期限切れは無くならなかったが、タスク遅延期間が長くても1日遅れくらいに収まった
  • タスクの内容も記載しているため、マネージャーとのコミュニケーションがいい意味で減った。(状況把握に時間がかからない。)

コード

タスク管理しているスプレットシートによって、少々修正を加えなければならないです。ご注意ください。

// トリガーする時間を設定
var postTimes = [
  [9, 45],
  [18, 30]  
];

(function(global){
  var Slack = (function() {

    function Slack(options){
      var options = options || {};
      this.url = options.url || "https://slack.com/api/chat.postMessage";
      this.token = options.token || UserProperties.getProperty('SlackAccessToken');
      this.channel = options.channel || "#" + UserProperties.getProperty('PostedChannelName');
      this.username = options.username || UserProperties.getProperty('SlackBotName');  // ボットの名前 (デフォルト値を設定)
      this.icon_emoji = options.icon_emoji || UserProperties.getProperty('SlackBotIcon');  // ボットのアイコン画像を指定 (デフォルト値を設定)
    }

    Slack.prototype.send =  function(text) {
      var self = this;
      UrlFetchApp.fetch(self.url, {
        "method" : "POST",
        "payload" : {
          token: self.token,
          channel: self.channel,
          username: self.username,
          icon_emoji: self.icon_emoji,
          text: text
        }
      });
    };

    return Slack;
  })();

  global.Slack = Slack;
})(this);

// triggerTimesに設定された全ての時間のトリガーを設定
function setTrigger() {
  var triggerDay = new Date();
  for(var i = 0; i < postTimes.length; i++) {
    triggerDay.setHours(postTimes[i][0], postTimes[i][1]);
    ScriptApp.newTrigger("main").timeBased().at(triggerDay).create();
  }
}

// その日のトリガーを削除する関数(消さないと残る)
function deleteTrigger() {
  var triggers = ScriptApp.getProjectTriggers();
  for(var i=0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == "main") {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

function isJapaneseHoliday(date) {
  var startDate = new Date(date.getTime());
  var endDate = new Date(date.getTime());
  startDate.setHours(0, 0, 0, 0);
  endDate.setHours(23, 59, 59, 999);

  var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
  var holidays = cal.getEvents(startDate, endDate);

  return holidays.length != 0;
}

function isHoliday(date) {
  return date.getDay() == 0 // 日曜かどうか
    || date.getDay() == 6 // 土曜かどうか
    || isJapaneseHoliday(date); // 日本の祝日かどうか
}

function getMsgBody(data) {
  var line = "------------------------------------------\n";
  var msg = line + ":sunny:*本日期限のアクション一覧は以下の通りです。*:sunny:\n";

  if (data.today.length != 0) { // 今日のアクションがある場合
    msg += (data.today.join("\n"));
  } else { // 今日のアクションがない場合
    msg += ":tada: なし :tada:\n";
  }

  if (data.past.length != 0) {
    msg += (

      "\n\n\n\n:zap::smiling_imp:*期限切れのアクション一覧は以下の通りです。*:smiling_imp::zap:\n" +
      data.past.join("\n")
    );
  } else { // 今日のアクションがない場合


    msg += "\n\n\n\n:zap::smiling_imp:*期限切れのアクション一覧は以下の通りです。*:smiling_imp::zap:\n" 
       + "\n" + ":tada::tada::tada: なし :tada::tada::tada:\n";
  }

  msg += line;
  return msg;
}

function main() {  
  // 土日祝日はこの先の処理を行わない
  var today = new Date();
  today.setHours(0, 0, 0, 0);
  if (isHoliday(today)) return;

  // ここからの列を定義する変数は、各自調整が必要になります。
  var spreadsheetId = UserProperties.getProperty('SpreadsheetId');
  var sheetName = UserProperties.getProperty('SheetName');
  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
  var lastRowIndex = sheet.getLastRow(); // データが入力されている最終行の行番号を取得
  var dateColumnIndex = 22;              // 「期限」カラムの列番号
  var clientColumnIndex = 2;             // 「顧客正式名称」カラムの列番号
  var siteColumnIndex = 3;               // 「サイト名称」カラムの列番号
  var managerColumnIndex = 7;            // 「担当者」カラムの列番号
  var actionColumnIndex = 21;            // 「ネクストアクション」カラムの列番号
  var mentionColumnIndex = 56;            // 「メンションアクション」カラムの列番号
  var data = { today: [], past: [] };    // slackに送信するメッセージを保持

  for(rowIndex = 1; rowIndex <= lastRowIndex; rowIndex++) {
    var displayedDate = sheet.getRange(rowIndex, dateColumnIndex).getDisplayValue();

    // セルの値が日付のフォーマット(xxxx/xx/xx)かどうか
    if(!/\d{4}\/\d{2}\/\d{2}/.test(displayedDate)) continue;

    var parsedDate = new Date(displayedDate);
    if (parsedDate.getTime() <= today.getTime()) { // 期限が今日以前の場合
      var clientName = sheet.getRange(rowIndex, clientColumnIndex).getDisplayValue();
      var siteName = sheet.getRange(rowIndex, siteColumnIndex).getDisplayValue();
      var managerName = sheet.getRange(rowIndex, managerColumnIndex).getDisplayValue();
      var action = sheet.getRange(rowIndex, actionColumnIndex).getDisplayValue();
      var mention = sheet.getRange(rowIndex, mentionColumnIndex).getDisplayValue();
      var item = "
                 + "クライアント名" + clientName + "\n"
                 + "サイト名" + siteName + "\n"
                 + "担当者" + managerName + "( " + mention + " )" + "\n"
                 + "アクション内容:\n" + action + "\n"
                 + "\n";"

      var type = parsedDate.getTime() == today.getTime() ? 'today' : 'past';
      data[type].push(item);
    }
  }

  var slack = new Slack();
  var msg = getMsgBody(data);
  slack.send(msg);
}
1
3
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
1
3