0

Ich versuche, ein .xlsx-Dokument vom Controller zu exportieren, wenn der Benutzer auf eine Schaltfläche klickt. Mein Modell sieht so aus:.NET-Export nach Excel - keine Listeneigenschaft anzeigen

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

Neben den String-Eigenschaften enthält ExportOrdersViewModel eine Liste von Elementen. Wenn die Datei erstellt wird, möchte ich diese Liste in einer Zelle anzeigen, wenn die Zeile erstellt wird.

Ich verwende ClosedXML, um die Datei zu erstellen. Bevor die Datei erstellt wird, habe ich im Controller eine DataTable erstellt, die alle ExportOrdersViewModel-Eigenschaften und eine Zeile enthält, die auf eine andere DataTable verweist, die die Eigenschaften für ExportOrdersItemViewModel enthält. Die parrent DataTable wird an die Arbeitsmappe übergeben.

Hier können Sie sehen, wie ich es tue:

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

, wenn ich in den Debug-Modus überprüfen die Aufträge Datatable, es Verweise auf die entsprechenden Positionen Datatable enthält, aber wenn ich Pass ist an der Arbeitsmappe, Die Zeile mit den Dateielementen ist leer.

Hier ist, wie ich die Datei erschaffe:

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

Dies ist ein Printscreen mit der Ausgabedatei: enter image description here

Und ich will es wie folgt aussehen: https://aspblogs.blob.core.windows.net/media/muhanadyounis/Media/linqParentChild_615EF617.jpg

+0

ist https://aspblogs.blob.core.windows.net/media/muhanadyounis/Media/linqParentChild_615EF617.jpg ein Screenshot von Excel? Sieht nicht so aus. –

+0

Es ist nicht. Ich wollte es nur so aussehen lassen –

+0

Nicht möglich in Excel. –

Antwort

0

In Am Ende fand ich eine passende Lösung dafür. Ich füge dem Arbeitsblatt jedes Mal eine neue Tabelle hinzu. Hier ist, wie ich es tat:

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

ich diese Methoden verwendet, um eine Datentabelle mit Elementen zu erstellen und die Tabellenköpfe für Aufträge und Einstellungen vor. Im nächsten Stück Code ist die Art, wie ich meine Datei erstellt:

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