I\'m using EPPlus
to generate Excel
files, in DAL I\'m populating DataTable
, filling data into table, and passing table to Presentation La
You do need the DataTable column to have the right type but you also need to modify the column or cell's Style.Numberformat.Format property.
Say you have an ExcelWorksheet
named ws
:
ws.Column(1).Style.Numberformat.Format = "yyyy-mm-dd";
//OR "yyyy-mm-dd h:mm" if you want to include the time!
To use build in excel formats, you need to pass correct string to
sheet.Cells[1, 1].Style.Numberformat.Format
property.
Now, somewhere later during execution, probably during serialization, EPPlus will try to match this format property with current dictionary of styles in workbook. It may depend on exact library version, but for example for EPPlust 4.1.0.0 short date key is "mm-dd-yy".
For 4.1.0.0 you can find all hard-coded codes and keys to build in formats in:
internal static void AddBuildIn(XmlNamespaceManager NameSpaceManager, ExcelStyleCollection<ExcelNumberFormatXml> NumberFormats)
- here all of those codes are actually included into workbook, all hard-codedWorkbook.Styles.NumberFormats
enumeration (as key use ExcelNumberFormatXml.Format
) Workbook.Styles.NumberFormats.
(non public memeber)_dic
for exact keys.If your columns are likely to move around (as we know end-users tend to be fickle) or you just have many date columns scattered across your spreadsheet, it would be helpful to write something a little more generic. Here is what I just wrote. It finds the position of all DateTime types in my POCO and creates a list that it then uses to set the column formatting. Remember data tables are zero based and Excel is not.
ws.Cells.LoadFromDataTable(tbl, true);
var dPos = new List<int>();
for (var i = 0; i < tbl.Columns.Count; i++)
if (tbl.Columns[i].DataType.Name.Equals("DateTime"))
dPos.Add(i);
foreach (var pos in dPos)
{
ws.Column(pos+1).Style.Numberformat.Format = "mm/dd/yyyy hh:mm:ss AM/PM";
}
If you are doing more than one datatable, you'll probably want to refactor it off into a function.
And here is a freebie... I can't take credit for this code. It takes a POCO list and turns it into a data table. It has made my life easier on a number of occasions having it in my 'toolkit'. Enjoy.
public DataTable ConvertToDataTable<T>(IList<T> data)
{
var properties =
TypeDescriptor.GetProperties(typeof(T));
var table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
var row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
Here's a nice C# extension method to help load from collection with headers and the proper date formatting:
(Decorate your properties with Description attributes for the column headings)
public static class EpPlusExtensions
{
public static void Load<T>(this ExcelWorksheet worksheet, IEnumerable<T> collection)
{
worksheet.Cells["A1"].LoadFromCollection(collection, true);
var properties = typeof(T).GetProperties();
for (var i = 0; i < properties.Length; i++)
{
if (new []{typeof(DateTime), typeof(DateTime?)}.Contains(properties[i].PropertyType))
{
worksheet.Column(i + 1).Style.Numberformat.Format = "m/d/yyyy";
}
}
}
}
Based on this discussion (epplus.codeplex.com/discussions/349927) you can also set column format to date.
worksheet_1.Cells[row, 3].Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern;