これはSOUSEI Technology アドベントカレンダー 10日目の記事です。

はじめに

Trelloのカードをスプレッドシートで管理したくなるときってありますよね!
そんなときはGASでTrelloAPI叩いてやっちゃいましょう!
(以前 スプレッドシートからTrelloにカード追加する を書いたのですが、今回はその逆です)

やりたいこと

  • 複数のTrelloボードを1つのスプレッドシートにまとめたい
  • 特定のラベルがついてるカードだけを対象にしたい

image.png
↓↓↓ こんな感じに転記したい
image.png

使い方

ボタンを押せばTrelloからスプレッドシートに転記されます。

image.png

自分はトリガーを仕掛けて毎日自動実行させたりもしてます。

スクリプト

こちらをスプレッドシートのGASにコピペして {書き換える} 部分を書き換えてください。
(参考:スプレッドシートからTrelloにカード追加する

// ユーザー名
// URLにも使用されている
var user_name = '{書き換える}';

// TrelloのAPIキーとトークン
// https://trello.com/app-key
// 上記にアクセスしてKeyとTokenを取得する。※Tokenは『generate a Token.』から作成する。
var api_key = '{書き換える}';
var api_token = '{書き換える}';

var boards_info = [
  {"name":"{書き換える}","id":"{書き換える}","label_name":"{書き換える}"},
  {"name":"{書き換える}","id":"{書き換える}","label_name":"{書き換える}"},
  // {"name":"テストボード","id":"hogehogehoge","label_name":"転記"},
];

function importTrelloCard() {
  // ----- ここから書き換え -----
  // 書き込むシートURL
  var sheet_url = '{書き換える}';
  // 書き込むシート名
  var sheet_name = 'シート1';
  // 存在チェック(true: すでに転記済のカードは取り込まない)
  var existence_check = true;
  // ----- ここまで書き換え -----

  var ss = SpreadsheetApp.openByUrl(sheet_url);
  var sheet = ss.getSheetByName(sheet_name);
  var existence_keys = fetchExistenceKeys();

  for (var i = 0; board = boards_info[i]; i++) {
    var cards = fetchCards(board['id'], board['label_name']);
    for (var j = 0; item = cards[j]; j++) {
      if (existence_check && existsData(item)) {
        continue;
      }
      sheet.appendRow(itemToRow(item, board));
    }
  }

  function fetchExistenceKeys () {
    var existence_keys = {};
    var sheet_data = sheet.getDataRange().getValues();
    for (var i = 0; row = sheet_data[i]; i++) {
      existence_keys[generateKey(rowToItem(row))] = true;
    }
    return existence_keys;
  }

  function existsData (item) {
    if (existence_keys[generateKey(item)]) {
      return true;
    }
    return false;
  }

  function generateKey (item) {
    var key = item['id'];
    return key;
  }

  function rowToItem (row) {
    var item = {};
    item['id'] = row[0];
    return item;
  }

  function itemToRow (item, board) {
    var row = [];
    row[0] = item['id'];
    row[1] = item['name'];
    row[2] = board['name'];
    row[3] = item['url'];
    return row;
  }

  function fetchCards (board_id, label_name) {
    var result = [];
    var response = getCardsBySearch(board_id, label_name);
    var cards = response['cards'];
    for (var i = 0; card = cards[i]; i++) {
      var item = {};
      item['id'] = card['shortLink'];
      item['name'] = card['name'];
      item['url'] = card['shortUrl'];
      result.push(item);
    }
    Logger.log(result);
    return result;
  }
}

// 事前準備用
function getBoards() {
  var url = 'https://api.trello.com/1/members/' + user_name + '/boards?key=' + api_key + '&token=' + api_token + '&fields=name';
  Logger.log(UrlFetchApp.fetch(url, {'method':'get'}));
}

function getCardsBySearch(board_id, label_name) {
  // 最終更新日でソートして100件を取得
  // label_idのキーワード指定だとヒットしないカードがあったため、ラベル名で検索するよう修正
  //var url = "https://trello.com/1/search?key=" + api_key + "&token=" + api_token + "&modelTypes=cards&card_fields=name,shortLink,shortUrl&cards_limit=100&sort:edited&query=" + label_id;
  var url = "https://trello.com/1/search?key=" + api_key + "&token=" + api_token + "&modelTypes=cards&card_fields=name,shortLink,shortUrl&cards_limit=100&sort:edited&query=board:" + board_id + " label:" + label_name;
  Logger.log(url);
  var response = UrlFetchApp.fetch(url, {'method':'get'});
  //Logger.log(response);
  var json = JSON.parse(response.getContentText());
  return json;
}

function onOpen() {
  // メニューバーにカスタムメニューを追加
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [
    {name : "Trelloから転記する", functionName : "importTrelloCard"},
  ];
  spreadsheet.addMenu("GAS", entries);
}
    

さいごに

それではステキなスプレッドシート&Trelloライフを!!