Last active
May 20, 2016 20:01
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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