2015-03-11 2 views
0

Я пытаюсь добавить функциональность Excel Export в мое приложение MVC5/Code-First Entity Framework через библиотеку EPPlus. На моем Экспорт View Я заполнил MultiSelectList с каждой из моих INV_Assets свойств модели. Затем они передаются в мой ExportController, чтобы указать, какие поля модели должны быть экспортированы.Экспорт в Excel - LINQ - включение значений ForeignKey в .ToList()?

Я получил заголовки (с помощью MultiSelectList), чтобы загрузить в Row1 из Excel и данные из моей INV_Assets модели для экспорта, чтобы преуспеть с помощью EPPlus LoadFromCollection(), как показано ниже (пример):

Код:

[HttpPost] 
    public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model) 
    { 
     ExcelPackage package = new ExcelPackage(); 
     var ws = package.Workbook.Worksheets.Add("TestExport"); 

     var exportFields = new List<string>(); 
     foreach (var selectedField in model.SelectedFields) 
     { 
      // Adds selected fields to [exportFields] List<string> 
      exportFields.Add(model.ListOfExportFields.First(s => s.Key == selectedField).Value); 
     } 

     { 
      ws.Cells[1, i + 1].Value = exportFields[i].ToString(); 
     } 

     var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray(); 

     ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow); 

     var memoryStream = new MemoryStream(); 
     package.SaveAs(memoryStream); 

     string fileName = "Exported-InventoryAssets-" + DateTime.Now + ".xlsx"; 
     string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 

     memoryStream.Position = 0; 
     return File(memoryStream, contentType, fileName); 
    } 

Выход:

Excel Output

Единственная проблема, которая у меня есть, - это поля ForeignKey в моей модели. Например, [Status] определяется в моей INV_Assets модели как:

[Required] 
    public int Status_Id { get; set; } 
    [ForeignKey("Status_Id")] 
    public virtual INV_Statuses Status { get; set; } 

Когда текущий экспорт выполняется, хотя, вместо того, чтобы сказать AVAILABLE/RECYCLED, то [Status] столбец в Excel содержит "InventoryTracker.Models.INV_Statuses" в каждой ячейке для каждой записи на экспорт.

Может ли кто-нибудь предложить понять, как получить не только прямые поля INV_Assets, но и значения ForeignKey для Model, Location, Status, Vendor, Manufacturer, and Type также в Excel?

Я прочитал и подумал, что метод Include() будет работать, но не повезло. [Type] по-прежнему отображается InventoryTracker.Models.INV_Types во всех звукозаписывающих клетках, используя следующий код (Ex.):

ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.Include("Model").Include("Manufacturer").Include("Type").Include("Status").Include("Vendor").ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow); 

EDIT:

я добавил using System.Data.Entity к моему ExportController, что позволило следующие компиляции:

ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.Include(m => m.Model.model_description).Include(m => m.Manufacturer.manufacturer_description).Include(m => m.Type.type_description).Include(m => m.Status.status_description).Include(m => m.Vendor.vendor_name).ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow); 

Я думал, что это будет трюк, но во время исполнения Я получаю:

InvalidOperationException was unhandled by user code. 

An exception of type 'System.InvalidOPerationException' occurred in EntityFramework.SqlServer.dll but was not handled in user code. 

Additional Information: A specified Include path is not valid. The EntityType 'InventoryTracker.DAL.INV_Models' does not declare a naviation property with the name 'model_description'. 

Я не понимаю, почему это помечено таким образом. INV_Assets имеет отношение к INV_Models определяется следующим образом:

public int Model_Id { get; set; } 
    [ForeignKey("Model_Id")] 
    public virtual INV_Models Model { get; set; } 

И INV_Models определяется как:

public class INV_Models 
{ 
    public int Id { get; set; } 

    [Required(ErrorMessage = "Please enter a Model Description.")] 
    public string model_description { get; set; } 

    [Required] 
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] 
    public DateTime created_date { get; set; } 

    [Required] 
    public string created_by { get; set; } 

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")] 
    public DateTime? modified_date { get; set; } 

    public string modified_by { get; set; } 
} 

Можно ли определить, что я делаю неправильно на Include()?


EDIT2:

Благодаря предложению Eric J «s, проблема решена! Добавлен ToString() переопределение на каждом из моих желаемых моделей, чтобы обеспечить значение пришли через а не только тип объекта:

public class INV_Models 
{ 

    public override string ToString() 
    { 
     return this.model_description; 
    } 
} 

public class INV_Manufacturers 
{ 
    public override string ToString() 
    { 
     return this.manufacturer_description; 
    } 
} 

public class INV_Locations 
{ 
    public override string ToString() 
    { 
     return this.location_dept + "|" + this.location_room; 
    } 
} 

public class INV_Vendors 
{ 
    public override string ToString() 
    { 
     return this.vendor_name; 
    } 
} 

public class INV_Types 
{ 
    public override string ToString() 
    { 
     return this.type_description; 
    } 
} 

public class INV_Statuses 
{ 
    public override string ToString() 
    { 
     return this.status_description; 
    } 
} 

ExportController:

[HttpPost] 
    public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model) 
    { 
     ExcelPackage package = new ExcelPackage(); 
     var ws = package.Workbook.Worksheets.Add("TestExport"); 

     var exportFields = new List<string>(); 
     foreach (var selectedField in model.SelectedFields) 
     { 
      // Adds selected fields to [exportFields] List<string> 
      exportFields.Add(model.ListOfExportFields.First(s => s.Key == selectedField).Value); 
     } 

     // Loops to insert column headings into Row 1 of Excel 
     for (int i = 0; i < exportFields.Count(); i++) 
     { 
      ws.Cells[1, i + 1].Value = exportFields[i].ToString(); 
     } 

     var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray(); 

     ws.Cells["A2"].LoadFromCollection(_db.INV_Assets.ToList(), false, TableStyles.None, BindingFlags.Default, membersToShow); 



     var membersToShow = typeof(INV_Assets).GetMembers().Where(p => exportFields.Contains(p.Name)).ToArray(); 

     var memoryStream = new MemoryStream(); 
     package.SaveAs(memoryStream); 

     string fileName = "Exported-InventoryAssets-" + DateTime.Now + ".xlsx"; 
     string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; 

     memoryStream.Position = 0; 
     return File(memoryStream, contentType, fileName); 
    } 

И выход Excel файл:

Excel3

ответ

1

Когда th Однако текущий экспорт выполняется, но вместо того, чтобы говорить «ДОСТУПНО/РЕЦИКЛИРОВАН», столбец [Статус] в excel содержит «InventoryTracker.Models.INV_Statuses» в каждой ячейке для каждой экспортируемой записи.

Это то, что вы получаете, если System.Object.ToString() вызывается в экземпляре INV_Statuses.

Попробуйте перекрывая ToString() в этом классе:

public class INV_Statuses 
{ 
    public override string ToString() 
    { 
     // TODO: Return whatever you would like to have appear in Excel 
    } 

    // Rest of the class here 
} 
+0

Спасибо Эрик, который сделал трюк! - показано выше в EDIT2. –

+0

Рад, что все получилось. –

Смежные вопросы