使用 C# 从 Gridview 和 Datareader 导出大型数据到 Excel 文件






4.27/5 (24投票s)
2007年6月21日
5分钟阅读

264853

3927
一篇关于将大型数据导出到 Excel 文件的文章。
引言
显示数据的良好方式是将其显示在网格视图中。然而,以这种方式处理和筛选大量数据变得困难。将数据导出到 Excel 文件是处理大量数据的绝佳解决方案,因为 Excel 具有许多功能——例如排序、搜索和筛选——而无需您编写一行代码。在此示例中,我将展示
- 如何从数据库中提取数据并在网格中显示它。
- 如何将数据从网格导出到 Excel 文件。
- 如何将数据从数据读取器导出到 Excel 文件。
- 如何处理大量数据并应对不同类型的错误。
使用代码
此示例使用 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 端代码如下
<asp:GridView ID="grdStudentMarks" runat="server"
DataSourceID="dsStudentMarks">
<EmptyDataTemplate>
No Data Found
</EmptyDataTemplate>
<RowStyle CssClass="ClsOddRow" />
<AlternatingRowStyle CssClass="ClsEvenRow" />
<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>
<asp:Button ID="btnExportFromDatagrid" runat="server"
Text="Export From Grid" OnClick="btnExportFromDatagrid_Click" />
<asp:Button ID="btnExportFromDataset" runat="server"
Text="Export From Data set" />
当 ASP.NET 页面渲染时,grdStudentMarks
将由 UniversityManager 数据库的 Student 表中的数据填充。因此,使用了 Windows 身份验证。除此之外,我还添加了两个名为 btnExportFromDatagrid
和 btnExportFromDataset
的按钮。现在我们有一个包含数据库数据的网格。我们的下一个目标是将此数据从数据网格导出到 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
流中添加了一个标题。它将强制用户下载文件,而不是在浏览器中内嵌显示。然后,我们使用 Response.ContentType
将输出流的 HTTP MIME 类型设置为 *application/vnd.xls*。然后使用 GridView
类的 RenderControl
方法,该方法将服务器控件内容输出到提供的 HtmlTextWriter htmlWrite
。最后,将其写入 Response 流。
此时工作应该完成了!然而,如果您加载页面并单击按钮,您可能会看到以下错误
类型为“GridView”的控件“grdStudentMarks”必须放置在具有 runat=server 的 form 标签内。
要解决此错误,您应该重写 VerifyRenderingInServerForm
方法。只需编写以下代码
public override void VerifyRenderingInServerForm(Control control)
{
}
就是这样!网格视图的数据将被导出到 Excel 文件,该文件应保存在桌面。然而,这个解决方案存在一些问题。首先,如果您的网格视图使用分页,那么只有单个页面的数据将被导出,而不是整个网格的数据。这意味着只有页面内渲染的数据才会被导出。其次,如果网格视图的数据量很大,您可能会遇到以下错误
超时已过期。在操作完成之前,超时时间已到期,或者服务器未响应。
这是一个 System.Data.SqlClient.SqlException
。当操作完成之前超时时间已到期时,就会发生此异常。因此,要解决此类问题,我们将使用以下解决方案。
超时解决方案
我将使用 SQLCommand
类,因为通过使用它,我们可以设置超时属性。CommandTimeout
属性设置在终止任何执行命令之前的等待时间。数据被读入 SqlDataReader
,数据读取器的每一行都被写入 Response 流。需要注意的是,每个单元格的值——即一行中的特定列——后面都跟着一个逗号分隔符,以便 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
超时异常的问题现已解决,但仍有可能出现 HttpRequest
超时异常。要解决此问题,请在 *web.config* 文件的 <system.web> 标签内放入以下行
<httpRuntime maxRequestLength="209715" executionTimeout="3600" />
就是这样!
关注点
因此,我们学习了如何从数据库中提取数据并在网格视图控件中显示它。我们学习了如何将数据从网格视图导出到 Excel 文件,如何从数据读取器导出大量数据以及如何将这些数据导出到 Excel 文件。我希望这个例子能帮助您。对于本篇文章,请随时给我任何建议。编码愉快!
历史
此演示首次上传于 2007 年 6 月 21 日。