Wie exportiere ich nach Excel?

Ich folgte diesem Leitfaden, der in einem anderen Beitrag empfohlen wurde, aber ich kann es nicht richtig zum Laufen bringen. Ich bekomme einen Fehler 404, wenn ich versuche, nach / LogModelsController / ExportData umzuleiten, was – wie ich es verstanden habe – das war, was ich tun sollte.

_LogPartialLayout.cshtml

@using (Html.BeginForm("ExportData", "LogModelsController", FormMethod.Post, new { enctype = "multipart/form-data" })) {  @foreach (var item in Model) {  } 
@Html.ActionLink("message", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter }) @Html.ActionLink("timestamp", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter }) @Html.ActionLink("level", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })
@Html.DisplayFor(modelItem => item.message) @Html.DisplayFor(modelItem => item.timeStamp) @Html.DisplayFor(modelItem => item.level)
}

_LogPartialLayout.cshtml

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  Log { get; set; } } } 

TD; DR: Wie exportiere ich diese Tabelle korrekt nach Excel?

Bonus: functioniert es auch mit PagedList?


Bearbeiten 3 – Getriggers

Index.cshtml:

 @using (Html.BeginForm("ExportData", "LogModels")) {  } 

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; } 

Ich habe einen Fehler im CommandText gemacht und “Id” anstelle von “CustomerId” eingegeben – es gibt jetzt die gesamte Tabelle in der Excel-Datei zurück.

Die Anleitung zeigt nicht, wie man eine Excel-Datei erstellt, sie zeigt einen Hack, der eine HTML-Datei mit einer Tabelle erstellt. Excel versucht, CSV- oder HTML-Dateien mit Tabellen zu importieren, die Standardeinstellungen verwenden, die häufig fehlschlagen können.

Es ist viel einfacher, eine richtige Excel-Datei mit einer Bibliothek wie EPPlus zu erstellen. Ich bin mir sicher, dass dies bereits beantwortet wurde, aber ich kann keine Antwort finden, die zeigt, wie man eine Excel-Datei aus Daten erstellt und den richtigen Inhaltstyp für eine xlsx Datei xlsx .

EPPlus stellt die LoadFromDataTable-Methode und die LoadFromCollection-Methode bereit, um einen Excel-Bereich mit Daten aus einer DataTable- oder einer generischen Auflistung zu füllen. Die Spalten- oder Eigenschaftsnamen werden jeweils als Kopfzeilen verwendet.

 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 oder LoadFromCollection geben einen Excel-Zellbereich zurück, der zum Formatieren der Tabelle verwendet werden kann:

 var range=ws.Cells["A1"].LoadFromDataTable(table); range.Style.Numberformat.Format = "#,##0.00"; range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right; 

Sie können auch einen Tabellenstil auf den Bereich anwenden oder den gewünschten Stil an LoadFromDataTable oder LoadFromCollection , z.

 ws.Cells[1,1].LoadFromDataTable(table, true, TableStyles.Light1); 

Die Codeplex-Site der Bibliothek zeigt, wie das Ergebnis formatiert, Formeln generiert, Pivot-Tabellen erstellt, Tabellen behandelt werden usw.

Das Speichern in einem MemoryStream kann ein Problem darstellen, wenn Sie ein relativ großes Blatt erstellen möchten. Die gleichen Daten zweimal zu schreiben, einmal in den MemoryStream und dann in die Ausgabe zu kopieren, verschwendet Zyklen. Es ist jedoch eine schlechte Übung, direkt in den Ausgabe-Stream einer MVC-Aktion zu schreiben. Der Trick besteht darin, ein benutzerdefiniertes FileResult zu erstellen, das EPPlus-Pakete verarbeitet und das anstelle des von File FileResult zurückgibt, z. B .:

 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); } } } 

Welche ermöglicht Ihnen, die folgende Aktion zu schreiben:

 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"}; } 

Erstellen Sie keine HTML-basierten Excel-Dateien, sie haben so viele Probleme.

Verwenden Sie dafür eine kompakte Bibliothek wie 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); } } 

Ich habe Panagiotis Kanavos Code-Struktur verwendet, um diese Lösung zu implementieren

Überprüfen Sie das. Diese Bibliothek enthält ein ExcelResult, das den Erstellungsprozess automatisiert und Excel-Dateien an den Client sendet, indem die Excel () -Methode wie Json () aufgerufen wird.

https://github.com/iabdelkareem/MVC-Excel-Extensions