我有一个MVC5 / Code-First应用程序,我正在使用Entity Framework进行开发。目前,我正在尝试添加导出到Excel功能,以动态输出我的INV_Assets
模型的用户选定属性。使用EPPlus Libary和Linq.Dynamic
我设法将我的数据导出到excel,但不太正确。
我已经将标题导出到第1行,但我仍然难以将数据导出。目前我所选字段的数据都是相同的,但是每个值都作为一个长字符串导出到它自己在A列中的行。例如,如果我选择以下字段(Status,ip_address,mac_address,note,所有者,成本,po_number和描述)我得到以下内容:
第1行:[Status][ip_address][mac_address][note][owner][cost][po_number][description]
第2行:[{Status=SIGNEDOUT, ip_address=10.10.121.25, mac_address=10.10.134.11, note=, owner=John Smith, cost=35.00, po_number=G348, description=This is a description of the item.}][][][][][][][]
以下是我目前在Excel中获得的输出的视觉效果:
当我在VS2013中将IQueryable
变量(selectStatement
)设置为Watch变量时,我可以深入查看内容,但我无法弄清楚如何访问这些内容单独代码:
目前我使用我的IQueryable
并通过EPPlus LoadFromCollection()
方法将其加载到Excel中,但如果我能弄清楚如何访问IQueryable
的个别内容,我可以设置一些计数器和循环来适当地设置我想要的单元格而不是一切都倾倒到ColumnA中。
有人可以协助吗?我的ExportController
的完整代码如下:
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);
}
IQueryable 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();
}
// Place contents of IQueryable into Excel -- currently dumps selected value for each record into rows with all values for the row as a long string in ColumnA
if (selectStatement.Count() > 0)
{
ws.Cells["A2"].LoadFromCollection(selectStatement.Cast<object>(), true);
}
int cnt = 20;
foreach (var item in selectStatement)
{
ws.Cells["A" + cnt].LoadFromCollection(selectStatement.Cast<object>(), false);
cnt++;
}
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("_", ""));
//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);
}
}
}
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 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
}
答案 0 :(得分:0)
您在非标头单元格中获得的输出:
Status = SIGNEDOUT,ip_address = 10.10.121.25,mac_address = 10.10.134.11,note =,owner = John Smith,cost = 35.00,po_number = G348,description =这是项目的描述。
看起来像用property=value
表示的对象,用逗号分隔。我猜想对象的ToString()方法被覆盖并创建了那个输出。
因为您要将强类型对象强制转换为System.Object
selectStatement.Cast<object>()
这可能是EPPlus最好的。
尽量不要将其强制转换为System.Object,例如
ws.Cells["A2"].LoadFromCollection(selectStatement, true);
这是一篇文章,展示了LoadFromCollection的正确使用
http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt5
<强>更新强>
错误
无法从用法推断出方法'OfficeOpenXml.ExcelRangeBase.LoadFromCollection(System.Collection.Generic.IE numerable,bool)'的类型参数。尝试明确指定类型参数。
告诉您需要指定查询返回的实际类型(而不是指定object
)。
ws.Cells["A2"].LoadFromCollection(selectStatement.Cast<DynamicColumns>(), true);