我正在尝试使用以下代码生成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");
}
}
}
}
这就像一种享受,但是..我想忽略我的类集合中的几个属性,因此它与我的模板匹配。我知道LoadFromCollection
将根据类的公共属性在Excel文件中生成列,但是当我使用Entity Framework加载类时,如果我将该字段标记为私有,那么EF会抱怨 - 主要是因为我不想展示的其中一个领域是Key。
我试图使用[XmlIgnore]
标记我不想要的属性,但无济于事。有没有办法做到这一点,没有将整个集合加载到数据集或其他一些数据集,并修剪列中的列?或者在没有我不需要的属性的情况下投射到基类?
答案 0 :(得分:16)
是的,EPPlus提供了.LoadFromCollection<T>()
方法的重载,其中包含您希望包含的属性的MemberInfo[]
参数。
这给了我们所有我们需要忽略具有特定属性的任何属性。
例如,如果我们要忽略具有此自定义属性的属性:
public class EpplusIgnore : Attribute { }
然后我们可以编写一个小扩展方法来首先找到没有MemberInfo
属性的属性的所有[EpplusIgnore]
对象,然后返回.LoadFromCollection
方法的正确重载的结果EPPlus dll。
这样的事情:
public static class Extensions
{
public static ExcelRangeBase LoadFromCollectionFiltered<T>(this ExcelRangeBase @this, IEnumerable<T> collection) where T:class
{
MemberInfo[] membersToInclude = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p=>!Attribute.IsDefined(p,typeof(EpplusIgnore)))
.ToArray();
return @this.LoadFromCollection<T>(collection, false,
OfficeOpenXml.Table.TableStyles.None,
BindingFlags.Instance | BindingFlags.Public,
membersToInclude);
}
}
因此,例如,在将.Key
集合导出为excel时,使用它会忽略Person
属性:
public class Person
{
[EpplusIgnore]
public int Key { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
var demoData = new List<Person> { new Person { Key = 1, Age = 40, Name = "Fred" }, new Person { Key = 2, Name = "Eve", Age = 21 } };
FileInfo fInfo = new FileInfo(@"C:\Temp\Book1.xlsx");
using (var excel = new ExcelPackage())
{
var ws = excel.Workbook.Worksheets.Add("People");
ws.Cells[1, 1].LoadFromCollectionFiltered(demoData);
excel.SaveAs(fInfo);
}
}
}
给出我们期望的输出:
答案 1 :(得分:3)
感谢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);
}
答案 2 :(得分:0)
从 EPPlus
的 5.5 版开始,EpplusIgnore
属性被添加到库中。
https://github.com/EPPlusSoftware/EPPlus/pull/258
我们可以像下面那样使用它。
using System;
using OfficeOpenXml.Attributes;
namespace ExportToExcel.Services.ExportViewModels
{
[EpplusTable]
public class StudentExportViewModel
{
// [EpplusTableColumn]
[EpplusIgnore]
public string Id { get; set; }
...
}
}
请注意,EpplusTable
或 EpplusTableColumn
属性是必需的。
最近,我不得不在一个项目中使用 EPPlus
,并且我在这篇博文 https://www.kajanm.com/blog/exporting-data-to-excel-in-c-sharp/
答案 3 :(得分:0)
以下是 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();
}
}
}
然后像这样调用这个方法
public ActionResult ExportToExcel()
{
var result= // Here pass your data (list)
byte[] fileResult = EPPlusHelper.GetExportToExcelByteArray(result);
return File(fileResult, "application/vnd.ms-excel", "FileName.xlsx");
}