65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 将大型数据从 GridView 和 DataReader 导出到 Excel 文件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (9投票s)

2007年6月20日

CPOL

4分钟阅读

viewsIcon

100123

downloadIcon

711

关于将大型数据导出到 Excel 文件的文章

引言

在 GridView 中显示数据是一种很好的方式,但处理和过滤 GridView 中的大量数据会变得困难。将数据导出到 Excel 文件是处理大量数据的绝佳解决方案,因为 Excel 提供了许多功能,如排序、搜索、过滤等,而无需编写一行代码。

在此示例中,我将展示

  1. 如何从数据库中提取数据并在网格中显示。
  2. 如何将网格数据导出到 Excel 文件。
  3. 如何将 DataReader 数据导出到 Excel 文件。
  4. 如何处理大型数据并应对不同类型的错误。

Using the Code

此示例使用 ASP.NET 2.0、C# 和 SQL Server 2005。

我使用一个简单的数据库表来避免不必要的开销。假设我们有一个名为“UniversityManager”的数据库,其中有一个名为“Student”的表。表的结构如下:

列名 数据类型
Roll(滚动) varchar(10)
名称 varchar(50)
分数 int

我使用 ASP.NET SqlDataSource 控件从数据库中提取数据。SqlDataSource 可用作数据源,可以从数据库获取数据,并可以绑定到 ASP.NET 控件。为了在网格中显示这些数据,我使用了 ASP.NET GridView 控件。GridView 控件是 DataGrid 控件的后继者。与 DataGrid 控件一样,GridView 控件旨在将数据显示在 HTML 表中。当绑定到数据源时,DataGridGridView 控件都会将 DataSource 中的一行显示为输出表中的一行。

<asp:GridView ID="grdStudentMarks" 
      Font-Names="verdana" runat="server" 
      DataSourceID="dsStudentMarks">
<EmptyDataTemplate>
No Data Found
</EmptyDataTemplate>
        
<RowStyle BackColor="white" />
<AlternatingRowStyle BackColor="beige" />
<HeaderStyle CssClass="ClsHeaderRow" />               
</asp:GridView>
<asp:SqlDataSource ID="dsStudentMarks" runat="server" 
   ConnectionString="Data Source=.;Initial Catalog=
                     UniversityManager;Integrated Security=True;"
SelectCommand="(SELECT *FROM STUDENT) ">        
</asp:SqlDataSource>
<headerstyle cssclass="ClsHeaderRow">
<asp:Button ID="btnExportFromDatagrid" runat="server" 
   Text="Export From Grid" OnClick="btnExportFromDatagrid_Click" />
<asp:Button ID="btnExportFromDataset"  runat="server" 
  Text="Export From Data Reader" OnClick="btnExportFromDataset_Click" />
</headerstyle>
<asp:sqldatasource selectcommand="  (
                SELECT *FROM STUDENT                                     
                )                 
                " connectionstring="Data Source=.;
                Initial Catalog=UniversityManager;Integrated Security=True;" 
         runat="server" id="dsStudentMarks">
</asp:sqldatasource>    
<asp:button text="Export From Data set" runat="server" id="btnExportFromDataset">
</asp:button>

当 ASP.NET 页面呈现时,“grdStudentMarks”将填充来自“UniversityManager”数据库的“student”表的数据。因此,使用了 Windows 身份验证。此外,我还有两个按钮,名为“btnExportFromDatagrid”和“btnExportFromDataset”。

现在我们有了一个包含来自数据库的数据的网格。我们的下一个目标是将此数据从 DataGrid 导出到 Excel。我们已将此代码写入“btnExportFromDataGrid”的 Click 事件中。

protected void btnExportFromDatagrid_Click(object sender, EventArgs e)
{
    ExportGridToExcel(grdStudentMarks, "StudentMarks.xls");   
}
public void ExportGridToExcel(GridView grdGridView, string fileName)
{
    Response.Clear();
    Response.AddHeader("content-disposition", 
       string.Format("attachment;filename={0}.xls", fileName));
    Response.Charset = "";
    Response.ContentType = "application/vnd.xls";

    StringWriter stringWrite = new StringWriter();
    HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
    grdGridView.RenderControl(htmlWrite);
    Response.Write(stringWrite.ToString());
    Response.End();
}

当按钮被点击时,我们调用一个名为 ExportGridToExcel 的函数,并将 Gridview 作为参数,以及我们希望保存的文件名。向 HttpResponse 流添加了标头。它将强制用户下载文件,而不是在浏览器中(在 IE 中)嵌入显示。然后,通过 Response.ContentType,我们将输出流的 HTTP MIME 类型设置为“application/vnd.xls”。然后,使用 GridView 类的 RenderControl 方法,它将服务器控件的内容输出到提供的 HtmlTextWriter,即 htmlWrite。最后,将其写入响应流。

到此为止,工作应该已经完成了!但是,当您加载页面并单击按钮时,您可能会看到以下错误:

"Control 'grdStudentMarks' of type 'GridView' must 
          be placed inside a form tag with runat=server."

要解决此错误,您应该覆盖 VerifyRenderingInServerForm 方法。只需编写以下内容:

public override void VerifyRenderingInServerForm(Control control)
{
}

就这样!GridView 中的数据将被导出到 Excel 文件,该文件将保存在桌面。

但是这个解决方案存在一些问题:

  1. 如果您在 GridView 中使用分页,则只会导出单个页面的数据,而不是整个网格的数据。这意味着只会导出页面内渲染的数据。
  2. 如果 GridView 中的数据量很大,您可能会遇到以下错误:
  3. "Timeout expired. The timeout period elapsed prior 
       to completion of the operation or the server is not responding."

    这是一个 System.Data.SqlClient.SqlException。当操作完成之前超时时间已过时,将发生此异常。

要解决此类问题,我们将使用以下解决方案:

解决方案

我将使用 SQLCommand 类,因为使用它,我们可以设置超时属性。“CommandTimeout”属性设置在终止任何执行命令之前的等待时间。数据以 SqlDataReader 的形式获取,数据读取器的每一行都写入响应流。需要注意的是,每个单元格的值(行的特定列)后面都跟着一个逗号 (,) 分隔符,以便 CSV 文件可以对其进行格式化。

代码如下

 protected void btnExportFromDataset_Click(object sender, EventArgs e)
{
    ExportToExcel(dsStudentMarks, "StudentMarks");
}

public void ExportToExcel(SqlDataSource dataSrc, string fileName)
{
    //Add Response header 

    Response.Clear();
    Response.AddHeader("content-disposition", 
       string.Format("attachment;filename={0}.csv", fileName));
    Response.Charset = "";
    Response.ContentType = "application/vnd.xls";
    //GET Data From Database                

    SqlConnection cn = new SqlConnection(dataSrc.ConnectionString);
    string query = dataSrc.SelectCommand.Replace("\r\n", " ").Replace("\t", " ");
    
    SqlCommand cmd = new SqlCommand(query, cn);
    
    cmd.CommandTimeout = 999999 ;
    cmd.CommandType    = CommandType.Text;
    try
    {
        cn.Open();
        SqlDataReader dr = cmd.ExecuteReader();
        StringBuilder sb = new StringBuilder();
        //Add Header

        for (int count = 0; count < dr.FieldCount; count++)
        {
            if (dr.GetName(count) != null)
                sb.Append(dr.GetName(count));
            if (count < dr.FieldCount - 1)
            {
                sb.Append(",");
            }
        }
        Response.Write(sb.ToString() + "\n");
        Response.Flush();
        //Append Data

        while (dr.Read())
        {
            sb = new StringBuilder();
           
            for (int col = 0; col < dr.FieldCount - 1; col++)
            {
                if (!dr.IsDBNull(col))
                    sb.Append(dr.GetValue(col).ToString().Replace(",", " "));
                sb.Append(",");
            }
            if (!dr.IsDBNull(dr.FieldCount - 1))
                sb.Append(dr.GetValue(dr.FieldCount - 1).ToString().Replace(",", " "));
            Response.Write(sb.ToString() + "\n");
            Response.Flush();
        }
        dr.Dispose();
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
    }
    finally
    {
        cmd.Connection.Close();
        cn.Close();
    }
    Response.End();
}

这将解决下载大型数据的问题。SqlClient 超时异常的问题已解决,但仍然可能发生 HtttpRequest 超时异常。要解决此问题,请将以下行放在 web.config 文件的 <system.web> 标签内。

<httpRuntime maxRequestLength="2097151" executionTimeout="3600"/></httpruntime>

就是这样!

关注点

因此,我们学习了如何从数据库中提取数据并在 GridView 控件中显示,如何将 GridView 数据导出到 Excel 文件,以及一种从 DataReader 导出大量数据并将其导出到 Excel 文件的方法。

希望这个例子能帮到您。如果您对本文有任何建议,请随时提出。

祝您编码愉快!

历史

  • 此演示于 2007 年 6 月上传。
© . All rights reserved.