I am working on adding Export()
functionality to my MVC5 Code-First app. To do this, I have created the following ViewModel
- ExportAssetsViewModel
:
public class ExportAssetsViewModel
{
public Dictionary<int, string> ListOfExportFields { get; set; }
public int[] SelectedFields { get; set; }
public ExportAssetsViewModel() {
ListOfExportFields = new Dictionary<int, string>() {
{1, "Model"},
{2, "Manufacturer"},
{3, "Type"},
{4, "Location"},
{5, "Vendor"},
{6, "Status"},
{7, "ip_address"},
{8, "mac_address"},
{9, "note"},
{10, "owner"},
{11, "cost"},
{12, "po_number"},
{13, "description"},
{14, "invoice_number"},
{15, "serial_number"},
{16, "asset_tag_number"},
{17, "acquired_date"},
{18, "disposed_date"},
{19, "verified_date"},
{20, "created_date"},
{21, "created_by"},
{22, "modified_date"},
{23, "modified_by"},
};
}
}
This is used to display my MultiSelectList
on my ExportController - Index()
View:
ExportController - Index() Action:
public ActionResult Index()
{
ExportAssetsViewModel expViewMod = new ExportAssetsViewModel();
return View(expViewMod);
}
Index View:
@model InventoryTracker.Models.ExportAssetsViewModel
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Export</h2>
<p>Please select which Asset fields to Export to Excel:</p>
@using (Html.BeginForm("ExportUsingEPPlus", "Export", FormMethod.Post))
{
@Html.ListBoxFor(m => m.SelectedFields, new MultiSelectList(Model.ListOfExportFields, "Key", "Value"), new { @class = "form-control", style = "height: 250px;" })
<br />
<input type="submit" value="ExportUsingEPPlus" />
}
Index View - Rendered HTML:
<h2>Export</h2>
<p>Please select which Asset fields to Export to Excel:</p>
<form action="/Export/ExportUsingEPPlus" method="post"><select class="form-control" id="SelectedFields" multiple="multiple" name="SelectedFields" style="height: 250px;"><option value="1">Model</option>
<option value="2">Manufacturer</option>
<option value="3">Type</option>
<option value="4">Location</option>
<option value="5">Vendor</option>
<option value="6">Status</option>
<option value="7">ip_address</option>
<option value="8">mac_address</option>
<option value="9">note</option>
<option value="10">owner</option>
<option value="11">cost</option>
<option value="12">po_number</option>
<option value="13">description</option>
<option value="14">invoice_number</option>
<option value="15">serial_number</option>
<option value="16">asset_tag_number</option>
<option value="17">acquired_date</option>
<option value="18">disposed_date</option>
<option value="19">verified_date</option>
<option value="20">created_date</option>
<option value="21">created_by</option>
<option value="22">modified_date</option>
<option value="23">modified_by</option>
</select> <br />
<input type="submit" value="ExportUsingEPPlus" />
</form>
Now what I'm attempting to do is use the EPPlus library to Export all values in my INV_Assets
table for the selected fields in my MultiSelectList
to Excel.
ExportController - ExportUsingEPPlus():
[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();
}
// INVALID - Need to query table INV_Assets for all values of selected fields and insert into appropriate columns.
if (exportFields.Count() > 0)
{
ws.Cells["A2"].LoadFromCollection(exportFields);
}
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);
For my current code, if I select [ip_address]
, [mac_address]
, [note]
, [owner]
, and [cost]
in my MultiSelectList
I get the following output verbatim in my Excel Sheet:
[ip_address]
[mac_address]
[note]
[owner]
[cost]
How do I query my INV_Assets
table to insert all the data values for the selected fields into the appropriate columns?
EDIT:
This is my INV_Assets
Model I'm attempting to query using LINQ. The suggestion for THIS seems promising, but I'm not quite sure how to set it up using my own fields?
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using GridMvc.DataAnnotations;
using System.Web.Mvc;
using InventoryTracker.Models;
namespace InventoryTracker.Models
{
[GridTable(PagingEnabled = true, PageSize = 30)]
public class INV_Assets
{
// Setting GridColumn Annotations allows you to use AutoGenerateColumns on view to auto create the Grid based on the model.
public int Id { get; set; }
public int Model_Id { get; set; }
[ForeignKey("Model_Id")]
public virtual INV_Models Model { get; set; }
[Required]
public int Manufacturer_Id { get; set; }
[ForeignKey("Manufacturer_Id")]
public virtual INV_Manufacturers Manufacturer { get; set; }
[Required]
public int Type_Id { get; set; }
[ForeignKey("Type_Id")]
public virtual INV_Types Type { get; set; }
[Required]
public int Location_Id { get; set; }
[ForeignKey("Location_Id")]
public virtual INV_Locations Location { get; set; }
public int Vendor_Id { get; set; }
[ForeignKey("Vendor_Id")]
public virtual INV_Vendors Vendor { get; set; }
[Required]
public int Status_Id { get; set; }
[ForeignKey("Status_Id")]
public virtual INV_Statuses Status { get; set; }
public string ip_address { get; set; }
public string mac_address { get; set; }
[DataType(DataType.MultilineText)]
public string note { get; set; }
public string owner { get; set; }
//[DataType(DataType.Currency)]
//[DisplayFormat(DataFormatString="{0:C}", ApplyFormatInEditMode=true)]
[DisplayFormat(DataFormatString = "{0:#,###0.00}", ApplyFormatInEditMode=true)]
public decimal cost { get; set; }
public string po_number { get; set; }
[DataType(DataType.MultilineText)]
public string description { get; set; }
public int invoice_number{ get; set; }
[Required]
public string serial_number { get; set; }
[Required]
public string asset_tag_number { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? acquired_date { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? disposed_date { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime? verified_date { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime created_date { get; set; }
[Required]
public string created_by { get; set; }
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime? modified_date { get; set; }
public string modified_by { get; set; }
// Flag to specify if item is available? (Not signed out, not auctioned, recycled, etc.)
//public bool available { get; set; }
}
}
EDIT2:
I believe I got the right file as mentioned in I need to select particular column based on check box list. That solution says to get DynamicLibrary.cs, but in the download all I found was Dynamic.cs? In VS2013 I clicked on my Project and added a new class called DynamicLibrary.cs
. I then copy/pasted the contents from the downloaded file to this new class file.
This allowed me to reference using System.Linq.Dynamic
.
Now however I think I've added the example setup in the wrong place? This is how my ExportController
currently stands with the DynamicColumns
code towards the bottom. The last section public IQueryable DynamicSelectionColumns()
currently has not been modified -- IQueryable
, TrackerDataContext()
and DynamicColumns()
are all flagged as errors currently.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using InventoryTracker.DAL;
using OfficeOpenXml;
using InventoryTracker.Models;
using System.Linq.Dynamic;
namespace InventoryTracker.Controllers
{
public class ExportController : Controller
{
InventoryTrackerContext _db = new InventoryTrackerContext();
// GET: Export
public ActionResult Index()
{
ExportAssetsViewModel expViewMod = new ExportAssetsViewModel();
return View(expViewMod);
}
public ActionResult Export()
{
GridView gv = new GridView();
gv.DataSource = _db.INV_Assets.ToList();
gv.DataBind();
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=InventoryAssets-" + DateTime.Now + ".xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
return RedirectToAction("StudentDetails");
}
[HttpPost]
public ActionResult ExportUsingEPPlus(ExportAssetsViewModel model)
{
//FileInfo newExcelFile = new FileInfo(output);
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();
}
// INVALID - Need to query table INV_Assets for all values of selected fields and insert into appropriate columns.
if (exportFields.Count() > 0)
{
var exportAssets = from ia in _db.INV_Assets
select new {
ia.ip_address,
}
ws.Cells["A2"].LoadFromCollection(exportFields);
}
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);
}
}
public class DynamicColumns : INV_Assets
{
//public int Id { get; set; }
//public int Model_Id { get; set; }
public virtual INV_Models Model { get; set; }
//public int Manufacturer_Id { get; set; }
public virtual INV_Manufacturers Manufacturer { get; set; }
//public int Type_Id { get; set; }
public virtual INV_Types Type { get; set; }
//public int Location_Id { get; set; }
public virtual INV_Locations Location { get; set; }
//public int Vendor_Id { get; set; }
public virtual INV_Vendors Vendor { get; set; }
//public int Status_Id { get; set; }
public virtual INV_Statuses Status { get; set; }
public string ip_address { get; set; }
public string mac_address { get; set; }
public string note { get; set; }
public string owner { get; set; }
public decimal cost { get; set; }
public string po_number { get; set; }
public string description { get; set; }
public int invoice_number { get; set; }
public string serial_number { get; set; }
public string asset_tag_number { get; set; }
public DateTime? acquired_date { get; set; }
public DateTime? disposed_date { get; set; }
public DateTime? verified_date { get; set; }
public DateTime created_date { get; set; }
public string created_by { get; set; }
public DateTime? modified_date { get; set; }
public string modified_by { get; set; }
}
public enum EnumTasks
{
Model = 1,
Manufacturer = 2,
Type = 3,
Location = 4,
Vendor = 5,
Status = 6,
ip_address = 7,
mac_address = 8,
note = 9,
owner = 10,
cost = 11,
po_number = 12,
description = 13,
invoice_number = 14,
serial_number = 15,
asset_tag_number = 16,
acquired_date = 17,
disposed_date = 18,
verified_date = 19,
created_date = 20,
created_by = 21,
modified_date = 22,
modified_by = 23
}
public IQueryable DynamicSelectionColumns()
{
using (var db = new TrackerDataContext())
{
string fieldIds = "," + "4,5,3,2,6,17,11,12" + ",";
var taskColum = Enum.GetValues(typeof(EnumTasks)).Cast<EnumTasks>().Where(e => fieldIds.Contains("," + ((int)e).ToString() + ",")).Select(e => e.ToString().Replace("_", ""));
string select = "new ( TaskId, " + (taskColum.Count() > 0 ? string.Join(", ", taskColum) + ", " : "") + "Id )";
return db.Task.ToList().Select(t => new DynamicColumns() { Id = t.Id, TaskId = Project != null ? Project.Alias + "-" + t.Id : t.Id.ToString(), ActualTime = t.ActualTime, AssignedBy = t.AssignedBy.ToString(), AssignedDate = t.AssignedDate, AssignedTo = t.AssignedTo.ToString(), CreatedDate = t.CreatedDate, Details = t.Details, EstimatedTime = t.EstimatedTime, FileName = t.FileName, LogWork = t.LogWork, Module = t.Module != null ? t.Module.Name : "", Priority = t.Priority != null ? t.Priority.Name : "", Project = t.Project != null ? t.Project.Name : "", ResolveDate = t.ResolveDate, Status = t.Status != null ? t.Status.Name : "", Subject = t.Subject, TaskType = t.TaskType != null ? t.TaskType.Type : "", Version = t.Version != null ? t.Version.Name : "" }).ToList().AsQueryable().Select(select);
}
}
}
Where/how do I set up this code to use Linq DynamicColumns()
?