.NET导出到excel - 不显示列表属性

时间:2017-11-27 12:23:29

标签: .net model-view-controller datatable export-to-excel closedxml

我正在尝试在用户单击按钮时从控制器导出.xlsx文档。我的模型看起来像这样:

public class ExportOrdersViewModel
{
    public int Id { get; set; }
    public string CustomerFirstName { get; set; }
    public string CustomerLastName { get; set; }
    public string CustomerEmail { get; set; }
    public string CustomerMobile { get; set; }
    public string ShippingStreet { get; set; }
    public string ShippingCity { get; set; }
    public string ShippingCountry { get; set; }
    public string ShippingPostalCode { get; set; }
    public string ShippingTo { get; set; }
    public bool IsShipped { get; set; }
    public ICollection<ExportOrdersItemViewModel> Items { get; set; }

}

public class ExportOrdersItemViewModel
{
    public string TicketName { get; set; }
    public string EventName { get; set; }
    public int Quantity { get; set; }
    public string CurrencyId { get; set; }
    public string PaymentCurrencyId { get; set; }
    public string UnitPrice { get; set; }
    public string PaymentUnitPrice { get; set; }
}

除了字符串属性,ExportOrdersViewModel还包含一个项目列表。创建文件时,我想在创建行时在单元格中显示此列表。

我正在使用ClosedXML来创建文件。在创建文件之前,在控制器中我创建了一个DataTable,其中包含所有ExportOrdersViewModel属性,以及一行引用包含ExportOrdersItemViewModel属性的另一个DataTable。 parrent DataTable将被传递给工作簿。

在这里你可以看到我是如何做到的:

        DataTable orders = new DataTable();

        orders.Columns.Add("OrderID", typeof(string));
        orders.Columns.Add("Items", typeof(DataTable));
        orders.Columns.Add("IsShipped", typeof(bool));

        DataTable items = new DataTable();
        items.Columns.Add("TicketName", typeof(string));
        items.Columns.Add("Quantity", typeof(int));
        items.Columns.Add("Currency", typeof(string));


        exportModels.ForEach(o => orders.Rows.Add(
                                            o.Id,
                                           (DataTable)GetItems(o.Items),
                                            o.IsShipped
                                            ));

当我在调试模式下检查订单DataTable时,它包含对相应项DataTable的引用,但是当我传递给工作簿时,文件项行是空的。

以下是我创建文件的方法:

XLWorkbook workbook = new XLWorkbook();
        workbook.Worksheets.Add(orders, "Orders");

        Response.Clear();
        Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        Response.AddHeader("content-disposition", "attachment;filename=\"HelloWorld.xlsx\"");

        using (MemoryStream memoryStream = new MemoryStream())
        {
            workbook.SaveAs(memoryStream);
            memoryStream.WriteTo(Response.OutputStream);
            memoryStream.Close();
        }

        Response.End();

这是一个带有输出文件的打印屏幕:enter image description here

我想让它看起来像这样:https://aspblogs.blob.core.windows.net/media/muhanadyounis/Media/linqParentChild_615EF617.jpg

1 个答案:

答案 0 :(得分:0)

最后,我找到了一个合适的解决方案。我每次都会在工作表中添加一个新表。我是这样做的:

   //HELPER METHODS
    private DataTable GetItems(ICollection<ExportOrdersItemViewModel> list)
    {
        var items = new DataTable();

        items.Columns.Add(Resources.Names.OrderTicketName, typeof(string));
        items.Columns.Add(Resources.Names.OrderEventName, typeof(string));
        items.Columns.Add(Resources.Names.Quantity, typeof(int));
        items.Columns.Add(Resources.Names.Currency, typeof(string));
        items.Columns.Add(Resources.Names.PaymentCurrencyId, typeof(string));
        items.Columns.Add(Resources.Names.UnitPrice, typeof(string));
        items.Columns.Add(Resources.Names.PaymentUnitPrice, typeof(string));
        list.ForEach(i => items.Rows.Add(i.TicketName, i.EventName, i.Quantity, i.CurrencyId, i.PaymentCurrencyId, i.UnitPrice, i.PaymentUnitPrice));

        return items;
    }

    private void SetOrdersProperties(DataTable dataTable)
    {
        dataTable.Columns.Add(Resources.Names.OrderId, typeof(string));
        dataTable.Columns.Add(Resources.Names.OrderDate, typeof(string));
        dataTable.Columns.Add(Resources.Names.InvoicedDate, typeof(string));
        dataTable.Columns.Add(Resources.Names.CustomerFirstname, typeof(string));
        dataTable.Columns.Add(Resources.Names.CustomerLastName, typeof(string));
        dataTable.Columns.Add(Resources.Names.CustomerEmail, typeof(string));
        dataTable.Columns.Add(Resources.Names.CustomerPhone, typeof(string));
        dataTable.Columns.Add(Resources.Names.ShipTo, typeof(string));
        dataTable.Columns.Add(Resources.Names.ShippingStreet, typeof(string));
        dataTable.Columns.Add(Resources.Names.City, typeof(string));
        dataTable.Columns.Add(Resources.Names.ShippingPostalCode, typeof(string));
        dataTable.Columns.Add(Resources.Names.ShippingCountry, typeof(string));
        dataTable.Columns.Add(Resources.Names.IsShipped, typeof(string));
    }

    private void SetItemsProperties(DataTable dataTable)
    {
        dataTable.Columns.Add(Resources.Names.OrderTicketName, typeof(string));
        dataTable.Columns.Add(Resources.Names.OrderEventName, typeof(string));
        dataTable.Columns.Add(Resources.Names.Quantity, typeof(int));
        dataTable.Columns.Add(Resources.Names.Currency, typeof(string));
        dataTable.Columns.Add(Resources.Names.PaymentCurrencyId, typeof(string));
        dataTable.Columns.Add(Resources.Names.UnitPrice, typeof(string));
        dataTable.Columns.Add(Resources.Names.PaymentUnitPrice, typeof(string));
    }

我使用这些方法创建包含项目的DataTable,并为订单和项目设置tableHeaders。 在下一段代码中是我创建文件的方式:

 DataTable orders = new DataTable();
        SetOrdersProperties(orders);

        DataTable items = new DataTable();
        SetItemsProperties(items);

        XLWorkbook workbook = new XLWorkbook();
        var workSheet = workbook.Worksheets.Add("Orders");


        var index = 1;
        exportModels.ForEach(o =>
                            {
                                orders.Rows.Add(
                                             o.Id,
                                             o.OrderDate,
                                             o.InvoicedDate,
                                             o.CustomerFirstName,
                                             o.CustomerLastName,
                                             o.CustomerEmail,
                                             o.CustomerMobile,
                                             o.ShippingTo,
                                             o.ShippingStreet,
                                             o.ShippingCity,
                                             o.ShippingPostalCode,
                                             o.ShippingCountry,
                                             o.IsShipped ? "YES":"NO"
                                             );
                                workSheet.Cell(index, 1).InsertTable(orders);
                                index += orders.Rows.Count+1;
                                orders = new DataTable();
                                SetOrdersProperties(orders);
                                workSheet.Cell(index, 2).InsertTable(GetItems(o.Items));
                                workSheet.Cell(index, 1).Value = Resources.Names.Tickets;
                                workSheet.Range(index, 1, index + o.Items.Count,1).Merge();
                                index += o.Items.Count()+1;
                                index++;
                            });

        workSheet.Tables.ForEach(t => t.ShowAutoFilter = false);
        workSheet.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
        workSheet.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
        workSheet.Tables.ForEach(t => t.Theme = XLTableTheme.TableStyleLight13);