Skip to main content
Con's place

Google Sheets script for Trello V2

Since I have posted the Google Sheets script for Trello I made some updates to include members assigned to card and customfields value (power-up), so I thought I’d share the code.

/**
 * Loads the details from a Trello board using the Trello API v1, into a google sheet.
 *
 * Each time it is run the sheet gets cleared and the following data are downloaded from the Trello board 
 *"Date", "Task", "Desc", "Who", "List", "Link", "Labels","Label Colors","Checklists", "Due Date", "Due Complete","Task (Link)", "Members", "Comments"
 *
 * NOTE: Additional columns are created for custom fields if any
 *
 * Additionally the sheet for checklist gets cleared and the following data are downloaded from the Trello board 
 *"Card","Checklist", "Check Name", "State","Task","Who","Link","Labels","Due Date","Due Complete","List","Members"
 * 
 * Additionally the sheet for comments gets cleared and the following data are downloaded from the Trello board 
 *"Card","Date", "Who Commented", "Comment","Task","Who","Link","Labels","Due Date","Due Complete","List","Members"
 *
 * @param {string} api_key The Trello API Key (Get it from https://trello.com/app-key)
 * @param {string} api_token The Trello API token (Get it from https://trello.com/app-key)
 * @param {string} board_id The Trello Board ID who's cards will be downloaded (Get it from adding ".json" at the end of the board url)
 * @param {string} sheetName The name of the sheet in the active spreadsheet to update it's rows
 * @param {string} checklistSheetName The name of the sheet in the active spreadsheet to update it's rows for checklists
 * @param {string} commentsSheetName The name of the sheet in the active spreadsheet to update it's rows for comments
 * @param {boolean} enableStackdriverLogging True to enable Stackdriver Logging. Default is false
 * @param {string} logingName logging name to be appended in the message. Default is ""
 * @return {void} Not applicable. 
 */
function loadTrello(api_key,api_token,board_id,sheetName,checklistSheetName, commentsSheetName, enableStackdriverLogging, logingName) {
  try {
    if (enableStackdriverLogging) console.time(logingName + " - loadTrello");
    if (enableStackdriverLogging) console.log(logingName + " - Loading from Trello STARTED");
     
    var url = "https://api.trello.com/1/";
    var key_and_token = "key="+api_key+"&token="+api_token;    
    var cr = 2;
     
    // get sheet with name Trello, clear all contents, add titles
    var ss = SpreadsheetApp.getActive().getSheetByName(sheetName).clear();
    var trelloFiledHeaders = ["Date", "Task", "Desc", "Who", "List", "Link", "Labels","Label Colors","Checklists", "Due Date", "Due Complete", "Task (Link1)", "Members", "Comments"];
    // headers without custom fields
    var originalTrelloFiledHeadersCount = 14;
    // headers with custom fields
    var trelloFiledHeadersCount = originalTrelloFiledHeadersCount;
    //Get all custom fields from Trello API
    var response = UrlFetchApp.fetch(url + "boards/" + board_id + "/customFields?" + key_and_token);
    var boardCustomFields = JSON.parse((response.getContentText()));
    // for all custom fields
    for (var i=0; i < boardCustomFields.length; i++) {
      trelloFiledHeaders.push(boardCustomFields[i].name);
      //position in append array of custom fields
      boardCustomFields[i].pos=trelloFiledHeadersCount;
      trelloFiledHeadersCount++;
    }
    ss.appendRow(trelloFiledHeaders);
    ss.getRange(1,1,1,trelloFiledHeadersCount).setFontWeight("Bold");
     
    // get sheet for checklists, clear all contents, add titles
    var ssChecklist = SpreadsheetApp.getActive().getSheetByName(checklistSheetName).clear();
    ssChecklist.appendRow(["Card","Checklist", "Check Name", "State","Task","Who","Link","Labels","Due Date","Due Complete","List","Members"]);
    ssChecklist.getRange(1,1,1,12).setFontWeight("Bold");
     
    // get sheet for comments, clear all contents, add titles
    var ssComments = SpreadsheetApp.getActive().getSheetByName(commentsSheetName).clear();
    ssComments.appendRow(["Card","Date", "Who Commented", "Comment","Task","Who","Link","Labels","Due Date","Due Complete","List","Members"]);
    ssComments.getRange(1,1,1,12).setFontWeight("Bold");
     
    //Get all lists from Trello API
    var response = UrlFetchApp.fetch(url + "boards/" + board_id + "/lists?cards=all&" + key_and_token);
    var lists = JSON.parse((response.getContentText()));
     
    // for all lists 
    for (var i=0; i < lists.length; i++) {
      var list = lists[i];
      // Get all cards from Trello API
      // /?filter=all if we want archived as well (archived have closed:true)
      var response = UrlFetchApp.fetch(url + "list/" + list.id + "/cards/?actions=all&customFieldItems=true&" + key_and_token); 
      var cards = JSON.parse(response.getContentText());
      if(!cards) continue;
       
      // for all cards
      for (var j=0; j < cards.length; j++) {
        var appentArray = new Array(trelloFiledHeadersCount);
        //initialize custom fields values
        for (var jk=originalTrelloFiledHeadersCount; jk < trelloFiledHeadersCount; jk++) {
          appentArray[jk] = "";
        }
        var card = cards[j];
         
        var name = card.name;
        var link = card.shortUrl;
        var listname = list.name;
        var desc = card.desc;
        var duedate = card.due;
        var duecomplete = (card.dueComplete == true ? 'YES' : 'NO');
        var labels = "";
        var labelsColors = "";
        for (var l=0; l < card.labels.length; l++) {
          labels = labels + (labels == "" ? "" : ", ")  + card.labels[l].name;
          labelsColors = labelsColors + (labelsColors == "" ? "" : "\n")  + card.labels[l].color;
        }
        var namelink = '=HYPERLINK("' + link +'", "' + name + '")';
        for (var k=0; k < card.actions.length; k++) {
          // Get the rest of the card data
          var dato = card.actions[k].date;
          var fullname = card.actions[k].memberCreator.fullName;
        }
         
        // ------- Custom Fields  --------------------
        var customFieldItems = card.customFieldItems;
        for (var ck=0; ck < customFieldItems.length; ck++) {
          // get board custom field from id
          var boardCustomField = searchArray(customFieldItems[ck].idCustomField, boardCustomFields);
           
          var customFieldValueText = "";
          if (boardCustomField.type=="text") {
            customFieldValueText = customFieldItems[ck].value.text;
          } else if (boardCustomField.type=="checkbox") {
            customFieldValueText = customFieldItems[ck].value.checked; 
          }else if (boardCustomField.type=="date") {
            customFieldValueText = customFieldItems[ck].value.date; 
          }else if (boardCustomField.type=="number") {
            customFieldValueText = customFieldItems[ck].value.number; 
          }else if (boardCustomField.type=="list") {
            customFieldValueText = searchArray(customFieldItems[ck].idValue, boardCustomField.options).value.text; 
          }
            appentArray[boardCustomField.pos] = customFieldValueText;
        }
        // Get custom field items END -----
                
        //-------- Members  ----------------------
        //Get all Members frin API
        var response = UrlFetchApp.fetch(url + "cards/" + card.id + "/members/?" + key_and_token);
        var membersdetails = JSON.parse(response.getContentText());
                 
        var membersstr = "";
         
        // For all checklists get Name
        for (var o=0; o < membersdetails.length; o++) {
          membersstr = membersstr + (membersstr == "" ? "" : ", \n") + membersdetails[o].fullName;
        }
         
        //-------- Checklists ----------------------
        //Get all checklists of card from Trello API
        var response = UrlFetchApp.fetch(url + "cards/" + card.id + "/checklists?action=all&" + key_and_token);
        var cardchecklists = JSON.parse(response.getContentText());
         
        var checkliststr = "";
        // For all checklists get Name
        for (var m=0; m < cardchecklists.length; m++) {
          checkliststr = checkliststr + (checkliststr == "" ? "" : "\n\n") + cardchecklists[m].name + "\n --------- \n";
          // For all checklists get Items
          for (var n=0; n < cardchecklists[m].checkItems.length; n++) {
            checkliststr = checkliststr + (checkliststr == "" ? "" : "\n") + (cardchecklists[m].checkItems[n].state == 'complete' ? "[x] ":"[ ] " ) + cardchecklists[m].checkItems[n].name;
            //append row in checklist sheet            
            ssChecklist.appendRow([card.name,cardchecklists[m].name, cardchecklists[m].checkItems[n].name, cardchecklists[m].checkItems[n].state
              ,name + " - " +cardchecklists[m].checkItems[n].name,fullname,link,labels,duedate,duecomplete,listname,membersstr]);
          }
        }
         
        //-------- Comments ----------------------
        //Get all comments of card from Trello API
        var response = UrlFetchApp.fetch(url + "cards/" + card.id + "/?actions=commentCard&" + key_and_token);
        var cardcomments = JSON.parse(response.getContentText()).actions;
         
        var cardcommentsstr = "";
        // For all comments get Name
        for (var p=0; p < cardcomments.length; p++) {
          cardcommentsstr = cardcommentsstr + (cardcommentsstr == "" ? "" : "\n\n") + cardcomments[p].date + " --" + cardcomments[p].memberCreator.fullName + "\n --------- \n" + cardcomments[p].data.text;
          //append row in checklist sheet            
            ssComments.appendRow([card.name,cardcomments[p].date, cardcomments[p].memberCreator.fullName, cardcomments[p].data.text
              ,name,fullname,link,labels,duedate,duecomplete,listname,membersstr]);          
        }
               
      //Append row with data
      appentArray[0] = dato;
      appentArray[1] =  name;
      appentArray[2] =  desc;
      appentArray[3] =  fullname;
      appentArray[4] =  listname;
      appentArray[5] =  link;
      appentArray[6] =  labels;
      appentArray[7] =  labelsColors;
      appentArray[8] =  checkliststr;
      appentArray[9] =  duedate;
      appentArray[10] =  duecomplete;
      appentArray[11] =  namelink;
      appentArray[12] =  membersstr;
      appentArray[13] =  cardcommentsstr;
      ss.appendRow(appentArray);
       
      //change labels color ---
      var labelsColor = labelsColors.split('\n');
      if (labelsColor[0] == "sky") {
        ss.getRange(cr, 8).setBackground("#87CEFA");
      } else {
        ss.getRange(cr, 8).setBackground(labelsColor[0]);
        if ((labelsColor[0] == "red") || (labelsColor[0] == "black") || (labelsColor[0] == "purple") || (labelsColor[0] == "green") || (labelsColor[0] == "blue")) {
          ss.getRange(cr, 8).setFontColor("white");
        }
      }
      //change labels color END ---
       
      cr++;
     }                                      
    }
  } catch (e) {
    if (enableStackdriverLogging) console.error(logingName + " ERROR: " + e);    
  } finally {
    if (enableStackdriverLogging) console.log(logingName + " - Loading from Trello ENDED");
    if (enableStackdriverLogging) console.timeEnd(logingName + " - loadTrello");
  }
}
 
/**
* Finds objects in an array of objects by obj.id 
*
* @param {string} idKey The id sting to find
* @param {Array} myArray The array that contains the objects
* @return {object} The object that is found. 
*/
function searchArray(idKey, myArray){
    for (var i=0; i < myArray.length; i++) {
        if (myArray[i].id === idKey) {
            return myArray[i];
        }
    }
}
© Constantinos Evangelou, 2011 - 2026