以 .xlsx 格式将 GridView 导出到 Excel 时出错

Getting Error while Exporting GridView To Excel in .xlsx format

我想将 GridView 导出为 excel(.xlsx 格式)。 这是我的代码

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
 GridView gv;

protected void Button1_Click(object sender, EventArgs e)
{
    setGridView();
    Response.Clear();
    Response.ClearContent();
    Response.ClearHeaders();
    string fileName = "TestExcelFile.xlsx";
    Response.Buffer = true;
    Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    //Response.ContentType = "application/vnd.ms-excel"; // Works perfectly for .xls files
    StringWriter sw = new StringWriter();
    HtmlTextWriter htw = new HtmlTextWriter(sw);
    gv.RenderControl(htw);
    Response.Write(sw.ToString());
    Response.Flush();
    Response.End();
}

private void setGridView()
{
    gv = new GridView();
    Queue q = new Queue();
    for (int i = 0; i < 20; i++)
    {
        q.Enqueue(i);
    }
    gv.DataSource = q;
    gv.DataBind();
 }
}

如果我将响应内容类型保留为:Response.ContentType = "application/vnd.ms-excel"; 那么它非常适合 excel 的 .xls 格式。

但对于 .xlsx 格式的 excel 文件,内容类型应为:Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";.

我可以使用 .xls 格式,但问题是 .xls 格式只能容纳 64000 条记录,根据我的项目要求,我将获得近 100000 (100K) 行。所以我必须将其导出为 .xlsx 格式的 excel 以保存 64000 以上的记录。

错误文本和图片如下: "Excel cannot open the file 'TestExcelFile[2].xlsx' because the file format for the file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file."

首先,我不知道 "Lakh" 是什么,但我猜它大于 65535,但据我所知 ASP.NET Gridview 无法将其导出到 XLSX直接格式化,因为它将其输出为原始 HTML。

我建议您看一下像 EPPlus (http://epplus.codeplex.com/) 这样的组件,它更加灵活和可扩展,可以满足您的要求。

作为变通方法,您可以尝试使用以下代码,尽管这不是那么优雅:

protected void btnExportData_Click(object sender, EventArgs e)
{
    Response.Clear();

    Response.AddHeader("content-disposition", "attachment;filename=output.xlsx");
    Response.Charset = "";
    Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

    System.IO.StringWriter sw = new System.IO.StringWriter();
    System.Web.UI.HtmlTextWriter htmlWriter = new HtmlTextWriter(sw);

    foreach (GridViewRow row in gvData.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
            for (int idxColumn = 0; idxColumn < row.Cells.Count; idxColumn++)
                row.Cells[idxColumn].Attributes.Add("class", "xlText");
    }

    gvData.RenderControl(htmlWriter);

    string appendStyle = @"<style> .xlText { mso-number-format:\@; } </style> ";
    Response.Write(appendStyle);

    Response.Write(sw.ToString());
    Response.End();
}

我在 Excel 2007 年之前使用过那个,但它是一个 hack,不是很优雅。

这个问题的另一个解决方案(它只会说服你得到 EPPlus,正如 JaggenSWE 在我之前提到的,当比较相对工作量时)是使用 Microsoft.Office.Interop.Excel 工具......

using Microsoft.Office.Interop.Excel

string path = @"C:\testoutput\output.xlsx";

Microsoft.Office.Interop.Excel.Application oXL;
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
Microsoft.Office.Interop.Excel.Range oRng;

oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = false; //This can be fun to leave enabled though :)
oXL.UserControl = false;

oBook = oXL.Workbooks.Add();
oSheet = oBook.ActiveSheet;

//This part can take a while, so throwing it into an async method elsewhere may be a thought
for (int x = 0; x < gv.Rows.Count; x++)
{
    for (int y = 0; y < gv.Columns.Count; y++)
    {
        oSheet.Cells[x + 2, y + 1] = gv.Rows[x].Cells[y].ToString();
    }
}
oBook.SaveAs(path, Microsoft.Office.Interop.Excel.XlFileFormat.xlOpenXMLWorkbook);

oBook.Close(); //Don't forget this because the program will not close it automatically!!!