如何导出到Excel?
我遵循这个指南 ,这是在另一篇文章中推荐这个,但我不能完全得到它的工作。 当试图redirect到/ LogModelsController / ExportData时,我得到一个404错误 – 据我了解 – 是我应该做的。
_LogPartialLayout.cshtml
@using (Html.BeginForm("ExportData", "LogModelsController", FormMethod.Post, new { enctype = "multipart/form-data" })) { <table class="table"> <tr> <th> @Html.ActionLink("message", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter }) </th> <th> @Html.ActionLink("timestamp", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter }) </th> <th> @Html.ActionLink("level", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter }) </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.message) </td> <td> @Html.DisplayFor(modelItem => item.timeStamp) </td> <td> @Html.DisplayFor(modelItem => item.level) </td> </tr> } </table> <input type="submit" name="Export" id="Export" value="Export" /> }
LogModelsController.cs
public ActionResult ExportData() { GridView gv = new GridView(); gv.DataSource = db.Log.ToList(); gv.DataBind(); Response.ClearContent(); Response.Buffer = true; Response.AddHeader("content-disposition", "attachment; filename=Loglist.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("~/LogModels/Index"); }
LogModel.cs
namespace ASDMVC.Models { [Table("Log")] public class LogModel { [Key] public long id { get; set; } public string message { get; set; } public DateTime timeStamp { get; set; } public string level { get; set; } public int customerId { get; set; } } public class LogDBContext:DbContext { public LogDBContext() : base("MySqlConnection") { } public DbSet <LogModel> Log { get; set; } } }
TD; DR:如何正确地将此表格导出到Excel?
奖金:它也可以和PagedList一起使用吗?
编辑3 – 解决
Index.cshtml:
@using (Html.BeginForm("ExportData", "LogModels")) { <input type="submit" name="Export" id="Export" value="Export" /> }
LogModelsController.cs
public ActionResult ExportData() { DataTable dataTable = GetData(); using (ExcelPackage package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("My Sheet"); //true generates headers ws.Cells["A1"].LoadFromDataTable(dataTable, true); var stream = new MemoryStream(); package.SaveAs(stream); string fileName = "myfilename.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; stream.Position = 0; return File(stream, contentType, fileName); } } public DataTable GetData() { DataTable dt = new DataTable(); if (ModelState.IsValid) { using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MySqlConnection"].ConnectionString)) { using (SqlCommand comm = conn.CreateCommand()) { comm.Parameters.AddWithValue("@val1", Session["myID"]); comm.CommandText = "SELECT * FROM dbo.Log WHERE CustomerId = @val1"; try { conn.Open(); dt.Load(comm.ExecuteReader()); } catch (SqlException e) { throw new Exception(e.ToString()); } } } } return dt; }
我在CommandText中犯了一个错误,并把“Id”而不是“CustomerId” – 它现在返回Excel文件中的整个表。
该指南不显示如何创build一个Excel文件,它显示了创build一个带有表格的HTML文件的破解。 Excel将尝试使用默认设置导入csv或HTML文件,这些设置通常可能会失败。
使用像EPPlus这样的库来创build一个合适的 Excel文件要容易得多 。 我确信这已经被回答了,但我找不到一个答案,显示如何从数据创build一个Excel文件,并为xlsx
文件设置适当的内容types 。
EPPlus提供LoadFromDataTable和LoadFromCollection方法来填充从DataTable或generics集合中提取的数据的Excel范围。 列或属性名称分别用作标题。
public ActionResult ExportData() { //Somehow, load data to a DataTable using (ExcelPackage package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("My Sheet"); //true generates headers ws.Cells["A1"].LoadFromDataTable(dataTable, true); var stream = new MemoryStream(); package.SaveAs(stream); string fileName = "myfilename.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; stream.Position = 0; return File(stream, contentType, fileName); } }
LoadFromDataTable或LoadFromCollection返回一个Excel单元格范围,可用于格式化表格:
var range=ws.Cells["A1"].LoadFromDataTable(table); range.Style.Numberformat.Format = "#,##0.00"; range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
您也可以将表格样式应用于范围,或将所需的样式传递给LoadFromDataTable
或LoadFromCollection
,例如:
ws.Cells[1,1].LoadFromDataTable(table, true, TableStyles.Light1);
库的Codeplex站点显示如何格式化结果,生成公式,数据透视表,处理表等
如果您想创build相对较大的工作表,保存到MemoryStream可能会成为问题。 一次写入相同的数据到MemoryStream,然后复制到输出,浪费周期。 尽pipe直接从MVC动作直接写入输出stream是个不错的做法。 诀窍是创build一个处理EPPlus包的自定义FileResult,并返回FileResult而不是File
返回的File
,例如:
public class EpplusResult:FileResult { public EpplusResult(ExcelPackage package) : base("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { if (package == null) { throw new ArgumentNullException("package"); } Package = package; } public ExcelPackage Package { get; private set; } protected override void WriteFile(HttpResponseBase response) { // grab chunks of data and write to the output stream Stream outputStream = response.OutputStream; using (Package) { Package.SaveAs(outputStream); } } }
它允许你写下面的动作:
public FileResult ExportData() { ExcelPackage package = new ExcelPackage(); var ws = package.Workbook.Worksheets.Add("My Sheet"); ... ws.Cells[1,1].LoadFromDataTable(table, true, TableStyles.Light1); return new EpplusResult(package){FileDownloadName = "SomeFile.xlsx"}; }
不要创build基于HTML的Excel文件,他们有这么多的问题。
保证使用一个紧凑的库,如epplus 。
public ActionResult ExportData() { using (ExcelPackage package = new ExcelPackage()) { var ws = package.Workbook.Worksheets.Add("LogMessages"); //Headers ws.Cells["A1"].Value = "Message"; ws.Cells["B1"].Value = "TimeStamp"; ws.Cells["C1"].Value = "Level"; var rowNumber=1; foreach (var log in DbContext.Log) { ws.Cells[rowNumber, 1].Value = vehicle.message; ws.Cells[rowNumber, 2].Value = vehicle.timeStamp; ws.Cells[rowNumber, 3].Value = vehicle.level; rowNumber++; } var stream = new MemoryStream(); package.SaveAs(stream); string fileName = "logMessags.xlsx"; string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; stream.Position = 0; return File(stream, contentType, fileName); } }
我用Panagiotis Kanavos代码结构来实现这个解决scheme
检查一下,这个库包含一个ExcelResult,它将自动创build过程,并通过调用Excel()方法像Json()一样发送Excel文件到客户端。