简体   繁体   English

如何导出到 Excel?

[英]How do I export to Excel?

I followed this guide which was recommended in another post about this but I can't quite get it to work.我遵循了在另一篇关于此的帖子中推荐的本指南,但我无法使其正常工作。 I get a 404 error when trying to redirect to /LogModelsController/ExportData which - as I understood it - was what I was supposed to do.尝试重定向到 /LogModelsController/ExportData 时出现 404 错误,正如我所理解的,这是我应该做的。

_LogPartialLayout.cshtml _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" />
}

_LogPartialLayout.cshtml

LogModelsController.cs 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日志模型.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: How do I properly export this table to Excel? TD;DR:如何将此表正确导出到 Excel?

Bonus: Does it work with PagedList too?奖励:它也适用于 PagedList 吗?


Edit 3 - SOLVED编辑 3 - 已解决

Index.cshtml:索引.cshtml:

@using (Html.BeginForm("ExportData", "LogModels"))
{
    <input type="submit" name="Export" id="Export" value="Export" />
}

LogModelsController.cs 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;
}

I made a mistake in the CommandText and put "Id" instead of "CustomerId" - it now returns the entire table in the Excel file.我在 CommandText 中犯了一个错误,把“Id”而不是“CustomerId” - 它现在返回 Excel 文件中的整个表。

The guide doesn't show how to create an Excel file, it shows a hack that creates an HTML file with a Table.该指南没有展示如何创建 Excel 文件,它展示了一种使用表格创建 HTML 文件的技巧。 Excel will try to import csv or HTML files with tables using default settings which can often fail. Excel 将尝试使用通常会失败的默认设置导入带有表格的 csv 或 HTML 文件。

It's far easier to create a proper Excel file using a library like EPPlus .使用像EPPlus这样的库创建合适的Excel 文件要容易得多 I'm sure this has been answered before but I can't find an answer that shows both how to create an Excel file from data and set the proper content type for an xlsx file.我确定之前已经回答过这个问题,但我找不到一个答案来显示如何从数据创建 Excel 文件并为xlsx文件设置正确的内容类型

EPPlus provides the LoadFromDataTable and LoadFromCollection methods to fill an Excel range with data pulled from a DataTable or generic collection. EPPlus 提供 LoadFromDataTable 和 LoadFromCollection 方法来使用从 DataTable 或通用集合中提取的数据填充 Excel 范围。 The column or property names are used as headers respectively.列名或属性名分别用作标题。

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 or LoadFromCollection return an Excel cell range which can be used to format the table: LoadFromDataTable 或 LoadFromCollection 返回可用于格式化表格的 Excel 单元格范围:

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

You can also apply a table style to the range, or pass the desired style to LoadFromDataTable or LoadFromCollection , eg:您还可以将表格样式应用于范围,或将所需样式传递给LoadFromDataTableLoadFromCollection ,例如:

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

The library's Githup wiki shows how to format the result , generate formulas, PivotTables, handle tables etc.该库的Githup wiki展示了如何格式化结果、生成公式、数据透视表、处理表格等。

Saving to a MemoryStream may be an issue if you want to create a relatively large sheet.如果您想创建一个相对较大的工作表,保存到 MemoryStream 可能是一个问题。 Writing the same data twice, once to the MemoryStream and then copying it to output, wastes cycles.两次写入相同的数据,一次写入 MemoryStream,然后将其复制到输出,浪费周期。 Writing directly to the output stream from an MVC action is a bad practice though.但是,从 MVC 操作直接写入输出流是一种不好的做法。 The trick is to create a custom FileResult that handles EPPlus packages and return that instead of the FileResult returned by File , eg:诀窍是创建一个自定义 FileResult 来处理 EPPlus 包并返回它而不是File返回的 FileResult ,例如:

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

Which allows you to write the following action:这允许您编写以下操作:

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

Don't create HTML based excel files, they have so many problems.不要创建基于 HTML 的 excel 文件,它们有很多问题。

Insteed use a compact library for that such as epplus . Insteed 使用一个紧凑的库,例如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);
    }
}

I have used Panagiotis Kanavos code structure to implement this solution我已经使用 Panagiotis Kanavos 代码结构来实现这个解决方案

Check this out, This library is containing an ExcelResult that will automate the process of creation, and send Excel file to the client by calling Excel() method just like Json().看看这个,这个库包含一个 ExcelResult,它将自动创建过程,并通过调用 Excel() 方法将 Excel 文件发送到客户端,就像 Json()。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM