Skip to content

Instantly share code, notes, and snippets.

@dwcullop
Last active May 20, 2016 20:01
Show Gist options
  • Save dwcullop/43cc7e7ea5acb3e5af9ed21b1b5295bd to your computer and use it in GitHub Desktop.
Save dwcullop/43cc7e7ea5acb3e5af9ed21b1b5295bd to your computer and use it in GitHub Desktop.
Extension methods to create CSV/TSV content from any collection of POCO objects. Uses reflection to get all the readable properties and their names. Has overloads for optionally wrapping values in quotes, or supplying a value for missing values, etc.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace DareWare.Utils
{
public static class DataCollectionExtensions
{
#region Public Methods
#region Comma Separated Value Functions
public static string ToCSV<T>( this IEnumerable<T> data )
{
return data.BuildDataValues<T>( SEP_COMMA, CSV_DEF_MISSING, CSV_DEF_QUOTE, CSV_DEF_HEADER );
}
public static string ToCSV<T>( this IEnumerable<T> data, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_COMMA, CSV_DEF_MISSING, CSV_DEF_QUOTE, includeHeader );
}
public static string ToCSV<T>( this IEnumerable<T> data, char wrap, string missing )
{
return data.BuildDataValues<T>( SEP_COMMA, missing, wrap, CSV_DEF_HEADER );
}
public static string ToCSV<T>( this IEnumerable<T> data, char wrap, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_COMMA, missing, wrap, includeHeader );
}
public static string ToCSV<T>( this IEnumerable<T> data, string missing )
{
return data.BuildDataValues<T>( SEP_COMMA, missing, CSV_DEF_QUOTE, CSV_DEF_HEADER );
}
public static string ToCSV<T>( this IEnumerable<T> data, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_COMMA, missing, CSV_DEF_QUOTE, includeHeader );
}
public static string ToCSV<T>( this IEnumerable<T> data, char wrap )
{
return data.BuildDataValues<T>( SEP_COMMA, CSV_DEF_MISSING, wrap, CSV_DEF_HEADER );
}
public static string ToCSV<T>( this IEnumerable<T> data, char wrap, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_COMMA, CSV_DEF_MISSING, wrap, includeHeader );
}
#endregion
#region Tab Separated Value Functions
public static string ToTSV<T>( this IEnumerable<T> data )
{
return data.BuildDataValues<T>( SEP_TAB, TSV_DEF_MISSING, TSV_DEF_QUOTE, TSV_DEF_HEADER );
}
public static string ToTSV<T>( this IEnumerable<T> data, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_TAB, TSV_DEF_MISSING, TSV_DEF_QUOTE, includeHeader );
}
public static string ToTSV<T>( this IEnumerable<T> data, char wrap, string missing )
{
return data.BuildDataValues<T>( SEP_TAB, missing, wrap, TSV_DEF_HEADER );
}
public static string ToTSV<T>( this IEnumerable<T> data, char wrap, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_TAB, missing, wrap, includeHeader );
}
public static string ToTSV<T>( this IEnumerable<T> data, string missing )
{
return data.BuildDataValues<T>( SEP_TAB, missing, TSV_DEF_QUOTE, TSV_DEF_HEADER );
}
public static string ToTSV<T>( this IEnumerable<T> data, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_TAB, missing, TSV_DEF_QUOTE, includeHeader );
}
public static string ToTSV<T>( this IEnumerable<T> data, char wrap )
{
return data.BuildDataValues<T>( SEP_TAB, TSV_DEF_MISSING, wrap, TSV_DEF_HEADER );
}
public static string ToTSV<T>( this IEnumerable<T> data, char wrap, bool includeHeader )
{
return data.BuildDataValues<T>( SEP_TAB, TSV_DEF_MISSING, wrap, includeHeader );
}
#endregion
#region Generic Text Table Functions
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator )
{
return data.BuildDataValues<T>( separator, TT_DEF_MISSING, TT_DEF_QUOTE, TT_DEF_HEADER );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, bool includeHeader )
{
return data.BuildDataValues<T>( separator, TT_DEF_MISSING, TT_DEF_QUOTE, includeHeader );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, char wrap, string missing )
{
return data.BuildDataValues<T>( separator, missing, wrap, TT_DEF_HEADER );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, char wrap, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( separator, missing, wrap, includeHeader );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, string missing )
{
return data.BuildDataValues<T>( separator, missing, TT_DEF_QUOTE, TT_DEF_HEADER );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, string missing, bool includeHeader )
{
return data.BuildDataValues<T>( separator, missing, TT_DEF_QUOTE, includeHeader );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, char wrap )
{
return data.BuildDataValues<T>( separator, TT_DEF_MISSING, wrap, TT_DEF_HEADER );
}
public static string ToTextTable<T>( this IEnumerable<T> data, string seperator, char wrap, bool includeHeader )
{
return data.BuildDataValues<T>( separator, TT_DEF_MISSING, wrap, includeHeader );
}
#endregion
#endregion
#region Private Methods
public static string Wrap( this string s, char wrapper )
{
return (wrapper != NO_QUOTE) ? wrapper + s.Replace(wrapper.ToString(), "\\" + wrapper.ToString()) + wrapper : s;
}
private static string BuildDataValues<T>( this IEnumerable<T> data, string seperator, string missing, char wrap, bool includeHeaders = true )
{
StringBuilder sb = new StringBuilder();
var properties = typeof( T ).GetProperties().Where( p => p.CanRead ).ToList();
if ( includeHeaders )
{
sb.AppendLine( properties.Select( p => p.Name ).BuildLine( separator, wrap ) );
}
data.ToList().ForEach( d => sb.AppendLine( properties.Select( p => p.GetStringValue( d, missing ) ).BuildLine( separator, wrap ) ) ) );
return sb.ToString();
}
private static string BuildLine( this IEnumerable<string> items, string separator, char wrap )
{
return String.Join( separator, items.Select( s => s.Wrap( wrap ) ) );
}
private static string GetStringValue( this PropertyInfo pi, object target, string missing )
{
try
{
object value = pi.GetValue( target );
return (value != null) ? value.ToString() : missing;
}
catch ( Exception e )
{
Debug.WriteLine( String.Format( CultureInfo.InvariantCulture, "Caught Exception while trying to get value: {0}", e.ToString() ) );
return missing;
}
}
#endregion
#region Constants
private static const bool CSV_DEF_HEADER = true;
private static const string CSV_DEF_MISSING = "-";
private static const char CSV_DEF_QUOTE = DOUBLE_QUOTE;
private static const bool TSV_DEF_HEADER = true;
private static const string TSV_DEF_MISSING = "N/A";
private static const char TSV_DEF_QUOTE = NO_QUOTE;
private static const bool TT_DEF_HEADER = false;
private static const string TT_DEF_MISSING = "";
private static const char TT_DEF_QUOTE = SINGLE_QUOTE;
private static const char NO_QUOTE = (char)0;
private static const char DOUBLE_QUOTE = '\"';
private static const char SINGLE_QUOTE = '\'';
private static const string SEP_COMMA = ",";
private static const string SEP_TAB = "\t";
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment