使用数据注释设置由 LoadFromCollection (epplus) 生成的单元格格式
Set format of cells produced by LoadFromCollection (epplus) using data annotation
我正在使用 eeplus 创建一个 excel 电子表格,就像这样
using (var pck = new ExcelPackage())
{
var ws = pck.Workbook.Worksheets.Add("Customers");
ws.Cells["A1"].LoadFromCollection(customers, PrintHeaders: true);
var ms = new System.IO.MemoryStream();
pck.SaveAs(ms);
ms.WriteTo(Response.OutputStream);
}
客户 class 具有类似
的属性
[DisplayName("Customer creation date")]
public DateTime Created { get; set; }
DisplayName
似乎很荣幸,所以最上面的行将显示为 Customer creation date
但单元格内容显示为 43257,41667
.
我真正想要的是格式为 2018-04-05
.
的单元格
我可以做数据注释吗?我都试过了
[DisplayName("Customer creation date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime Created { get; set; }
和
[DisplayName("Customer creation date")]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
但单元格内容保持不变。
不,EPPlus 不会根据数据注释格式化您的数据。
它将日期格式化为整数,因此您应该将要格式化的列指定为
ws.Column(colPosition+1).Style.Number.Format="yyyy-mm-dd";
您可以在此处找到详细信息:
https://github.com/JanKallman/EPPlus/wiki/Formatting-and-styling
EPPlus 在更新为 excel 时总是根据 DisplayName 属性更改列名,否则如果没有设置 DisplayName 属性,则它将查找 "_"
(下划线)字符并将其替换为 " "
(Space) 列名中的字符,因此我们无法借助列名轻松找到 PropertyInfo 以根据需要格式化列。
这是基于索引 PropertyInfo
格式化列的最简单且最快捷的解决方案
PropertyInfo[] props = typeof(T).GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
Type t = props[i].PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(i + 1).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(i + 1).Style.Numberformat.Format = "HH:mm:ss";
}
如果您需要根据列名格式化列,我有另一个解决方案。
void ApplyDateTimeFormatting<T>(ExcelWorksheet ws, IEnumerable<T> data)
{
if (data.Count() == 0)
return;
Type type = data.First().GetType();
for (int c = 1; c <= toColumns; c++)
{
string column = ws.Cells[1, c].Text;
var t = type.GetPropertyWithDisplayName<T>(column).PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(c).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(c).Style.Numberformat.Format = "HH:mm:ss";
}
}
PropertyInfo GetPropertyFromDisplayName(Type type, string DisplayName)
{
MemberInfo[] members = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var member in members)
{
DisplayNameAttribute displayNameAttribute = member
.GetCustomAttributes(typeof(DisplayNameAttribute), inherit: false)
.FirstOrDefault() as DisplayNameAttribute;
string text = ((displayNameAttribute == null) ? member.Name.Replace('_', ' ') :
displayNameAttribute.DisplayName);
if (text == DisplayName)
return type.GetProperty(member.Name);
}
return null;
}
我按如下方式解决了它,所以我只是加载模型并根据我的模型进行更改,如果它是 int
或 datetime
var li = typeof(Model).GetProperties().ToArray();
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Sheet1");
var i = 0;
foreach (var c in li)
{
i++;
if(c.PropertyType.Name == typeof(DateTime).Name || c.PropertyType.Name == typeof(DateTime?).Name)
workSheet.Column(i).Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; ;
if (c.PropertyType.Name == typeof(int).Name || c.PropertyType.Name == typeof(int?).Name)
workSheet.Column(i).Style.Numberformat.Format = "0";
}
}
我正在使用 eeplus 创建一个 excel 电子表格,就像这样
using (var pck = new ExcelPackage())
{
var ws = pck.Workbook.Worksheets.Add("Customers");
ws.Cells["A1"].LoadFromCollection(customers, PrintHeaders: true);
var ms = new System.IO.MemoryStream();
pck.SaveAs(ms);
ms.WriteTo(Response.OutputStream);
}
客户 class 具有类似
的属性[DisplayName("Customer creation date")]
public DateTime Created { get; set; }
DisplayName
似乎很荣幸,所以最上面的行将显示为 Customer creation date
但单元格内容显示为 43257,41667
.
我真正想要的是格式为 2018-04-05
.
我可以做数据注释吗?我都试过了
[DisplayName("Customer creation date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime Created { get; set; }
和
[DisplayName("Customer creation date")]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
但单元格内容保持不变。
不,EPPlus 不会根据数据注释格式化您的数据。 它将日期格式化为整数,因此您应该将要格式化的列指定为
ws.Column(colPosition+1).Style.Number.Format="yyyy-mm-dd";
您可以在此处找到详细信息: https://github.com/JanKallman/EPPlus/wiki/Formatting-and-styling
EPPlus 在更新为 excel 时总是根据 DisplayName 属性更改列名,否则如果没有设置 DisplayName 属性,则它将查找 "_"
(下划线)字符并将其替换为 " "
(Space) 列名中的字符,因此我们无法借助列名轻松找到 PropertyInfo 以根据需要格式化列。
这是基于索引 PropertyInfo
格式化列的最简单且最快捷的解决方案PropertyInfo[] props = typeof(T).GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
Type t = props[i].PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(i + 1).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(i + 1).Style.Numberformat.Format = "HH:mm:ss";
}
如果您需要根据列名格式化列,我有另一个解决方案。
void ApplyDateTimeFormatting<T>(ExcelWorksheet ws, IEnumerable<T> data)
{
if (data.Count() == 0)
return;
Type type = data.First().GetType();
for (int c = 1; c <= toColumns; c++)
{
string column = ws.Cells[1, c].Text;
var t = type.GetPropertyWithDisplayName<T>(column).PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(c).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(c).Style.Numberformat.Format = "HH:mm:ss";
}
}
PropertyInfo GetPropertyFromDisplayName(Type type, string DisplayName)
{
MemberInfo[] members = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var member in members)
{
DisplayNameAttribute displayNameAttribute = member
.GetCustomAttributes(typeof(DisplayNameAttribute), inherit: false)
.FirstOrDefault() as DisplayNameAttribute;
string text = ((displayNameAttribute == null) ? member.Name.Replace('_', ' ') :
displayNameAttribute.DisplayName);
if (text == DisplayName)
return type.GetProperty(member.Name);
}
return null;
}
我按如下方式解决了它,所以我只是加载模型并根据我的模型进行更改,如果它是 int
或 datetime
var li = typeof(Model).GetProperties().ToArray();
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Sheet1");
var i = 0;
foreach (var c in li)
{
i++;
if(c.PropertyType.Name == typeof(DateTime).Name || c.PropertyType.Name == typeof(DateTime?).Name)
workSheet.Column(i).Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; ;
if (c.PropertyType.Name == typeof(int).Name || c.PropertyType.Name == typeof(int?).Name)
workSheet.Column(i).Style.Numberformat.Format = "0";
}
}