MVC 网格到 Excel 文件下载






4.50/5 (14投票s)
将ASP.NET MVC网格的结果转换为可下载的Excel文件
引言
本文介绍如何将ASP.NET MVC Web应用程序中表格或网格形式呈现的数据转换为可下载的Excel数据文件。
背景
我最近正在构建一个基于ASP.NET MVC 3的报表应用程序。其中一个功能是提供一个可下载的Excel文件,用于呈现为网格/表格的报表。与其重新创建一个完整的模块来完成此操作,我希望找到一种重用用于渲染视图的数据的方法,并尽可能减少代码量。
使用代码
我尝试将大部分实现封装在一个自定义ActionResult类(DownloadFileActionResult)中,因此您可以传递一个GridView对象形式的数据,并期望得到一个包含表格数据的可下载Excel文件。
您可以从下面的链接下载完整的代码。
如上所述,大部分实现都包含在DownloadFileActionResult类中。
首先,DownloadFileActionResult继承自抽象ActionResult类,构造函数接受两个参数:绑定的GridView对象和可下载Excel文件的名称。
ExecuteResult被重写,包含自定义实现,该实现创建一个响应,然后使用HtmlTextWriter和一个StringWriter将GridView的渲染管道传输到字符串。然后将此字符串流式传输回响应,以作为Excel文件交付。就这么简单。
public class DownloadFileActionResult : ActionResult
{
public GridView ExcelGridView { get; set; }
public string fileName { get; set; }
public DownloadFileActionResult(GridView gv, string pFileName)
{
ExcelGridView = gv;
fileName = pFileName;
}
public override void ExecuteResult(ControllerContext context)
{
//Create a response stream to create and write the Excel file
HttpContext curContext = HttpContext.Current;
curContext.Response.Clear();
curContext.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
curContext.Response.Charset = "";
curContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
curContext.Response.ContentType = "application/vnd.ms-excel";
//Convert the rendering of the gridview to a string representation
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
ExcelGridView.RenderControl(htw);
//Open a memory stream that you can use to write back to the response
byte[] byteArray = Encoding.ASCII.GetBytes(sw.ToString());
MemoryStream s = new MemoryStream(byteArray);
StreamReader sr = new StreamReader(s, Encoding.ASCII);
//Write the stream back to the response
curContext.Response.Write(sr.ReadToEnd());
curContext.Response.End();
}
}
在控制器的Action结果中,您需要创建GridView,将模型数据绑定到它,并将其存储在Session变量中,以便将模型数据与视图绑定。
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
CarModels cm = new CarModels();
List<Cars> model = cm.getAllCars();
GridView gv = new GridView();
gv.DataSource = model;
gv.DataBind();
Session["Cars"] = gv;
return View(model);
}
在同一个控制器中,我们需要创建一个新的ActionResult,名为Download,以处理文件下载请求。
public ActionResult Download()
{
if (Session["Cars"] != null)
{
return new DownloadFileActionResult((GridView)Session["Cars"], "Cars.xls");
}
else
{
//Some kind of a result that will indicate that the view has
//not been created yet. I would use a Javascript message to do so.
}
}
在视图中,您放置以下下载链接
@Html.ActionLink("Download File", "Download")
关注点
我希望本文能展示如何通过自定义实现来覆盖默认的ActionResult类,从而生成自定义响应。
我不完全满意将网格结果存储在Session变量中,并将努力提出一个更好的解决方案。
局限性
由于这只是作为Excel工作表呈现的HTML,因此您将无法使用大多数Excel功能。在我的例子中,客户想要的是数据的可下载版本,所以没问题。但是,如果您想创建一个真正的Excel文件,可以考虑使用XSLT将HTML输出转换为Excel文件。
参考
http://www.codeshelve.com/code/details/54/export-to-excel-in-asp-net-mvc