Trelloからスプレッドシートに転記する

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/Trello%E3%81%8B%E3%82%89%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AB%E8%BB%A2%E8%A8%98%E3%81%99%E3%82%8B/)をご覧ください😀


これは[SOUSEI Technology アドベントカレンダー](https://qiita.com/advent-calendar/2020/st) 10日目の記事です。

# はじめに
Trelloのカードをスプレッドシートで管理したくなるときってありますよね！
そんなときはGASでTrelloAPI叩いてやっちゃいましょう！
（以前 [スプレッドシートからTrelloにカード追加する](https://qiita.com/naoqoo2/items/956d3294e9da861c2975) を書いたのですが、今回はその逆です）


# やりたいこと

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56789/6ea9b393-c747-b507-2615-4649c3dc26bb.png)
↓↓↓ こんな感じに転記したい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56789/235af693-9030-784b-39e6-6239ce90d700.png)

# 使い方

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56789/3dd33c8d-97f4-4baf-d6b4-baddf0c67992.png)


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

# スクリプト

こちらをスプレッドシートのGASにコピペして `{書き換える}` 部分を書き換えてください。
（参考：[スプレッドシートからTrelloにカード追加する](https://qiita.com/naoqoo2/items/956d3294e9da861c2975) ）

```js
// ユーザー名
// 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ライフを!!