excel 在EPPlus中调用LoadFromCollection时忽略属性

7uhlpewt  于 2023-03-24  发布在  其他
关注(0)|答案(4)|浏览(264)

我正在尝试使用以下代码生成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文件中生成列,但由于我正在使用实体框架加载类,如果我将字段标记为私有,然后EF抱怨-主要是因为我不想显示的字段之一是键。
我尝试使用[XmlIgnore]标记我不想使用的属性,但没有用。有没有什么方法可以做到这一点,除了将整个集合加载到数据集或其他数据集中并从中修剪列之外?或者强制转换到一个没有我不需要的属性的基类?

bwitn5fc

bwitn5fc1#

是的,EPPlus为.LoadFromCollection<T>()方法提供了一个重载,并为您希望包含的属性提供了一个MemberInfo[]参数。
这给了我们所有我们需要忽略的具有某个属性的任何属性。
例如,如果我们想忽略具有此自定义属性的属性:

public class EpplusIgnore : Attribute { }

然后,我们可以编写一个小扩展方法,首先查找没有[EpplusIgnore]属性的属性的所有MemberInfo对象,然后在EPPlus dll中返回.LoadFromCollection方法的正确重载结果。
大概是这样的

public static class Extensions
{
    public static ExcelRangeBase LoadFromCollectionFiltered<T>(this ExcelRangeBase @this, IEnumerable<T> collection, bool printHeaders = true) 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, printHeaders, 
            OfficeOpenXml.Table.TableStyles.None, 
            BindingFlags.Instance | BindingFlags.Public, 
            membersToInclude);
    }
    
}

因此,例如,像这样使用它将在将Person集合导出到excel时忽略.Key属性:

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);
        }
    }
}

给出我们期望的输出:

z2acfund

z2acfund2#

谢谢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);
}
yrefmtwq

yrefmtwq3#

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; }

        ...

    }
}

请注意,EpplusTableEpplusTableColumn属性是必需的。
下面是相关测试用例https://github.com/EPPlusSoftware/EPPlus/blob/develop/src/EPPlusTest/LoadFunctions/LoadFromCollectionAttributesTests.cs的链接
最近,我不得不在一个项目中使用EPPlus,我在这篇博客文章https://www.kajanm.com/blog/exporting-data-to-excel-in-c-sharp/中记录了设置

pobjuy32

pobjuy324#

下面是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");
        }

相关问题