14
10

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フォームで日報フォームを作成して回答したらSlackのチームチャンネルに共有されるようにした

Posted at

はじめに

あけましておめでとうございます。

日報書いてますか?
私の所属するチームには日報の文化はないのですが、日々の振り返りのために自主的に日報を書き始めました。

新人研修の頃にはテキストエディタを開いてマークダウン形式で日報を書いていました。
書き終わったらテキストをコピーしてSlackの新人研修チャンネルにスニペットで貼り付けていました。
これはイケてない。
今日のスケジュールを振り返るためにいちいちカレンダーを開かなくてはいけないし、夕礼の時間までに日報を書かなくてはいけないのに忘れてしまうこともしばしば。書き終わってからいちいちコピペするのも面倒です。

私の理想の日報体験は以下の通りです。

  • 終業時間のちょっと前に日報のリマインダーが欲しい
  • 今日のスケジュールを振り返りながら書きたい
  • 書き終わったらSlackのチームチャンネルに日報を共有したい

これをGoogleフォームとGoogle Apps Scriptの組み合わせで実現できましたので紹介します。
以下、Google Apps ScriptをGASと表記します。

Googleフォームで日報フォームを作成

まずはこんな感じでフォームを作ります。
スクリーンショット 2020-01-01 17.09.10.png

フォームに今日のスケジュールを追加しSlackに回答用URLを送信するGASを書く

GASで新規プロジェクトを作成してスクリプトを書きます。

function main() {
  // GoogleフォームをID指定でオープン
  var form = FormApp.openById('abcd');
  
  // フォームのタイトルに今日の日付を設定
  var today = new Date();
  var year = today.getYear() + '';
  var month = (today.getMonth() + 1)+ '';
  var day = today.getDate() + '';
  var form_desc = year + '' + month + '' + day + '';
  form.setTitle('日報@' + form_desc);
  
  var schedules = getTodayEvents();
  form.setDescription(schedules)
  
  // 回答用のURLをSlackに投稿
  form_url = form.getPublishedUrl();
  postMessage(form_url);
}

function getTodayEvents() {
  // アカウントのデフォルトカレンダーから
  // 00:00~23:59までのイベントを取得
  var now = new Date();
  var today_start = new Date(now.getYear(), now.getMonth(), now.getDate());
  var today_end = new Date(today_start.getTime() + (23 * 60 * 60 * 1000 + 59 * 60 * 1000));
  var events = CalendarApp.getDefaultCalendar().getEvents(today_start, today_end);
  
  var allDayEvents = []
  var notAllDayEvents = []
  var text = '';
  
  // allDayイベントとそうでないイベントをわける
  for (var i = 0; i < events.length; i++) {
    if (events[i].isAllDayEvent()) {
      allDayEvents.push(events[i]);
    } else {
      notAllDayEvents.push(events[i]);
    }
  }
  
  notAllDayEvents.sort(function(left, right) {
    // 開始時間でソートする
    var l_start = left.getStartTime().getHours() * 100 + left.getStartTime().getMinutes();
    var r_start = right.getStartTime().getHours() * 100 + right.getStartTime().getMinutes();
    if (l_start < r_start) return -1;
    if (l_start > r_start) return 1;
    
    // 開始時間が同じなら終了時間でソートする
    var l_end = left.getEndTime().getHours() * 100 + left.getEndTime().getMinutes();
    var r_end = right.getEndTime().getHours() * 100 + right.getEndTime().getMinutes();
    if (l_end < r_end) return -1;
    if (l_end > r_end) return 1;
    return 0;
  });
  
  // allDayイベント
  for (var i = 0; i < allDayEvents.length; i++) {       
    text = text + allDayEvents[i].getTitle() + '\n';
  }
  
  // 日中イベント
  for (var i = 0; i < notAllDayEvents.length; i++) {
    var startTime = notAllDayEvents[i].getStartTime();
    var endTime = notAllDayEvents[i].getEndTime();
    var start = ('00' + startTime.getHours()).slice(-2) + ':' + ('00' + startTime.getMinutes()).slice(-2);
    var end = ('00' + endTime.getHours()).slice(-2) + ':' + ('00' + endTime.getMinutes()).slice(-2);
    text = text + start + '~' + end + ': '+ notAllDayEvents[i].getTitle() + '\n';
  }
  
  return text
}

function postMessage(form_url) {
  
  // incoming webhookのURL
  var url = "https://hooks.slack.com/services/A/AAAAAAAA"

  var block = {
    "type": "section",
    "text": {
      "type": "mrkdwn",
      "text": "日報を書きましょう\n<" + form_url + "|リンク>"
    }
  }
  
  var payload = {
    "text": '日報の時間です',
    "blocks": [block]
  }
  
  // POSTオプション
  var options = {
    "method" : "post",
    "contentType": 'application/json',
    "payload": JSON.stringify(payload),
    "muteHttpExceptions": true
  }
  
  // POSTリクエスト
  var response = UrlFetchApp.fetch(url, options);  
  var responseCode = response.getResponseCode();
}

Slackに投稿するところはincoming webhookでもchat.postMessageでもお好きな方法でどうぞ。

GASを実行すると許可を求められるので内容を確認したうえで許可します。
スクリーンショット 2020-01-01 10.58.53.png

問題なければSlackに回答用フォームのリンクが投稿されます。
スクリーンショット 2020-01-01 16.51.31.png

リンクを開くとフォームが表示されます。
フォームのタイトルには今日の日付が入り、説明欄には今日のスケジュールが表示されていい感じ :thumbsup:
スクリーンショット 2020-01-01 17.11.44.png

Slackにリマインダーを投稿

GASが平日の夕方に実行されるようにトリガーを設定します。
毎週月曜日、毎週火曜日、毎週水曜日、毎週木曜日、毎週金曜日にトリガーを追加します。
もうちょっと柔軟な設定ができるといいんだけどなぁ。

スクリーンショット 2020-01-01 17.44.50.png

フォームに回答すると実行されるGASを書く

フォーム編集画面を開き、右上のボタンを押してスクリプトエディタを選択します。
スクリーンショット 2020-01-01 11.43.22.png

フォーム回答時に実行されるGASを書きます。
Googleフォーム回答時に受け取るイベントオブジェクトについての詳細は↓のGoogle Forms eventsのForm submitをご覧ください。
Event Objects | Apps Script | Google Developers

function main(e) {  
  // フォーム回答時にはEvent Objectを受け取る
  var form_response = e.response;
  
  // Slackに投稿するペイロードを作成
  var payload = build_payload(form_response)
  postMessage(payload);
}

function build_payload(form_response) {
  var payload = {
    'blocks': []
  }
  
  var itemResponses = form_response.getItemResponses();
  
  for (var i = 0; i < itemResponses.length; i++) {
    var itemResponse = itemResponses[i];
    
    var title = itemResponse.getItem().getTitle();
    var response = itemResponse.getResponse();
    
    var block = {
      'type': 'section',
      'text': {
        'type': 'mrkdwn',
        'text': '*' + title + '*' + '\n' + response
       }
    };
    payload.blocks.push(block);
  }
    
  return payload
}

function postMessage(payload) {
  
  // incoming webhookのURL
  var url = "https://hooks.slack.com/services/A/AAAAAAAA"

  // POSTオプション
  var options = {
    "method" : "post",
    "contentType": 'application/json',
    "payload": JSON.stringify(payload),
    "muteHttpExceptions": true
  }
  
  // POSTリクエスト
  var response = UrlFetchApp.fetch(url, options);  
  var responseCode = response.getResponseCode();
}

回答されるとスクリプトが実行されるようにトリガーを設定します。
赤枠のなかがポイントです。
スクリーンショット 2020-01-01 16.21.45.png

デモ

Slackに送られてきたURLを開いてフォームに回答します。
スクリーンショット 2020-01-01 16.23.12.png

送信ボタンを押すとSlackに回答が投稿されます。
スクリーンショット 2020-01-01 16.24.00.png

うまくいきました。

参考

Google Developers

Class FormApp | Apps Script | Google Developers
Event Objects | Apps Script | Google Developers
Class UrlFetchApp | Apps Script | Google Developers

Slack

Slack でのIncoming Webhook の利用 | Slack
chat.postMessage method | Slack

14
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
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?