Related
As an overview I am attempting to add Export() functionality to my application -- allowing the user to specify certain model fields and only export the values in those fields by querying with LINQ and using the EPPlus library to Export. I am attempting to implement Dynamic LINQ functionality in my MVC5/EF Code-First application based on THIS example, but not having much luck so far.
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();
public static List<DynamicColumns> DynamicColumnsCollection = new List<DynamicColumns>();
[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);
}
//int cnt = 0;
//foreach(var column in exportFields)
for (int cnt = 0; cnt < 10; cnt++ )
{
DynamicColumnsCollection.Add(new DynamicColumns()
{
Id = cnt,
ip_address = "ip_address" + cnt,
mac_address = "mac_address" + cnt,
note = "note" + cnt,
owner = "owner" + cnt,
cost = "cost" + cnt,
po_number = "po_number" + cnt,
description = "description" + cnt,
invoice_number = "invoice_number" + cnt,
serial_number = "serial_number" + cnt,
asset_tag_number = "asset_tag_number" + cnt,
acquired_date = "acquired_date" + cnt,
disposed_date = "disposed_date" + cnt,
verified_date = "verified_date" + cnt,
created_date = "created_date" + cnt,
created_by = "created_by" + cnt,
modified_date = "modified_date" + cnt,
modified_by = "modified_by" + cnt
});
}
//var selectStatement = DynamicSelectionColumns(exportFields);
IQueryable collection = DynamicSelectionColumns(new List<string>() {
"id",
"owner",
"note"
});
// 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();
}
// Process data from [collectin] into Excel???
ws.Cells["A2"].LoadFromCollection(collection.ToString());
// ws.Cells["A2"].LoadFromCollection(selectStatement.ToString());
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 IQueryable DynamicSelectionColumns(List<string> fieldsForExport)
{
using (var db = new InventoryTrackerContext())
{
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("_", ""));
var taskColum = Enum.GetValues(typeof(EnumTasks)).Cast<EnumTasks>().Where(e => fieldIds.Contains("," + ((int)e).ToString() + ",")).Select(e => e.ToString());
////string select = "new ( TaskId, " + (taskColum.Count() > 0 ? string.Join(", ", taskColum) + ", " : "") + "Id )";
//string select = "new ( " + string.Join(", ", fieldsForExport) + ")";
////return db.INV_Assets.ToList().Select(t => new DynamicColumns() { Id = t.Id, TaskId = Project != null ? Project.Alias + "-" + t.Id : t.Id.ToString(),
if (!fieldsForExport.Any())
{
return null;
}
string select = string.Format("new ( {0} )", string.Join(", ", fieldsForExport.ToArray()));
var collection = DynamicColumnsCollection.Select(t => new DynamicColumns()
{
Id = t.Id,
//Manufacturer = Convert.ToString(t.Manufacturer.manufacturer_description),
//Type = t.Type.type_description,
//Location = t.Location.location_room,
//Vendor = t.Vendor.vendor_name,
//Status = t.Status.status_description,
ip_address = t.ip_address,
mac_address = t.mac_address,
note = t.note,
owner = t.owner,
cost = t.cost,
po_number = t.po_number,
description = t.description,
invoice_number = t.invoice_number,
serial_number = t.serial_number,
asset_tag_number = t.asset_tag_number,
acquired_date = t.acquired_date,
disposed_date = t.disposed_date,
verified_date = t.verified_date,
created_date = t.created_date,
created_by = t.created_by,
modified_date = t.modified_date,
modified_by = t.modified_by
}).ToList().AsQueryable().Select(select);
return collection;
}
}
}
public class DynamicColumns : INV_Assets
{
public string Model { get; set; }
public string Manufacturer { get; set; }
public string Type { get; set; }
public string Location { get; set; }
public string Vendor { get; set; }
public string 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 string cost { get; set; }
public string po_number { get; set; }
public string description { get; set; }
public string invoice_number { get; set; }
public string serial_number { get; set; }
public string asset_tag_number { get; set; }
public string acquired_date { get; set; }
public string disposed_date { get; set; }
public string verified_date { get; set; }
public string created_date { get; set; }
public string created_by { get; set; }
public string 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
}
//https://stackoverflow.com/questions/5796151/export-model-data-to-excel-mvc
//https://landokal.wordpress.com/2011/04/28/asp-net-mvc-export-to-excel-trick/
}
My code is exporting my selected columns values from my MultiSelectList on my View into Row 1 of the Excel spreadsheet, but I have something amiss with my dynamic linq querying as the data that gets output is simply the value 0 in A2:A180 no matter how many fields I specify for output.
Can anyone with more experience or who has used System.Linq.Dynamic weigh in on this?
Here is something that I am using for some time:
public class ExcelExportHelper
{
public static string ExcelContentType { get { return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; } }
public static DataTable ToDataTable<T>(List<T> data)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
//table.Columns.Add(prop.Name, prop.PropertyType);
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); // to avoid nullable types
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}
public static byte[] ExportExcel(DataTable dt, string Heading = "", params string[] IgnoredColumns)
{
byte[] result = null;
using (ExcelPackage pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Exported Data");
int StartFromRow = String.IsNullOrEmpty(Heading) ? 1: 3;
// add the content into the Excel file
ws.Cells["A" + StartFromRow].LoadFromDataTable(dt, true);
// autofit width of cells with small content
int colindex = 1;
foreach (DataColumn col in dt.Columns)
{
ExcelRange columnCells = ws.Cells[ws.Dimension.Start.Row, colindex, ws.Dimension.End.Row, colindex];
int maxLength = columnCells.Max(cell => cell.Value.ToString().Count());
if (maxLength < 150)
ws.Column(colindex).AutoFit();
colindex++;
}
// format header - bold, yellow on black
using (ExcelRange r = ws.Cells[StartFromRow, 1, StartFromRow, dt.Columns.Count])
{
r.Style.Font.Color.SetColor(System.Drawing.Color.Yellow);
r.Style.Font.Bold = true;
r.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
r.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.Black);
}
// format cells - add borders
using (ExcelRange r = ws.Cells[StartFromRow + 1, 1, StartFromRow + dt.Rows.Count, dt.Columns.Count])
{
r.Style.Border.Top.Style = ExcelBorderStyle.Thin;
r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
r.Style.Border.Left.Style = ExcelBorderStyle.Thin;
r.Style.Border.Right.Style = ExcelBorderStyle.Thin;
r.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);
r.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);
}
// removed ignored columns
for (int i = dt.Columns.Count - 1; i >= 0; i--)
{
if (IgnoredColumns.Contains(dt.Columns[i].ColumnName))
{
ws.DeleteColumn(i + 1);
}
}
// add header and an additional column (left) and row (top)
if (!String.IsNullOrEmpty(Heading))
{
ws.Cells["A1"].Value = Heading;
ws.Cells["A1"].Style.Font.Size = 20;
ws.InsertColumn(1, 1);
ws.InsertRow(1, 1);
ws.Column(1).Width = 5;
}
result = pck.GetAsByteArray();
}
return result;
}
public static byte[] ExportExcel<T>(List<T> data, string Heading = "", params string[] IgnoredColumns)
{
return ExportExcel(ToDataTable<T>(data), Heading, IgnoredColumns);
}
}
With these you can export a list of objects or a datatable to an Excel file. Additionally, you can specify a header and columns/properties to be ignored (like ID). Also, there are some formatting added and also small cells will auto fit in width.
Using this code you can use this in your controller action that is expecting a FileResult:
byte[] filecontent = ExcelExportHelper.ExportExcel(...);
return File(filecontent, ExcelExportHelper.ExcelContentType, "FileName.xlsx");
I hope this helps!
As an overview I am attempting to add Export() functionality to my application -- allowing the user to specify certain model fields and only export the values in those fields by querying with LINQ and using the EPPlus library to Export. I am attempting to implement Dynamic LINQ functionality in my MVC5/EF Code-First application based on THIS example, but seem to be missing some things to get it working or not understanding something.
First I added a new class file to my main project folder called DynamicLibrary.cs. When I download the .zip HERE, I "believe" the code I wanted was the Dynamic.cs file code which I copied into DynamicLibrary.cs in my project. Doing this allowed me to reference using System.Linq.Dynamic in my project.
Now I'm stuck trying to figure out how to setup the rest for Dynamic LINQ.
In my ExportController within the namespace InventoryTracker.Controllers {} but outside the public class ExportController : Controller { } I added the example code based upon the fields in my INV_Assets model I am attempting to Export:
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);
}
}
}
I am not 100% sure this is set up in the right location. The last method below has 5 errors:
IQueryable - Expected class, delegate, enum, interface, or struct.
InventoryTrackerContext - Expected class, delegate, enum, interface, or struct.
DynamicColumns() - Expected class, delegate, enum, interface, or struct.
Closing } for public IQueryable DynamicSelectionColumns() - Type or namespace definition, or end-of-file expected.
Closing } for namespace InventoryTracker.Controllers - Type or namespace definition, or end-of-file expected.
public IQueryable DynamicSelectionColumns()
{
using (var db = new InventoryTrackerContext())
{
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);
}
}
Can anyone with more experience in this kind of thing weigh-in? I also checked out ScottGu's Blog, but seem to be missing or not understanding something.
EDIT:
REDACTED FOR SPACE
EDIT2:
Using the return from DynamicSelectionColumns() into my variable selectStatement, I have the following coded:
public IQueryable DynamicSelectionColumns(List<string> fieldsForExport)
{
using (var db = new InventoryTrackerContext())
{
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 )";
string select = "new ( " + string.Join(", ", fieldsForExport) + ")";
//return db.INV_Assets.ToList().Select(t => new DynamicColumns() { Id = t.Id, TaskId = Project != null ? Project.Alias + "-" + t.Id : t.Id.ToString(),
return db.INV_Assets.ToList().Select(t => new DynamicColumns() {
Id = t.Id,
Manufacturer = Convert.ToString(t.Manufacturer.manufacturer_description),
Type = t.Type.type_description,
Location = t.Location.location_room,
Vendor = t.Vendor.vendor_name,
Status = t.Status.status_description,
ip_address = t.ip_address,
mac_address = t.mac_address,
note = t.note,
owner = t.owner,
//Module = t.Module != null ? t.Module.Name : "",
cost = t.cost,
po_number = t.po_number,
description = t.description,
invoice_number = t.invoice_number,
serial_number = t.serial_number,
asset_tag_number = t.asset_tag_number,
acquired_date = t.acquired_date,
disposed_date = t.disposed_date,
verified_date = t.verified_date,
created_date = t.created_date,
created_by = t.created_by,
modified_date = t.modified_date,
modified_by = t.modified_by
}).ToList().AsQueryable().Select(select);
}
}
[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);
}
var selectStatement = DynamicSelectionColumns(exportFields);
// 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();
}
if (selectStatement.Count() > 0)
{
ws.Cells["A2"].LoadFromCollection(selectStatement.ToString());
}
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);
}
This yields an Excel output with columns [ip_address], [mac_address], [note], [owner], and [cost] (the fields I selected), but no data. Instead of data, I get 251 rows of 0 in column A and nothing in the others.
How do I implement the dynamic select query results into my Excel spreadsheet?
EDIT3:
Attempting ThulasiRam's suggestion (ExportController below):
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();
public static List<DynamicColumns> DynamicColumnsCollection = new List<DynamicColumns>();
[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);
}
int cnt = 0;
foreach(var column in exportFields)
{
DynamicColumnsCollection.Add(new DynamicColumns()
{
Id = cnt,
ip_address = "ip_address" + cnt,
mac_address = "mac_address" + cnt,
note = "note" + cnt,
owner = "owner" + cnt,
cost = "cost" + cnt,
po_number = "po_number" + cnt,
description = "description" + cnt,
invoice_number = "invoice_number" + cnt,
serial_number = "serial_number" + cnt,
asset_tag_number = "asset_tag_number" + cnt,
acquired_date = "acquired_date" + cnt,
disposed_date = "disposed_date" + cnt,
verified_date = "verified_date" + cnt,
created_date = "created_date" + cnt,
created_by = "created_by" + cnt,
modified_date = "modified_date" + cnt,
modified_by = "modified_by" + cnt
});
}
//var selectStatement = DynamicSelectionColumns(exportFields);
IQueryable collection = DynamicSelectionColumns(new List<string>() {
"id",
"owner",
"note"
});
// 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();
}
ws.Cells["A2"].LoadFromCollection(collection.ToString());
// ws.Cells["A2"].LoadFromCollection(selectStatement.ToString());
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 IQueryable DynamicSelectionColumns(List<string> fieldsForExport)
{
using (var db = new InventoryTrackerContext())
{
if (!fieldsForExport.Any())
{
return null;
}
string select = string.Format("new ( {0} )", string.Join(", ", fieldsForExport.ToArray()));
var collection = DynamicColumnsCollection.Select(t => new DynamicColumns()
{
Id = t.Id,
//Manufacturer = Convert.ToString(t.Manufacturer.manufacturer_description),
//Type = t.Type.type_description,
//Location = t.Location.location_room,
//Vendor = t.Vendor.vendor_name,
//Status = t.Status.status_description,
ip_address = t.ip_address,
mac_address = t.mac_address,
note = t.note,
owner = t.owner,
//Module = t.Module != null ? t.Module.Name : "",
cost = t.cost,
po_number = t.po_number,
description = t.description,
invoice_number = t.invoice_number,
serial_number = t.serial_number,
asset_tag_number = t.asset_tag_number,
acquired_date = t.acquired_date,
disposed_date = t.disposed_date,
verified_date = t.verified_date,
created_date = t.created_date,
created_by = t.created_by,
modified_date = t.modified_date,
modified_by = t.modified_by
}).ToList().AsQueryable().Select(select);
return collection;
}
}
public class DynamicColumns : INV_Assets
{
public string Model { get; set; }
public string Manufacturer { get; set; }
public string Type { get; set; }
public string Location { get; set; }
public string Vendor { get; set; }
public string 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 string cost { get; set; }
public string po_number { get; set; }
public string description { get; set; }
public string invoice_number { get; set; }
public string serial_number { get; set; }
public string asset_tag_number { get; set; }
public string acquired_date { get; set; }
public string disposed_date { get; set; }
public string verified_date { get; set; }
public string created_date { get; set; }
public string created_by { get; set; }
public string 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
}
What I can't figure out is where to put this relevant piece of code from their suggestion (or set it up) within my MVC application:
static void Main(string[] args)
{
IQueryable collection = DynamicSelectionColumns(new List<string>() { "id", "name" });
Console.ReadLine();
}
Any thoughts? I'm not sure how to structure the static Program() or Main() used in the example for my MVC app. In my code listed above (should I select just the note/owner field), I receive an output Excel sheet with "note" in A1, "owner" in B1, and then just the number 0 in cells A2:A180...?
The errors you're getting has nothing to do with linq or the other libraries you imported into your project.
You're declaring the function DynamicSelectionColumns in the namespace, not in the ExportController class.
After your Edit:
if your exportFields is already a list of Task columns, you can simply pass that list to DynamicSelectionColumns and have this inside:
string select = "new ( " + string.Join(", ", exportFields) + ")";
After Edit2:
Replace
ws.Cells["A2"].LoadFromCollection(selectStatement.ToString());
with
ws.Cells["A2"].LoadFromCollection(selectStatement, false);
After Edit3:
After this trial and error approaches, I decided to indeed lookup the EPPlus library you mentioned. I found out that you don't need any of this DynamicQuery. You can specify into LoadFromCollection the fields you want to show.
I didn't get to compile this (because it's your code) but It worked on my machine with fake data.
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.Reflection;
using OfficeOpenXml.Table;
namespace InventoryTracker.Controllers
{
public class ExportController : Controller
{
private InventoryTrackerContext _db = new InventoryTrackerContext();
[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();
}
var membersToShow = typeof(INV_Asset).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);
}
}
}
1. TaskId property not exist in DynamicColumns class.
2. Remove .Replace("_", "") from
var taskColum = Enum.GetValues(typeof(EnumTasks)).Cast<EnumTasks>().Where(e => fieldIds.Contains("," + ((int)e).ToString() + ",")).Select(e => e.ToString().Replace("_", ""));
3.exportFields.Count should be > 0.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
namespace Dynamic
{
public class Program
{
public static List<DynamicColumns> DynamicColumnsCollection = new List<DynamicColumns>();
static Program()
{
for (int i = 0; i < 10; i++)
{
DynamicColumnsCollection.Add(new DynamicColumns() { Id = i, Name = "Name" + i, ip_address = "ip_" + i });
}
}
static void Main(string[] args)
{
IQueryable collection = DynamicSelectionColumns(new List<string>() { "id", "name" });
Console.ReadLine();
}
public class DynamicColumns
{
public int Id { get; set; }
public string Name { get; set; }
public string ip_address { get; set; }
}
public static IQueryable DynamicSelectionColumns(List<string> fieldsForExport)
{
if (!fieldsForExport.Any())
return null;
string select = string.Format("new ( {0} )", string.Join(", ", fieldsForExport.ToArray()));
var collection = DynamicColumnsCollection.Select(t => new DynamicColumns()
{
Id = t.Id,
Name = t.Name,
ip_address = t.ip_address,
}).ToList().AsQueryable().Select(select);
return collection;
}
}
}
Further any problem let me know.
Regards,
Ram.S
I am running into an issue when manipulating strings when cleaning up a text file before converting it into a CSV.
my file looks like this..
^Smith, Joe
ACME Inc.
66 Main St, #1517
Ottawa, ON
Ottawa ON K1A 0P4
Phone: (613) 123-4567
^Jefferson, Bubba
Farmers Federation
Farmer Unit
50 Otherway Drive
North Bay ON P1B 0A4
Phone: (705) 123-4567
Fax: (705) 234-5678
^McStabber, Stabby
66 backwards St
Unit #412
Ottawa ON K1A 0P4
Phone: (613) 123-4567
^Weaver, Basket
Old and New
470 bamboo St E, Unit 63
Belleville ON K8N 1G1
Phone: (613) 123-4567 Ext. 890
^Smith, Joe
ACME Inc.
66 Main St, #1517
Ottawa, ON
Ottawa ON K1A 0P4
Phone: (613) 123-4567
When You look at Stabby McStabber, it is laid out properly. Bubba and Basket are examples of the problem I am having.
Basket for some reason when I encounter a record like that the address will populate in the city, this causes me issues when I convert the CSV to a datatable because of the shift of the cells.
The Bubba record type issue I can figure out what to do.
I know it has to do with how I am extracting the information, just don't know how to fix it when I run into those lines.
Here is the code that I wrote to take this text file and write it to a CSV.
public class PIADATA
{
public string LastName { get; set; }
public string FirstName { get; set; }
public string StreetAddress { get; set; }
public string Suite { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public string Telephone { get; set; }
public string Alternate { get; set; }
public string Fax { get; set; }
}
static void Main(string[] args)
{
PIADATA pia = new PIADATA();
string strFileContent;
List<string> NewData = new List<string>();
List<string> lstFinishedData = new List<string>();
string[] myDataString;
StringBuilder sb = new StringBuilder();
#region Read File to a List
using (StreamReader rd = new StreamReader(#"C:\TestData2.txt"))
{
while ((strFileContent = rd.ReadLine()) != null)
{
if (strFileContent.Contains("Details ยป"))
{
int nStartOf = strFileContent.IndexOf("Details");
int nEndOf = strFileContent.LastIndexOf(";");
NewData.Add(strFileContent.Remove(nStartOf - 6));
}
else
NewData.Add(strFileContent);
}
}
#endregion
foreach (string item in NewData)
{
if (item.Contains("^"))
{
if (pia != null)
{
//if (pia.Suite == pia.City || pia.Suite == pia.PostalCode) pia.Suite = "";
sb.Append(pia.LastName + "," +
pia.FirstName + "," +
pia.StreetAddress + "," +
pia.Suite + "," +
pia.City + "," +
pia.PostalCode + "," +
pia.Telephone + "," +
pia.Fax);
sb.AppendLine();
}
pia.LastName = string.Empty;
pia.FirstName = string.Empty;
pia.StreetAddress = string.Empty;
pia.Suite = string.Empty;
pia.City = string.Empty;
pia.PostalCode = string.Empty;
pia.Telephone = string.Empty;
pia.Fax = string.Empty;
string[] strReplaceName = item.Split(',');
pia.LastName = strReplaceName[0].Replace("^", "").Trim().ToString();
pia.FirstName = strReplaceName[1].Trim().ToString();
}
#region Name, Address
//if (item.Contains("^")) pia.FirstName = item;
if (Regex.IsMatch(item, #"^\d"))
{
pia.StreetAddress = item.Replace(",", "");
// Seperate Address if it contains Unit or Suite
#region Seperate Address Line
Match matchUnit = Regex.Match(item, #"[Unit]", RegexOptions.IgnoreCase);
if (item.Contains("Unit") || item.Contains("Suite"))
{
if (item.Contains("Unit"))
{
int nStart = item.IndexOf("Unit") + "Unit".Length;
pia.Suite = item.Substring(nStart);
if (Regex.IsMatch(item, #"^\d"))
{
//int a = item.Replace(item.Substring(nStart), string.Empty).Trim().Length;
string a = item;
int b = nStart;
if (a.Length - b == 0) pia.StreetAddress = item;
else
pia.StreetAddress = item.Replace(item.Substring(nStart), "").Trim();
//if(item.Replace(item.Substring(nStart), string.Empty).Trim() == "0") pia.StreetAddress = item;
}
}
if (item.Contains("Suite"))
{
int nStart = item.IndexOf("Suite") + "Suite".Length;
pia.Suite = item.Substring(nStart);
if (Regex.IsMatch(item, #"^\d")) pia.StreetAddress = item.Replace(item.Substring(nStart), "").Replace("Suite", "").Trim();
}
}
#endregion
}
#endregion
#region City and Postal Code
// Get the postal code
Match matchPostalCode = Regex.Match(item, #"[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1}[ -] *\d{1}[A-Z]{1}\d{1}$", RegexOptions.IgnoreCase);
if (matchPostalCode.Success)
{
pia.PostalCode = matchPostalCode.ToString();
// Get City
if (item.Contains(matchPostalCode.ToString()) && item.Contains("ON"))
{
string a = ", ON";
string b = "ON";
string c = " ON";
if (item.Contains(a)) pia.City = item.Replace(pia.PostalCode, "").Replace(a, "").Trim();
if (item.Contains(b)) pia.City = item.Replace(pia.PostalCode, "").Replace(b, "").Trim();
if (item.Contains(c)) pia.City = item.Replace(pia.PostalCode, "").Replace(c, "").Trim();
}
}
#endregion
#region Phone, Suite Number, Fax
if (item.Contains("Phone")) pia.Telephone = item.Remove(0, 7);
if (item.Contains("Suite") || item.Contains("Unit")) pia.Suite = item.Replace("Suite", "").Replace("Unit", "").Trim();
if (item.Contains("Fax")) pia.Fax = item;
#endregion
}
string g = sb.ToString();
File.WriteAllText(#"C:\Meh.csv", g);
}
I have a list of contacts in XML file.
Each contact have a few properties and mdpr:connection in it.
Connection is separate object.
I read this list and get all contacts to a list with standard proeprties but how to map this Connection to object.
<?xml version="1.0" encoding="UTF-8"?>
<mdpr:Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mdpr="http://...">
<mdpr:contactList>
<mdpr:contact ID="{123456}" classID="Customer">
<mdpr:Name>data1</mdpr:Name>
<mdpr:TransportCode>data2</mdpr:TransportCode>
<mdpr:connection connectionIndex="0" fromID="{12345}" toID="{123456}">
<mdpr:status>1-5</mdpr:status>
<mdpr:startDate>2012-03-13T10:23:00Z</mdpr:startDate>
<mdpr:endDate>2013-03-13T13:44:00Z</mdpr:endDate>
</mdpr:connection>
</mdpr:contact>
</mdpr:contactList>
...
Classes:
public class Contact
{
public string Name { get; set; }
public string TransportCode { get; set; }
public Connection Connection { get; set; }
public TransportPlan()
{
this.Connection = new Connection();
}
}
public class Connection
{
public string status{ get; set; }
public string startDate{ get; set; }
public string endDate { get; set; }
}
Code to read data:
XNamespace mdpr = "http://...";
var contacts = from c in xdoc.Root.Element(mdpr + "contactList")
.Elements(mdpr + "contact")
select new Contact {
TransportCode = (string)c.Element(mdpr + "TransportCode"),
Name = (string)c.Element(mdpr + "Name")
};
So the question is how to read mdpr:connection?
You can access the elements directly by adding another '.Element'. I added a variable for better readability.
var contacts = from c in xdoc.Element(mdpr + "Data")
.Element(mdpr + "contactList")
.Elements(mdpr + "contact")
let contact = c
let connection = contact.Element(mdpr + "connection")
select new Contact
{
TransportCode = (string)contact.Element(mdpr + "TransportCode"),
Name = (string)contact.Element(mdpr + "Name"),
Connection = new Connection
{
status = (string)connection.Element(mdpr + "status"),
startDate = (string) connection.Element(mdpr + "startDate"),
endDate = (string)connection.Element(mdpr + "endDate"),
},
};
If you want to allow multiple connections (in order to make the scenario more complex)
public class Contact
{
public string Name { get; set; }
public string TransportCode { get; set; }
public List<Connection> Connections { get; set; }
}
Code to parse multiple connections
var contacts = from c in xdoc.Element(mdpr + "Data")
.Element(mdpr + "contactList")
.Elements(mdpr + "contact")
let contact = c
let connections = contact.Elements(mdpr + "connection")
select new Contact
{
TransportCode = (string)contact.Element(mdpr + "TransportCode"),
Name = (string)contact.Element(mdpr + "Name"),
Connections = connections.Select( connection =>
new Connection
{
status = (string)connection.Element(mdpr + "status"),
startDate = (string) connection.Element(mdpr + "startDate"),
endDate = (string)connection.Element(mdpr + "endDate"),
}).ToList(),
};
I have a check box list in that user can check or uncheck the check box.
Based on the selected check box I used to store that value by comma separated. Now the problem is based on selected check box I need to get that particular column alone. in "select"**
db.Tasks.OrderBy(t => t.CreatedDate).ToList()
.Select(t => new {
Id = t.Id,
PriorityId = t.ProjectId,
Priority = t.Priority,
StatusId = t.StatusId,
Status = t.Status,
EstimatedTime = t.EstimatedTime,
ActualTime = t.ActualTime,
Subject = t.Subject,
FileName = t.FileName,
AssignedTo = t.AssignedTo,
Project = t.Project
}).ToList();
if i select in check box list ActualTime, Subject, it should be like
db.Tasks.OrderBy(t => t.CreatedDate).ToList()
.Select(t => new {
Id = t.Id,
ActualTime = t.ActualTime,
Subject = t.Subject
}).ToList();
if i select in check box list Subject, FileName, AssignedTo, it should be like
db.Tasks.OrderBy(t => t.CreatedDate).ToList()
.Select(t => new {
Id = t.Id,
Subject = t.Subject,
FileName = t.FileName,
AssignedTo = t.AssignedTo
}).ToList();
the select will be dynamic based on selected check box list.
add DynamicLibrary.cs to your project.
You can get it from this link . It's a zip file that contains the dynamic link source. It's not a dll.
Originally posted on ScottGu's blog here.
for reference see this stack overflow link .
using System.Linq.Dynamic;
public class DynamicColumns : BaseEntity
{
public string User { get; set; }
public string TaskId { get; set; }
public string Project { get; set; }
public string Priority { get; set; }
public string TaskType { get; set; }
public string Version { get; set; }
public string Module { get; set; }
public string Subject { get; set; }
public string Details { get; set; }
public string FileName { get; set; }
public string Status { get; set; }
public string AssignedBy { get; set; }
public string AssignedTo { get; set; }
public int ActualTime { get; set; }
public int LogWork { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime AssignedDate { get; set; }
public DateTime ResolveDate { get; set; }
public int EstimatedTime { get; set; }
}
public enum EnumTasks
{
User = 1,
Project = 2,
Priority = 3,
TaskType = 4,
Version = 5,
Module = 6,
Subject = 7,
Details = 8,
Status = 9,
Assigned_By = 10,
Assigned_To = 11,
Created_Date = 12,
Assigned_Date = 13,
Resolve_Date = 14,
Estimated_Time = 15,
Actual_Time = 16,
LogWork = 17
}
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);
}
}