41
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Apps ScriptAdvent Calendar 2014

Day 7

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

Last updated at Posted at 2014-12-07

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をご確認ください。

41
46
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
41
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?