C# 在EPPlus中调用LoadFromCollection时忽略属性
我正在尝试使用以下代码生成Excel文件:C# 在EPPlus中调用LoadFromCollection时忽略属性,c#,excel,entity-framework-6,epplus,C#,Excel,Entity Framework 6,Epplus,我正在尝试使用以下代码生成Excel文件: public static Stream GenerateFileFromClass<T>(IEnumerable<T> collection, int startrow, int startcolumn, byte[]templateResource) { using (Stream template = new MemoryStream(templateResource))//this is an excel
public static Stream GenerateFileFromClass<T>(IEnumerable<T> collection, int startrow, int startcolumn, byte[]templateResource)
{
using (Stream template = new MemoryStream(templateResource))//this is an excel file I am using for a base/template
{
using (var tmpl = new ExcelPackage(template))
{
ExcelWorkbook wb = tmpl.Workbook;
if (wb != null)
{
if (wb.Worksheets.Count > 0)
{
ExcelWorksheet ws = wb.Worksheets.First();
ws.Cells[startrow, startcolumn].LoadFromCollection<T>(collection, false);
}
return new MemoryStream(tmpl.GetAsByteArray());
}
else
{
throw new ArgumentException("Unable to load template WorkBook");
}
}
}
}
publicstaticstreamgenerateFileFromClass(IEnumerable集合、int-startrow、int-startcolumn、byte[]templateResource)
{
使用(Stream template=new MemoryStream(templateResource))//这是一个用于基本/模板的excel文件
{
使用(var tmpl=new ExcelPackage(模板))
{
Excel工作簿wb=tmpl.工作簿;
如果(wb!=null)
{
如果(wb.Worksheets.Count>0)
{
Excel工作表ws=wb.Worksheets.First();
单元格[startrow,startcolumn].LoadFromCollection(collection,false);
}
返回新的MemoryStream(tmpl.GetAsByteArray());
}
其他的
{
抛出新ArgumentException(“无法加载模板工作簿”);
}
}
}
}
然而,这就像是一种享受。。我想忽略我的类集合中的几个属性,所以它和我的模板匹配。我知道,LoadFromCollection
将根据类的公共属性在Excel文件中生成列,但当我使用Entity Framework加载类时,如果我将字段标记为private,则EF会抱怨-主要是因为我不想显示的字段之一是键
我尝试使用
[XmlIgnore]
标记我不想要的属性,但没有成功。除了将整个集合加载到数据集或类似的数据集中并从中删除列之外,还有什么方法可以做到这一点?或者强制转换到没有我不需要的属性的基类?是的,EPPlus为您希望包含的属性提供了一个带有MemberInfo[]
参数的.LoadFromCollection()
方法重载
这使我们可以忽略任何具有特定属性的属性
例如,如果要忽略具有此自定义属性的属性:
公共类EpplusIgnore:属性{}
然后我们可以编写一个小的扩展方法,首先查找属性的所有MemberInfo
对象,而不使用[EpplusIgnore]
属性,然后返回EPPlus dll中.LoadFromCollection
方法的正确重载结果
大概是这样的:
公共静态类扩展
{
公共静态ExcelRangeBase LoadFromCollectionFiltered(this ExcelRangeBase@this,IEnumerable collection),其中T:class
{
MemberInfo[]membersToInclude=类型(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p=>!Attribute.IsDefined(p,typeof(EpplusIgnore)))
.ToArray();
返回@this.LoadFromCollection(collection,false,
OfficeOpenXml.Table.TableStyles.None,
BindingFlags.Instance | BindingFlags.Public,
成员(包括);
}
}
例如,在将个人
集合导出到excel时,这样使用它将忽略.Key
属性:
公共类人物
{
[签名者]
公共int密钥{get;set;}
公共字符串名称{get;set;}
公共整数{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var demoData=new List{new Person{Key=1,Age=40,Name=“Fred”},new Person{Key=2,Name=“Eve”,Age=21};
FileInfo fInfo=newfileinfo(@“C:\Temp\Book1.xlsx”);
使用(var excel=new ExcelPackage())
{
var ws=excel.Workbook.Worksheets.Add(“人员”);
ws.Cells[1,1].LoadFromCollectionFiltered(解调数据);
excel.SaveAs(fInfo);
}
}
}
给出我们期望的输出:
谢谢Stewart\R,基于您的工作,我制作了一个新的,用于接收财产名称:
public static ExcelRangeBase LoadFromCollection<T>(this ExcelRangeBase @this,
IEnumerable<T> collection, string[] propertyNames, bool printHeaders) where T:class
{
MemberInfo[] membersToInclude = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p=>propertyNames.Contains(p.Name))
.ToArray();
return @this.LoadFromCollection<T>(collection, printHeaders,
OfficeOpenXml.Table.TableStyles.None,
BindingFlags.Instance | BindingFlags.Public,
membersToInclude);
}
公共静态ExcelRangeBase LoadFromCollection(this ExcelRangeBase@this,
IEnumerable集合,字符串[]propertyNames,bool printHeaders),其中T:class
{
MemberInfo[]membersToInclude=类型(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p=>propertyNames.Contains(p.Name))
.ToArray();
返回@this.LoadFromCollection(集合、打印头、,
OfficeOpenXml.Table.TableStyles.None,
BindingFlags.Instance | BindingFlags.Public,
成员(包括);
}
从EPPlus
的5.5版开始,EpplusIgnore
属性被烘焙到库中。
我们可以像下面那样使用它
使用系统;
使用OfficeOpenXml.Attributes;
命名空间ExportToExcel.Services.ExportViewModels
{
[EpplusTable]
公共类学生导出视图模型
{
//[EpplusTableColumn]
[签名者]
公共字符串Id{get;set;}
...
}
}
请注意,EpplusTable
或EpplusTableColumn
属性是必需的
这里是相关测试用例的链接
最近,我不得不在一个项目中使用
EPPlus
,我在这篇博文中记录了设置过程下面是Stewart_R答案的简短版本。如果有人使用通用方法创建excel,请继续使用以下方法
public static class EPPlusHelper
{
public static byte[] GetExportToExcelByteArray<T>(IEnumerable<T> data)
{
var memoryStream = new MemoryStream();
ExcelPackage.LicenseContext = LicenseContext.Commercial;
using (var excelPackage = new ExcelPackage(memoryStream))
{
//To get all members without having EpplusIgnore attribute added
MemberInfo[] membersToInclude = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => !Attribute.IsDefined(p, typeof(EpplusIgnore)))
.ToArray();
var worksheet = excelPackage.Workbook.Worksheets.Add("Sheet1");
worksheet.Cells["A1"].LoadFromCollection(data, true, TableStyles.None, BindingFlags.Instance | BindingFlags.Public,
membersToInclude);
worksheet.Cells["A1:AN1"].Style.Font.Bold = true;
worksheet.DefaultColWidth = 20;
return excelPackage.GetAsByteArray();
}
}
}
你能不能使用像AutoMapper或自定义映射到另一个只包含所需属性的POCO的东西,然后将新对象集合传递给epplus,而不是EF collectionIt对我有效。但是我创建了一个LoadFromCollectionFiltered方法(这个ExcelRangeBase@this,IEnumerable collection,bool printHeader),以决定是否要在以后打印标题。这是一个非常好的建议,但不幸的是,它对我不起作用。使用IEnumerable的标准LoadFromCollection,只需额外的
public ActionResult ExportToExcel()
{
var result= // Here pass your data (list)
byte[] fileResult = EPPlusHelper.GetExportToExcelByteArray(result);
return File(fileResult, "application/vnd.ms-excel", "FileName.xlsx");
}