我有两个类,其中一个继承自另一个:
public class First
{
public string a{get;set;}
public string b{get;set;}
}
public class Second: First
{
public string c {get;set;}
}
然后我创建一个List<Second>
并填写一些信息,然后我使用EPPlus将此列表导出到Excel。
但是“问题”是继承类(第二个)的属性首先出现,而基类(第一个)的属性出现在excel之后:
c | a | b
-------------------
问题是我是否可以先放置基类的属性,还是可以说EPPlus属性的顺序?
编辑:
我把代码创建为Excel,非常简单
:
using (ExcelPackage package = new ExcelPackage(archivo))
{
ExcelWorksheet ws= package.Workbook.Worksheets.Add("Solds");
{
ws.Cells["A3"].LoadFromCollection(lstSolds);
package.Save();
}
}
答案 0 :(得分:4)
您可以使用属性和反射来选择属性的顺序。它还允许选择要输出的属性
public class First {
[Order(1)]
public string a { get; set; }
[Order(2)]
public string b { get; set; }
}
public class Second : First {
[Order(3)]
public string c { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
public class OrderAttribute : Attribute {
public int Order {get; set; }
public OrderAttribute(int order) {
Order = order;
}
}
class Program {
static void Main(string[] args) {
List<Second> list = new List<Second>();
list.Add(new Second {
a = "a",
b = "b",
c = "c"
});
WriteList(list);
}
static void WriteList(List<Second> list) {
PropertyInfo[] properties = typeof(Second).GetProperties();
int row = 3;
int col = 0;
foreach (var item in list) {
Dictionary<int, object> values = new Dictionary<int, object>();
foreach (var pi in properties) {
var orderAttr = pi.GetCustomAttribute(typeof(OrderAttribute)) as OrderAttribute;
if (orderAttr != null) { //this allow to output selective propertes. Those properties without [order] attriburte will not output
values.Add(orderAttr.Order, pi.GetValue(item, null));
}
}
foreach (var key in values.Keys.OrderBy(x => x)) {
ws.Cells[row, col + key].Value = values[key];
}
row++;
}
}
编辑为@Ion评论,添加了从Excel中读取的功能
static List<Second> ReadFromExcel(string filePath) {
List<Second> result = new List<Second>();
PropertyInfo[] props = typeof(Second).GetProperties();
//Allow access propertyInfo by name
Dictionary<string, PropertyInfo> properties = new Dictionary<string, PropertyInfo>();
foreach (var pi in props) {
properties.Add(pi.Name, pi);
}
using (var xls = new ExcelPackage(new FileInfo(filePath))) {
ExcelWorksheet ws = xls.Workbook.Worksheets[0];
//Let's assume you have property names has row heading in Excel
List<string> names = new List<string>(3);
for (int i = 1; i <= 4; i++) {
names.Add(ws.Cells[1, i].Value.ToString());
}
//Fill the list from Excel
for (int row = 3; row <= ws.Dimension.End.Row; row++) {
Second second = new Second();
for (int col = 1; col <= 4; col++) {
object value = ws.Cells[row, col].Value;
if (value != null)
properties[names[col]].SetValue(second, value);
}
result.Add(second);
}
}
return result;
}
答案 1 :(得分:3)
另一种方式,更多&#34; Epplus&#34;我想你可以说,这将是这样的:
var lstSolds = new List<First>();
for (var i = 0; i < 10; i++)
{
lstSolds.Add(new Second
{
a = "A-" + i,
b = "B-" + i,
c = "C-" + i
});
}
using (ExcelPackage package = new ExcelPackage(archivo))
{
var mi = typeof (Second)
.GetProperties()
.OrderBy(pi => pi.Name) //This controls the column order
.Cast<MemberInfo>()
.ToArray();
ws.Cells["A3"]
.LoadFromCollection(
lstSolds
, true
, TableStyles.Custom
, BindingFlags.Default
, mi
);
package.Save();
}
您可以通过调整mi
收集顺序来控制列的顺序。在这种情况下,它按升序排序,但LoadFromCollection
将遵守任何订单集。
对评论的回应
很容易让它们以您需要的任何顺序排序。只需要在传递保证排序顺序的方式之前构建数组。假设我们向d
类添加了一个属性First
。我们可以确保在c
之前对其进行排序:
public class First
{
public string a { get; set; }
public string b { get; set; }
public string d { get; set; } //Say we need this to sort before 'c'
}
public class Second : First
{
public string c { get; set; }
}
...
var lstSolds = new List<First>();
for (var i = 0; i < 10; i++)
{
lstSolds.Add(new Second
{
a = "A-" + i,
b = "B-" + i,
c = "C-" + i,
d = "D-" + i,
});
}
using (var package = new ExcelPackage(file))
{
var ws = package.Workbook.Worksheets.Add("table");
//var mi = typeof(Second)
// .GetProperties()
// .OrderBy(pi => pi.Name) //This controls the column order
// .Cast<MemberInfo>()
// .ToArray();
var firstmi = typeof (First)
.GetProperties()
.OrderBy(pi => pi.Name);
var secondmi = typeof (Second)
.GetProperties()
.Where(pi => !firstmi.Select(fpi => fpi.Name).Contains(pi.Name))
.OrderBy(pi => pi.Name);
//Sorting above will keep first proper before second
var mi = firstmi
.Concat(secondmi)
.Cast<MemberInfo>()
.ToArray();
ws.Cells["A3"]
.LoadFromCollection(
lstSolds
, true
, TableStyles.Custom
, BindingFlags.Public | BindingFlags.Instance
, mi
);
package.Save();
}