简体   繁体   English

使用具有匿名类型的LoadFromCollection进行epplus

[英]epplus using LoadFromCollection with anonymous types

I have a IEnumerable<object> dataSource which contains a collection anonymous types. 我有一个IEnumerable<object> dataSource,它包含一个匿名类型的集合。 The actual structure of the anonymous type won't be known at design time, so I'm trying to find a generic solution that can handle any anonymous type. 匿名类型的实际结构在设计时将不知道,所以我试图找到一个可以处理任何匿名类型的通用解决方案。

How can I load them into epplus to create a spreadsheet? 如何将它们加载到epplus中以创建电子表格? I have a worksheet called ws and I tried: 我有一个名为ws的工作表,我尝试过:

ws.Cells["A1"].LoadFromCollection(dataSource, true);

However when that runs it outputs all of the anonymous type's properties into a single cell: 但是,当它运行时,它会将所有匿名类型的属性输出到单个单元格中:

{ Id = 10000, Title = This is a test }

I've tried passing in MemberInfo using: 我尝试使用以下方法传递MemberInfo:

var members = dataSource.First().GetType().GetMembers();
ws.Cells["A1"].LoadFromCollection(this._dataSource, true,
    TableStyles.Medium1, BindingFlags.Public, members);

But that throws an exception: 但这引发了一个例外:

Supplied properties in parameter Properties must be of the same type as T 参数Properties中提供的属性必须与T的类型相同

Any suggestions on how I can create a spreadsheet using anonymous types in c#? 有关如何使用c#中的匿名类型创建电子表格的任何建议?

I have tested 我测试过了

using (var excel = new OfficeOpenXml.ExcelPackage())
{
    var sheet = excel.Workbook.Worksheets.Add("Test");
    sheet.Cells["A1"].LoadFromCollection(dataSource, true);
    excel.SaveAs(new FileInfo(@"C:\Temp\Test.xlsx"));
}

with this sample data: 使用此示例数据:

var dataSource = Enumerable.Range(1, 100).Select(i => new{ ID=i, Title="Title " + i });

It works fine. 它工作正常。 It creates two columns with the correct headers and 100 rows. 它创建两列具有正确的标题和100行。

But you should use anonymous types only if you know the structure at compile time. 但是,只有在编译时知道结构时才应使用匿名类型。

You could use a DataTable and LoadFromDataTable instead. 您可以使用DataTableLoadFromDataTable Since i don't know how you create the anonymous type i show you just a small sample: 由于我不知道你如何创建匿名类型,我只展示了一个小样本:

DataTable dataSource = new DataTable();
dataSource.Columns.Add("Id");    // default type is string 
dataSource.Columns.Add("Title");  
// add other columns
dataSource.Rows.Add("1", "Title1");
// add other rows

using (var excel = new OfficeOpenXml.ExcelPackage())
{
    var sheet = excel.Workbook.Worksheets.Add("Test");
    sheet.Cells["A1"].LoadFromDataTable(dataSource, true);
    excel.SaveAs(new FileInfo(@"C:\Temp\Test.xlsx"));
}

You could group the anonymous types to make it easier for exporting with dataTables. 您可以对匿名类型进行分组,以便使用dataTables轻松导出。 The bug "Supplied properties in parameter Properties must be of the same type as T" is still there and a workaround is using DataTables. 错误 “参数属性中提供的属性必须与T的类型相同”仍然存在,并且解决方法是使用DataTables。

// Imagine list is your main datasource
IEnumerable<object> list = Enumerable.Empty<object>(); // Data Source of <object>

// Added anon types at runtime added to the object list
var anonTypesOne = new object[] 
{ 
    new { GuidID = Guid.NewGuid(), StringProperty = "the string property" },
    new { IntegerID = 1, IntegerProperty = 99 }
};

var anonTypesTwo = new object[]
{
    new { StringID = "1", BooleanProperty = true, NumberProperty = 3, StringProperty = "Four" },
    new { GuidID = Guid.NewGuid(), NumberThree = 3 },
    new { GuidID = Guid.NewGuid(), NumberThree = 3 },
    new { GuidID = Guid.NewGuid(), NumberThree = 3 }
};

list = list.Concat(anonTypesOne).Concat(anonTypesTwo);

// Grouping works on anon types so we can group the export into their own tables
var groupings = list.GroupBy(i => i.GetType());

using(var package = new ExcelPackage(new FileInfo("C:\\Temp\\Anon.xlsx")))
{
    var ws = package.Workbook.Worksheets.Add("Anonymous Types");

    // add each "anon type matched grouping"
    foreach(var grouping in groupings)
    {
        var isNew = ws.Dimension == null; // the sheet is empty if Dimension is null.
        var row = 0;

        if(isNew)
        {
            row = 1; // start from the first row
        }
        else 
        {       
            // otherwise there are tables already, start from the bottom
            row = ws.Dimension.End.Row; 
        }       

        // because of EPP inheritance bug of T, we can just use dataTable
        DataTable dt = new DataTable(grouping.Key.Name);
        var properties = grouping.Key.GetProperties(); // Get anon type Properties

        foreach(var property in properties)
        {
            dt.Columns.Add(property.Name);
        }

        foreach(var item in grouping.ToList())
        {
            var dataRow = dt.NewRow();

            foreach(var p in properties) // populate a single row
            {
                dataRow[p.Name] = p.GetValue(item); // item is anon object instance
            }

            dt.Rows.Add(dataRow);
        }

        if(isNew) // load into the top most left cell of the worksheet
            ws.Cells[1, 1].LoadFromDataTable(dt, PrintHeaders: true);
        else // load from the dimension of current items + 1 row for spacing
            ws.Cells[ws.Dimension.End.Row + 1, 1].LoadFromDataTable(dt, PrintHeaders: true);

        ws.InsertRow(ws.Dimension.End.Row + 2, 5); // Insert some padding between each group

    }

    package.Save();
}

I was, this thread is older, but I'm looking for the same problem. 我是,这个帖子比较老,但我正在寻找同样的问题。 With the following code (VB) I have success. 使用以下代码(VB),我获得了成功。 Carsten 卡斯滕

    Dim targetFile = New IO.FileInfo(sFN)
    Dim dataSource = Enumerable.Range(0, 1).Select(Function(i) New With {.ID = 1000, .Titel = "This is a test "}).ToList
    Using epp = New OfficeOpenXml.ExcelPackage(targetFile)
        Dim ws = epp.Workbook.Worksheets.Add("lst_Anonymous")
        ws.Cells(1, 1).LoadFromCollection(dataSource, True,
                                               OfficeOpenXml.Table.TableStyles.Medium1,
                                               Reflection.BindingFlags.Public,
                                               dataSource.GetType.GetGenericArguments()(0).GetProperties)
                    epp.Save()
    End Using

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM