Skip to content

Instantly share code, notes, and snippets.

@wqweto
Created June 8, 2015 12:48
Show Gist options
  • Save wqweto/5cbb064aa2a923243f72 to your computer and use it in GitHub Desktop.
Save wqweto/5cbb064aa2a923243f72 to your computer and use it in GitHub Desktop.
Generic CSV formatting extension that works on `IEnumerable<T>` and returns `IEnumerable<string>`
public static class CsvExtensions
{
//
// sample usage:
//
// var list = new object[] {
// new { Email = "svetlahristova0@gmail.bg", Name = "Свет.а Х,истова", UnsubscribeToken = "12\r34" },
// new { Email = "test", Name = "11\"22", UnsubscribeToken = "5\n67" },
// };
// var csv = string.Join(Environment.NewLine, list.ToCsvTable());
//
public static IEnumerable<string> ToCsvTable<T>(this IEnumerable<T> list, bool includeHeader = true)
{
const string separator = ",";
const string quote = "\"";
const int cellLength = 32768;
var props = typeof(T) != typeof(object) ? typeof(T).GetProperties() : null;
if (includeHeader)
{
var sb = new StringBuilder();
bool second = false;
foreach (var prop in props ?? list.First().GetType().GetProperties())
{
sb.Append(second ? separator : null).Append(prop.Name);
second = true;
}
yield return sb.ToString();
}
var escapeChars = new char[] { separator[0], quote[0], Environment.NewLine[0], Environment.NewLine.Last() };
foreach (var obj in list)
{
var sb = new StringBuilder();
bool second = false;
foreach (var prop in props ?? obj.GetType().GetProperties())
{
sb.Append(second ? separator : null);
second = true;
var value = prop.GetValue(obj, null);
if (value != null)
{
if (value is DateTime)
{
var output = ((DateTime)value);
sb.Append(output.ToString("yyyy-MM-dd" + (output.TimeOfDay.TotalSeconds != 0 ? " HH:mm:ss" : null)));
}
else
{
var output = value.ToString();
// quote string on either containing escape characters or length overflow only
if (output.IndexOfAny(escapeChars) < 0 && output.Length < cellLength)
{
sb.Append(output);
}
else
{
output = output.Replace(quote, quote + quote);
sb.Append(quote + (output.Length > cellLength - 3 ? output.Substring(1, cellLength - 3) : output) + quote);
}
}
}
}
yield return sb.ToString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment