esaの日報の提出状況をGASで可視化した話

こんにちは、CTOの@hiro_yです。

イノベーター・ジャパンではドキュメントの共有にesaを使っていて、メンバーの皆には日報を毎日書いてもらっています。最近では新しいメンバーの書く日報が文章としてとても凝っていて、読み応えがあって楽しいです。

しかし日報の常、どうしても書くのを忘れてしまったり、面倒になってしまったりします。イノベーター・ジャパンでは時間や場所にとらわれない働き方ができることもあり、日々の成果・進捗を共有することは大切なことです。また、いわゆる所感にあたる部分、何を感じ、何を考えてお仕事しているかの共有もとても大事です。

何より、日報を書かない人を放置してしまうと、きちんと書いている人が損している気分になってしまうのが一番の問題です。なので誰が書いていないのか把握できるようにしたい。できれば、評価の材料としても使いたい。

そこでesaにはAPIが用意されているのを利用し、日報の提出一覧をGoogle Spreadsheetに表示できるようにしてみました。ゴールは「設定」シートで年月を指定して「読込」ボタンを押すと、「結果」シートにメンバーのリストと日報を書いた日がわかりやすく表示されることです。

Google SpreadsheetなのでGAS(Gooogle Apps Script)を使って書きました。以下、コードです(あまり考えずに書いたので雑で失礼)。日報は「日報/YYYY/MM/DD」というカテゴリーに投稿されていることを前提としています。また、WIP(書き途中)のものは対象に含めていません。

var ACCESS_TOKEN = 'your access token';
var TEAM_NAME = 'your team name';

function _getTargetValue() {
  if (_getTargetValue.value) {
    return _getTargetValue.value;
  }
  var configSheet = SpreadsheetApp.getActive().getSheetByName('設定');
  _getTargetValue.value = configSheet.getRange('B1').getValue();
  return _getTargetValue.value;
}

function _getYearMonthString() {
  var date = new Date(_getTargetValue());
  var month = date.getMonth() + 1;
  if (month < 10) {
    month = '0' + month;
  }
  return date.getFullYear() + '/' + month;
}

function _getLastDay() {
  var date = new Date(_getTargetValue());
  date.setDate(1);
  date.setMonth(date.getMonth() + 1);
  date.setDate(0);
  return date.getDate();
}

function _getData(page, perPage) {
  // esa posts API
  var url = 'https://api.esa.io/v1/teams/' + TEAM_NAME + '/posts'
    + '?access_token=' + ACCESS_TOKEN
    + '&q=' + encodeURIComponent('wip:false in:日報/' + _getYearMonthString())
    + '&page=' + page
    + '&per_page=' + perPage;
  
  var response = UrlFetchApp.fetch(url);
  if (response.getResponseCode() >= 400) {
    // エラー
    Logger.log('Error: status = ' + response.getResponseCode());
  }

  return JSON.parse(response.getContentText());
}

function _mergeData(data, collection) {
  if (data.posts) {
    data.posts.forEach(function(post) {
      // カテゴリー末尾から日付取得
      var day = post.category.split('/').pop();
      day = parseInt(day, 10);
      var screenName = post.created_by.screen_name;
      if (screenName in collection) {
        collection[screenName].push(day);
      } else {
        collection[screenName] = [day];
      }
    });
  }
}

function execute() {
  // データクリア
  var resultSheet = SpreadsheetApp.getActive().getSheetByName('結果');
  resultSheet.clearContents();

  // 日報データ取得
  var collection = {};
  for (var page = 1;; page++) {
    var data = _getData(page, 50);
    _mergeData(data, collection);
    if (data.next_page === null) {
      // 次のページがないので終わり
      break;
    }
  }
  
  // 対象年月と日付書き込み
  resultSheet.getRange(1, 1).setValue(_getYearMonthString());
  for (var day = 1, lastDay = _getLastDay(); day <= lastDay; day++) {
    resultSheet.getRange(1, 1 + day).setValue(day);
  }

  // データ書き込み
  var row = 2;
  var memberNames = Object.keys(collection).sort();
  memberNames.forEach(function(memberName) {
    resultSheet.getRange(row, 1).setValue(memberName);
    collection[memberName].forEach(function(day) {
      resultSheet.getRange(row, 1 + day).setValue('○');
    });
    row++;
  });
}

このスクリプトを登録して、execute関数を実行できるようにすれば「設定」シートの「B1」に入力されている日付の年月の日報の提出状況が、「結果」シートに次のように表示されます(適宜セルの書式など設定しています)。

f:id:hiro_y:20180220120334p:plain

あとは必要な(確認したい)タイミングでスクリプトを実行して、日報を書いていない人に声をかけたり、そもそも日報を書く意味について話したりする機会を増やしたり、評価の材料にしたりすればよさそうです。

スクリプトの実行をスクリプトエディタからするのも面倒なので、定期実行してもかまいません。今回は「設定」シートに「読込」ボタンを置いて、押したら実行されるようにしてみました。Excelと同じようなイメージでボタンを配置しようとしたのですが、Google Spreadsheetには「ボタン」というパーツがないのですね…。

仕方がないので、「挿入」から「図形描画」を開き、「図形」で使えそうなものを探して置いてみたのですが、とてもクラシカルな見た目のボタンになりました(ベベル(面取り)を使ってみました)。目的は達することができたのですが、もうちょっと格好いいボタンのパーツがほしいところです。

f:id:hiro_y:20180220121444p:plain

Web APIにGASからアクセスしてGoogle Spreadsheetにデータを貯めたり、それを元に表やグラフの形式で可視化していくのは、プログラミングの知識が少しあればとても簡単にできてしまいます。今後もいろいろなツールを気軽に作っていけたらと思います。