Embrace reflection and export collection to csv

Introduction

Its became very common request in recent data driven apps to able to export some certain data as csv format. CSv format became widely used and acceptable. And its very common that a individual app contains several such export feature that take different object collection respect to different needs and export to csv, so here is the problem lies. Goal of this post is to provide a generic solution using .net Reflation and Generics so same export can be reusable though entire application disrespect to object type and save our (programmers: most hardworking creature in this planet after ant 😎 ) effort.

Problem Statement

I have seen programmers invest several hours to build such export features satisfy different needs. So what happens for different object collection programmers write different export method that address particular export feature. Why is that? answer is simple each object has different property so csv will contains different column name for each object. So programmers write different export functions that address a specific object type and arrange the csv column name statically.

How Reflection can Help

To address this issue we can use .net Generics and Reflection. I will not discuss about theses wonderful feature instead of that I will utilize those feature to find a solution. If you navigate to msdn to see what reflection can do, you will see PropertyInfo (Humm this is all we need) .

Use PropertyInfo to discover information such as the name, data type, declaring type, reflected type, and read-only or writable status of a property, and to get or set property values.

So idea is we will use a Generic collection to export and use Reflection to iterate all property via PropertyInfo, thus we can get all property name/type all that whatever the object collection is provided. Once we have property name/ type we can do whatever data formatting  or processing we need according to our needs. Say for a particular app specification is whatever date time is exports to csv it should be formatted like ddMMYYY. As we have property type now , its a piece of cake right? 🙂

Solution

Here is the method that take Generic List<t> as parameter and use reflection to iterate the type and export accordingly.

/// <summary>
 /// Take object List as input and export to csv 
///which will be prompt save as dialog
 /// </summary>
 /// <typeparam name="T">Type of object</typeparam>
 /// <param name="listToExport">Object list to export</param>
 /// <param name="seperateChar">character to use as scv separator</param>
 public static void ExportListToCSV<T>(List<T> listToExport, string seperateChar)
 {
 Int32 success = 0;
 StringBuilder export = new StringBuilder();
 try
 { 
 string seperator = "";
 StringBuilder builder = new StringBuilder();
 PropertyInfo[] fieldInfo = listToExport[0].GetType().GetProperties();
 foreach (PropertyInfo col in fieldInfo)
 {
  if (col.PropertyType != typeof(EntityKey) 
&& col.PropertyType != typeof(EntityState))
 {
 builder.Append(seperator).Append(col.Name);
 seperator = seperateChar;
 }
 }
 export.AppendLine(builder.ToString());
 foreach (T dataItem in listToExport)
 {
 PropertyInfo[] allProperties = dataItem.GetType().GetProperties();
 seperator = "";
 StringBuilder builderTmp = new StringBuilder();
 foreach (PropertyInfo thisProperty in allProperties)
 {
 if (thisProperty.PropertyType != typeof(EntityKey) 
&& thisProperty.PropertyType != typeof(EntityKey))
 {
 object value = thisProperty.GetValue(dataItem, null);
 String propetyValue = (value == null ? String.Empty : value.ToString());
 builderTmp.Append(seperator).Append(propetyValue);
 seperator = seperateChar;
 }
 }
 ++success;
 export.AppendLine(builderTmp.ToString()); 
 }
 }
 catch (Exception ex)
 {
 throw ex;
 }
// finally { if (sr != null) { sr.Close(); } }
HttpContext.Current.Response.Clear();
 HttpContext.Current.Response.Buffer = true;
 HttpContext.Current.Response.ContentType = "application/CSV";
 HttpContext.Current.Response.AppendHeader("content-disposition", 
                                "attachment;filename=FileName.csv");
 HttpContext.Current.Response.Charset = "";
 HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
 HttpContext.Current.Response.Write(export.ToString());
 HttpContext.Current.Response.End();
}

One thing might you notice above

if (thisProperty.PropertyType != typeof(EntityKey) 
&& thisProperty.PropertyType != typeof(EntityKey))

Why we need this checking? you see if you are using Entity Framework in your app, all entity has these two additional property type predefined and we don’t what them to be exported to csv and confuse end user, do we? So additional checking is required to remove them. If you do not use Entity Framework you don’t need to worry about this checking.

So you can see a simple trick can save lots of development effort, enjoy the free time 🙂

Leave a comment