C# generic Excel exporter using reflection -
i'm working on generic excel exporter in c#. point put collection of type , specify properties of class should exported using lambda expressions , have done that. problem i'm struggling when have complex property in class, property value exported "namespace.classname" (e.g. "myapp.viewmodels.myviewmodel").
here code:
excel exporter class:
public class excelexporter { public void exporttoexcel<t>(ienumerable<t> data, params expression<func<t, object>>[] columns) { datatable datatable = this.converttodatatable(data, columns); //export datatable object excel using library... } private datatable converttodatatable<t>(ienumerable<t> data, params expression<func<t, object>>[] columnsfunc) { datatable table = new datatable(); foreach (var column in columnsfunc) { string columnname = reflectionutility.getpropertydisplayname<t>(column); table.columns.add(columnname); } foreach (t obj in data) { datarow row = table.newrow(); (int = 0; < table.columns.count; i++) { row[table.columns[i].columnname] = reflectionutility.getpropertyvalue<t>(obj, columnsfunc[i]); } table.rows.add(row); } return table; }
reflectionutility class - provides methods property name , value. "getpropertydisplayname" method reads [displayname] attribute value property , sets header column in excel document (the reason i'd property 'firstname' displayed 'first name').
public static class reflectionutility { /// <summary> /// returns display name of property (set using [displayname] attribute). /// if [displayname] not provided, returns actual property name. /// </summary> /// <typeparam name="t"></typeparam> /// <param name="expression"></param> /// <returns></returns> public static string getpropertydisplayname<t>(expression<func<t, object>> expression) { var memberexpression = expression.body memberexpression; if (memberexpression == null) { memberexpression = ((unaryexpression)expression.body).operand memberexpression; } var property = memberexpression.member propertyinfo; if (property != null) { var displaynameattribute = property.getcustomattribute(typeof(displaynameattribute), false) displaynameattribute; if (displaynameattribute != null) { return displaynameattribute.displayname; } } return memberexpression.member.name; } public static object getpropertyvalue<t>(t obj, expression<func<t, object>> expression) { var memberexpression = expression.body memberexpression; if (memberexpression == null) { memberexpression = ((unaryexpression)expression.body).operand memberexpression; } var property = memberexpression.member propertyinfo; if (property != null) { // note: if want export complex object, object's value "namespace.classname", // inappropriate displaying. must specify additionally property complex object should visualized... var value = property.getvalue(obj); return value; } return null; }
how consume excelexporter class:
excelexporter excelexporter = new excelexporter(); excelexporter.exporttoexcel<myviewmodel>(genericlisttoexport, p => p.stringproperty1, p => p.stringproperty2, p => p.complexproperty.intproperty1);
how can pass complexproperty.intproperty1 , value of , handle case when complexproperty null, won't nullreferenceexception.
here test scenario excel output:
any appreciated!
epplus can load ienumerable worksheet. means can load results of enumerable.select
call restrict columns want, eg:
var products=allproducts.where(prod=>prod.customerid=14) .select(new {prod.name,prod.category}); sheet.cells["a1"].loadfromcollection(products);
you can use if want, or can check how it's done in excelrangebase.loadfromcollection.
looking @ code, epplus looks displayname
, description
attributes generate header text, before falling member's name
Comments
Post a Comment