Help us understand the problem. What is going on with this article?

スプレッドシートで作ったtodoリストでステータスを変更するとslackに流す

More than 5 years have passed since last update.

Google Apps Script Advent Calendar 2014の7日目の記事になります。よろしくお願いします。

2日目の方のslackバージョンに近いかと思います。既出でしたら大変恐縮です、、。

画面小さいですが、通知される様子は、こんな感じになります。

todoToSlack.gif
※ ↑これgifなんですが、動いてない場合はこちらから...

slackに流れる内容は、例えばこんな感じです。
Screen Shot 2014-12-06 at 16.48.15.png

では、下記にとりあえず動くものを作る手順を書いて、その後に簡単に補足したいと思います。

slack側の設定

todo用のチャンネルを作成

  • slackの左側CHANNELSの下の方にある、Create a channel... からチャンネルを作成

incoming hookの設定

  • https://yourslackdomainname.slack.com/services/new#diy から Incoming WebHooksのaddを選択
  • postしたいチャンネル(さっき作ったtodo)を選択して、Add Incoming WebHooks Integrationを選択
  • 下記のようなURLがでてくるのでこれをコピっておく

Screen Shot 2014-12-06 at 16.06.34.png

google apps側の設定

スプレッドシートの用意

  • 下記の感じで用意(列の範囲:B列~I列、todo開始行:3行目)

Screen Shot 2014-12-06 at 16.08.28.png

gasの編集

  • ツール > スクリプトエディタを選択し新規に.gsファイルを作成
  • プロジェクト名、ファイル名を適当に入力
  • 下記のコードをコピペ
  • 1行目に、さっきslack側でコピっておいた、incoming hookのpost用urlをペースト
todo.gs
var postUrl = "https://hooks.slack.com/services/xxxxxxx/xxxxxxx/xxxxxx";
var postChannel = "#todo";

function myOnEdit()
{
  var keywordCol = 8;         // ステータス列idx
  var inChargePersonCol = 7;  // 担当者列idx
  var dataStartCol = 2;       // データが開始する列のidx
  var taskContentCol = 2;     // タスク内容列idx

  var colOffset = 1;  // A列はoffset

  var dataColNum = 8;  // データの列数
  var range = SpreadsheetApp.getActiveRange();
  var rowidx = range.getRow();
  var colidx = range.getColumn();
  if(colidx != keywordCol){ return ; }
  var sheet = SpreadsheetApp.getActiveSheet();

  // ステータスに変更のあったtodo1行
  var aLine = sheet.getRange(rowidx, dataStartCol, 1, dataColNum);
  if(!aLine){
    return;
  }

  // ステータスセルの値
  var status = aLine.getCell(1,keywordCol-colOffset).getValue();

  // 担当者セルの値
  var username = aLine.getCell(1, inChargePersonCol-colOffset).getValue();
  if(!username){
    username = "unknown";
  }

  // タスクの内容
  var taskContent = aLine.getCell(1, taskContentCol-colOffset).getValue();  
  if(!taskContent){
    return;
  }

  // ステータスを変更した人の名前(googleのアカウント名) 
  // todo: めんどくさそうなので一旦なしで
  // var editor = Session.getActiveUser().

  var message = username;
  message += "さんが、タスク「";
  message += taskContent;  
  message += "」のステータスを";

  if( status == '完了' ){
    aLine.setBackgroundColor("#efefef");
    aLine.setFontColor('black');
    message += "【完了】";

  }
  else if(status == '未着手' || !status){
    aLine.setBackgroundColor('white');
    message += "【未着手】";
  }
  else if(status == '進行中'){
    aLine.setBackgroundColor('#fce5cd');
    message += "【進行中】";
  }

  message += "にしました";

  sendHttpPost(message, "TODOテスト");
}

function test()
{
  sendHttpPost("上様が、タスク「ほげほげほげ」のステータスを【進行中】にしました", "TODOテスト");
}

function sendHttpPost(message, username)
{
  var jsonData =
  {
     "channel" : postChannel,
     "username" : username,
     "text" : message
  };
  var payload = JSON.stringify(jsonData);
  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };

  UrlFetchApp.fetch(postUrl, options);
}
  • スクリプトを動かすために承認(下記参照)が必要なので、まずはtest()を動かして、続行 > 承認 を選択

Screen Shot 2014-12-06 at 15.25.28.png

  • test()がうまく動いたら、gasのエディタメニューのリソース > 現在のプロジェクトのトリガーから、下記のように設定して保存(既にonEditが入っている場合は一旦トリガーを消して新たに追加)

Screen Shot 2014-12-10 at 15.51.24.png

以上。これでうごくはず!

解説と補足

Simple Triggers

gasには、Simple Triggersというイベントハンドラがあります。今回使ったのは、onEditです。スプレッドシートの値を編集すると、呼ばれるます。なので、値を編集するごとに、slackに通知を飛ばす処理はここに入れたいわけです。

ですが、上記公式ドキュメントのRestrictionsの部分で

They cannot access services that require authorization. For example, a simple trigger cannot send an email because the Gmail service requires authorization, but a simple trigger can translate a phrase with the Language service, which is anonymous.

とあるように、gmaiとか外部接続サービスとかは実行できないようになっています。なので、ちょっとstackoverflowの方のwork aroundを参考に回避しています(できない場合はお知らせください)。

実行権限の承認

ga側の設定の途中で、test()を実行して、実行権限の承認を行っています。これをしないと恐らく動きません。自動的に承認する方法もあったかもしれませんが、これが手っ取り早かったので大抵これでやってます。

slackに吐き出すテキストのカスタマイズ

  var jsonData =
  {
     "channel" : postChannel,
     "username" : username,
     "text" : message
  };

ここでやってます。ここでusernameとかchannnelを任意に変えれば吐かれる内容も変わります。また、もっとカスタマイズしたい場合は、https://yourslackdomain.slack.com/services のIncoming WebHooksから先ほど作成した、incoming hookの設定ができます。アイコンとか、デフォのusernameとか、デフォのチャンネルとか設定できます。また、上記のjsonDataの内容をカスタマイズしたい場合は、Configured Integrationsとか、Message Attachmentsとかをみると参考になるかと思います。

Screen Shot 2014-12-06 at 17.05.30.png

以上、簡単でしたが、Google Apps Script Advent Calendar 2014の7日目の記事でした。


[訂正1]

Simple TriggersでonEdit()が呼ばれるように設定していますが、一定時間たつと自動的に外れてしまうようです。ですので、Simple Triggerで、myOnEdit()を呼ぶようにしました。また、myOnEdit()の引数と中身を少し編集しました。

[訂正2]

既にonEditが入っている場合は一旦トリガーを消して新たに追加

と書きましたが、そうすると他のプロジェクトのトリガーのonEditを消すことになってしまうので、、現在のプロジェクトのトリガーに新たに追加する形になります、大変失礼しました。

[訂正3]

if(colidx != keywordCol){ return ; }

myOnEdit()に、上記1行を追加しました。これでステータス以外のセルを編集するごとに通知が飛んでいたのが修正されます。

変更の差分は、revisionsをご確認ください。

mito_log
ベトナム・ハノイ拠点の個人デベロッパ。東南アジア向けに素敵なサービスと文化を作るべく模索中。ベトナムで1年半農業。newbie skateboarder、ハノイITもくもく会毎週土曜朝9時頃 → https://bit.ly/2Oe9Ehk
http://mitolab.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした