Write to CSV using Generic method passing Tuple

562 views Asked by At

I'm trying to create a generic method that will take in a List<T> and a List<Tuple<string,string, int>> so that I can write out to a CSV. I want the method to be able to take in any single level List<object> passed to it and using the Tuple list which will contain the correct column names and the order in which the columns should appear, however, I've never worked with a Tuple in this manner and so I'm not certain how to make the order part work with the Tuple.

So far I have this:

protected List<Tuple<string, string, int>> CreateColumnOrder()
{
     var columns = new List<Tuple<string, strint, int>>();
     columns.Add(Tuple.Create("OriginalColumnName", "New Column Name", 0);
     columns.Add(Tuple.Create("OriginalColumnName", "New Column Name", 2);
     columns.Add(Tuple.Create("OriginalColumnName", "New Column Name", 1);
     return columns;
}

public FileInfo GenericCsvFile<T>(List<T> list, List<Tuple<string, string, int>> columns)
{
    if(list != null)
    {
        //File logic here...

        StringBuilder sb = new StringBuilder();

        bool IsFirstRow = true;
        int rowCounter = 1;

        //Re-order the columns here before they get written out...

        foreach (T item in list)
        {
            PropertyInfo[] propInfo = item.GetType().GetProperties();

            while (isFirstRow)
            {
                sb.Append(WriteColumnName(columns));
                isFirstRow = false;
            }

            foreach (PropertyInfo info in propInfo)
            {
                object value = info.GetValue(item, null);
                sb.Append("\"").Append(value).Replace("\"", "''").Append("\"");
                rowCounter++;

                if (rowCounter == list.Count)
                {
                    sb.Append(Environment.NewLine);
                    using (var sw = file.AppendText())
                    {
                         sw.Write(sb.ToString());
                         sw.Close();
                         sw.Dispose();
                     }
                 }
                 else
                     sb.Append(Delimiter);
                }
            }
        }
        return file;
    }
}

protected StringBuilder WriteColumnName(List<Tuple<string, string, int>> columns)
{
    StringBuilder sb = new StringBuilder();

    //Same here, how to use the Tuple order to write the column names...

    foreach(var c in columns)
        sb.Append("\"").Append(c.Item2).Replace("\"", "''").Append("\"");

    return sb;
}

UPDATED: I'm posting the solution to my particular problem, special credit goes to @cloud120 for helping me with sorting the Tuple.

public FileInfo GenericCsvFile<T>(List<T> list, List<Tuple<string, string, int>> columns)
{
    if(list != null)
    {
        //File logic here...

        StringBuilder sb = new StringBuilder();

        bool IsFirstRow = true;
        int rowCounter = 0;

       if(columns != null)
           columns.Sort((a,b) => a.Item3.CompareTo(b.Item3));

        //moved this here to avoid reflection every time the loop was processed
        PropertyInfo[] propInfo = item.GetType().GetProperties();
        int count = propInfo.Length;

        foreach (T item in list)
        {
            if(isFirstRow)
            {
                sb.Append(WriteColumnName(columns));
                sb.Append(Environment.NewLine);
                isFirstRow = false;
            }

            int infoCount = 0;
            foreach (var column in columns)
            {
                var value = item.GetType().GetProperty(column.Item1).GetValue(item,null);
                sb.Append(value);
                infoCount++;
                rowCounter++;

                if (rowCounter == list.Count)
                {
                    sb.Append(Environment.NewLine);
                    using (var sw = file.AppendText())
                    {
                         sw.Write(sb.ToString());
                         sw.Close();
                         sw.Dispose();
                     }
                 }
                 else
                     sb.Append(infoCount == count ? Environment.NewLine : ",";
                }
            }
        }
        return file;
    }
}

protected StringBuilder WriteColumnName(List<Tuple<string, string, int>> columns)
{
    StringBuilder sb = new StringBuilder();

    foreach(var c in columns)
        sb.Append(c.Item2).Append(",");

    return sb;
}
0

There are 0 answers