:::: MENU ::::
Posts tagged with: trello

Exporting tasks from Basecamp to Trello

After using Basecamp Classic for years, our team needed something fresh.

We had just come from an all-day test session that resulted in 200+ new tasks, and I started looking around for something visual, fast and with a good API.

We opted for Trello after some fruitful Twitter research and tests.

Getting data out of Basecamp Classic is pretty easy: under Settings:Export, they allow you to export all tasks, messages etc. in raw XML format.

2014-07-25_1556

Using a slick little library called Trello.NET, I then wrote a simple C# task importer that cycles through the XML file, creates lists and adds a card for every outstanding Basecamp task.

Within a few hours, the new board was ready and we were up and running!

photo

We will keep using Basecamp for some of our projects for a while, but Trello is already proving to be must faster and more convenient, especially when working on a game.

*Update*

Here’s some of the code I used (it won’t work if you copy paste it directly).
You can also see some naming conventions we used for task severity (like “nice to have”, “critical” and “polish”).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TrelloNet;
using System.Xml.Linq;
using System.Xml;

/* ... */

Board elroyProduction;

void addCard(string taskDescription, string taskResponsible, TrelloNet.Color color, 
List list, string creator, string addedOn)
{
    NewCard card = new NewCard(taskDescription, list);

    var resCard = trello.Cards.Add(card);

    if (taskDescription.ToLower().IndexOf("critical") != -1)
        trello.Cards.AddLabel(resCard, TrelloNet.Color.Red);
    else
        trello.Cards.AddLabel(resCard, color);

    trello.Cards.AddMember(resCard, getMemberFromName(taskResponsible));

    trello.Cards.AddComment(resCard, creator 
    + " added to Basecamp, " + addedOn);
}

/* ... */

// Main method:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("basecamp_classic_export.xml");

xmlDoc.DocumentElement.SelectNodes("todo-lists/todo-list");

foreach (XmlNode xmlNode in xmlDoc.DocumentElement.SelectNodes("todo-list"))
{
    string listName = xmlNode.ChildNodes[4].InnerText;

    List list = trello.Lists.Add(listName, elroyProduction);

    int count = 0;

    foreach (XmlNode task in xmlNode.SelectNodes("todo-items/todo-item"))
    {
        if (   task.ChildNodes[2].InnerText.IndexOf("true") != -1 
            && task.ChildNodes[2].Name.IndexOf("completed") != -1)
        {
            continue;
        }

        TrelloNet.Color color = TrelloNet.Color.Yellow;

        if (listName.ToLower().IndexOf("bug") != -1)
            color = TrelloNet.Color.Orange;
        if (   listName.ToLower().IndexOf("nice to have") != -1 
            || listName.ToLower().IndexOf("polish") != -1)
            color = TrelloNet.Color.Green;

        addCard(getDescription(task), getResponsible(task), color, 
                list, getCreator(task), getCreatedDate(task));
        count++;
    }

    if(count==0)
    {
        trello.Lists.Archive(list);
    }
}