使用 C# 将大型数据从 GridView 和 DataReader 导出到 Excel 文件
关于将大型数据导出到 Excel 文件的文章
引言
在 GridView 中显示数据是一种很好的方式,但处理和过滤 GridView 中的大量数据会变得困难。将数据导出到 Excel 文件是处理大量数据的绝佳解决方案,因为 Excel 提供了许多功能,如排序、搜索、过滤等,而无需编写一行代码。
在此示例中,我将展示
- 如何从数据库中提取数据并在网格中显示。
- 如何将网格数据导出到 Excel 文件。
- 如何将 DataReader 数据导出到 Excel 文件。
- 如何处理大型数据并应对不同类型的错误。
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 表中。当绑定到数据源时,DataGrid
和 GridView
控件都会将 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 文件,该文件将保存在桌面。
但是这个解决方案存在一些问题:
- 如果您在
GridView
中使用分页,则只会导出单个页面的数据,而不是整个网格的数据。这意味着只会导出页面内渲染的数据。 - 如果
GridView
中的数据量很大,您可能会遇到以下错误:
"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 月上传。