论文部分内容阅读
摘要:本文就ASP.Net中数据导出至Excel的实现方法进行讨论,然后提出一个通用的数据导出类。该类以函数的形式提供数据导出功能,且易扩展,可以很方便地复用。
关键词:数据导出;数据网格控件;网格视图控件
中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)12-21483-01
Study on Exporting Data to Excel in ASP.NET
CHAI Xiao-hui
(Department of Computer Science,Shangqiu Teachers College,Shangqiu 476000,China)
Abstract:This article discussed how to export the data to excel in ASP.NET, the class we propose for the Export to Excel are not linked to the backend structure and can be re-used across projects for the common functionality provided.
Key words:Data Export;DataGrid Control;GridView Control
1 引言
在我们的研究生管理信息系统中,经常需要进行数据的导出操作,如学生学习计划、成绩单、各种统计报表等,其中最常用的就是把处理后的数据导出至Excel。格式要求的多样化给程序的实现带来了很大困难。为了解决这个问题,我们进行了较深入的研究,并提出了一种比较通用的解决方法,该方法不拘于具体背景,几乎不加任何修改即可直接使用。
2 问题研究
在研究生管理系统中,我们原来的数据导出解决方法主要分为两种:
(1)无模板的数据导出:该类数据通常比较单一,不要求进行很多的数据统计工作。实现时采用通用的导出方法。首先处理标题信息,然后从数据控件中依次取出每一行中的数据,填充到对应的Excel单元格中。这种实现方法比较简单,本文不再讨论。
(2)有模板的数据导出:该类数据通常包含各种统计信息,并且要求按照特定的格式导出,而这些格式如果使用第一种方法太多繁琐,需要编写大量的控制代码来指定标题信息和各单元格的实际数据。下面对该问题进行分析。
由于格式要求不一,为了减少程序的工作量,我们原来的解决办法是把要求的格式固定为模板来保存,然后对每一个模板都编写相应的导出方法来实现。如图1所示为招生模块中一志愿上线统计报表的格式:
图1
解决方法:以DataGrid控件为例,设控件名称为dg_1,数据通过Dataset数据源进行绑定。导出数据时,首先利用.xlt格式的模板文件取得格式信息,然后从Dataset中取出数据进行直接导出,完成后保存为.xls格式。参考代码如下:
string path = getPath();
string bookpath = path + filename + ".xlt";
//取得模板文件的路径及名称
string savepath = path + filename + ".xls";
Excel.Application objExcel;
objExcel = new Excel.Application();
objExcel.Workbooks.Add(bookpath);
Excel.Worksheet objSheet;
objSheet = (Excel.Worksheet)(objExcel.Workbooks[1].Worksheets[1]);
HttpResponse response = HttpContext.Current.Response;
for(i = 0;i<hang;i++)
{for(j = 0;j<lie;j++)
{//导出实际数据至对应单元格
objSheet.Cells[i+6,j+1] = y_Ds.Tables[0].Rows[i][j].ToString().Trim();}}
objSheet.SaveAs(savepath); …
该方法虽然可以减少不用再每次指定标题等各种格式信息,但是由于实现时仍然需要指定各单元格对应的填充数据,所以工作量仍然很大。另外,类似研究生学习计划的数据每次只需导出一页(每个学生),而类似一志愿上线统计等的报表则一次就要求导出全部的数据。如果能够根据数据控件直接导出至Excel,不再一一指定行中各字段对应的Excel单元格,则可以很方便地进行导出操作。
3 解决方法
为了描述方便,给定图2所示的导出文件格式,然后分别以DataGrid控件和GridView控件实现数据导出功能。
图2
3.1实现方法:
对于DataGrid控件,为了生成图2所示的标题格式,需要采用代码动态生成标题。需要在控件的ItemCreated事件中添加如下代码:
if (e.Item.ItemType == ListItemType.Header)
{ TableCellCollection Tcc = e.Item.Cells;
Tcc.Clear();
Tcc.Add(new TableHeaderCell());
Tcc[0].RowSpan = 2;
Tcc[0].Text = "员工编号";
Tcc.Add(new TableHeaderCell());
Tcc[1].ColumnSpan = 2;
Tcc[1].Text = "员工姓名</td>";
Tcc[1].Text += "<td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>部门编号</td><td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>薪水</td><td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>雇佣日期</td></tr>";
Tcc[1].Text += "<tr align='center' style='FONT-WEIGHT:bold;'><td>LastName</td><td> FirstName</td></tr>";}
導出数据时的处理代码:
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=FileName.xls");
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
dg_1.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
此时如果DataGrid控件AllowPaging设置true,则程序执行时会产生如下错误:类型“DataGridLinkButton”的控件“dg_1_ctl14_ctl01”必须放在具有 runat=server 的窗体标记内。为了解决这个错误并导出所有数据,在创建控件时仍然允许分页,然后在调用Render方法之前把DataGrid控件的AllowPaging设置false并重新绑定数据。
对于GridView控件,标题部分的实现是在GridView控件的RowCreated事件处理程序添加类似的代码:
if (e.Row.RowType == DataControlRowType.Header)
{ //代码同上 }
实现数据导出时无论分页与否都会产生如下的错误:类型“GridView”的控件“gv_1”必须放在具有 runat=server 的窗体标记内。产生这个错误的详细原因可以参考文献[1]中的解释,本文不再详细解释,只对解决方法进讨论。参考文献[2]中提出新建一个Form对象来消除该错误,然而此时导出的Excel文件的开始位置包含一个多余的空行,为了研究产生这个问题的原因,我们可以在Excel文件中单独输出FORM对象的内容,如下所示:
关键词:数据导出;数据网格控件;网格视图控件
中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)12-21483-01
Study on Exporting Data to Excel in ASP.NET
CHAI Xiao-hui
(Department of Computer Science,Shangqiu Teachers College,Shangqiu 476000,China)
Abstract:This article discussed how to export the data to excel in ASP.NET, the class we propose for the Export to Excel are not linked to the backend structure and can be re-used across projects for the common functionality provided.
Key words:Data Export;DataGrid Control;GridView Control
1 引言
在我们的研究生管理信息系统中,经常需要进行数据的导出操作,如学生学习计划、成绩单、各种统计报表等,其中最常用的就是把处理后的数据导出至Excel。格式要求的多样化给程序的实现带来了很大困难。为了解决这个问题,我们进行了较深入的研究,并提出了一种比较通用的解决方法,该方法不拘于具体背景,几乎不加任何修改即可直接使用。
2 问题研究
在研究生管理系统中,我们原来的数据导出解决方法主要分为两种:
(1)无模板的数据导出:该类数据通常比较单一,不要求进行很多的数据统计工作。实现时采用通用的导出方法。首先处理标题信息,然后从数据控件中依次取出每一行中的数据,填充到对应的Excel单元格中。这种实现方法比较简单,本文不再讨论。
(2)有模板的数据导出:该类数据通常包含各种统计信息,并且要求按照特定的格式导出,而这些格式如果使用第一种方法太多繁琐,需要编写大量的控制代码来指定标题信息和各单元格的实际数据。下面对该问题进行分析。
由于格式要求不一,为了减少程序的工作量,我们原来的解决办法是把要求的格式固定为模板来保存,然后对每一个模板都编写相应的导出方法来实现。如图1所示为招生模块中一志愿上线统计报表的格式:
图1
解决方法:以DataGrid控件为例,设控件名称为dg_1,数据通过Dataset数据源进行绑定。导出数据时,首先利用.xlt格式的模板文件取得格式信息,然后从Dataset中取出数据进行直接导出,完成后保存为.xls格式。参考代码如下:
string path = getPath();
string bookpath = path + filename + ".xlt";
//取得模板文件的路径及名称
string savepath = path + filename + ".xls";
Excel.Application objExcel;
objExcel = new Excel.Application();
objExcel.Workbooks.Add(bookpath);
Excel.Worksheet objSheet;
objSheet = (Excel.Worksheet)(objExcel.Workbooks[1].Worksheets[1]);
HttpResponse response = HttpContext.Current.Response;
for(i = 0;i<hang;i++)
{for(j = 0;j<lie;j++)
{//导出实际数据至对应单元格
objSheet.Cells[i+6,j+1] = y_Ds.Tables[0].Rows[i][j].ToString().Trim();}}
objSheet.SaveAs(savepath); …
该方法虽然可以减少不用再每次指定标题等各种格式信息,但是由于实现时仍然需要指定各单元格对应的填充数据,所以工作量仍然很大。另外,类似研究生学习计划的数据每次只需导出一页(每个学生),而类似一志愿上线统计等的报表则一次就要求导出全部的数据。如果能够根据数据控件直接导出至Excel,不再一一指定行中各字段对应的Excel单元格,则可以很方便地进行导出操作。
3 解决方法
为了描述方便,给定图2所示的导出文件格式,然后分别以DataGrid控件和GridView控件实现数据导出功能。
图2
3.1实现方法:
对于DataGrid控件,为了生成图2所示的标题格式,需要采用代码动态生成标题。需要在控件的ItemCreated事件中添加如下代码:
if (e.Item.ItemType == ListItemType.Header)
{ TableCellCollection Tcc = e.Item.Cells;
Tcc.Clear();
Tcc.Add(new TableHeaderCell());
Tcc[0].RowSpan = 2;
Tcc[0].Text = "员工编号";
Tcc.Add(new TableHeaderCell());
Tcc[1].ColumnSpan = 2;
Tcc[1].Text = "员工姓名</td>";
Tcc[1].Text += "<td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>部门编号</td><td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>薪水</td><td rowspan='2' align='center' style='FONT-WEIGHT:bold;'>雇佣日期</td></tr>";
Tcc[1].Text += "<tr align='center' style='FONT-WEIGHT:bold;'><td>LastName</td><td> FirstName</td></tr>";}
導出数据时的处理代码:
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=FileName.xls");
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
dg_1.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
此时如果DataGrid控件AllowPaging设置true,则程序执行时会产生如下错误:类型“DataGridLinkButton”的控件“dg_1_ctl14_ctl01”必须放在具有 runat=server 的窗体标记内。为了解决这个错误并导出所有数据,在创建控件时仍然允许分页,然后在调用Render方法之前把DataGrid控件的AllowPaging设置false并重新绑定数据。
对于GridView控件,标题部分的实现是在GridView控件的RowCreated事件处理程序添加类似的代码:
if (e.Row.RowType == DataControlRowType.Header)
{ //代码同上 }
实现数据导出时无论分页与否都会产生如下的错误:类型“GridView”的控件“gv_1”必须放在具有 runat=server 的窗体标记内。产生这个错误的详细原因可以参考文献[1]中的解释,本文不再详细解释,只对解决方法进讨论。参考文献[2]中提出新建一个Form对象来消除该错误,然而此时导出的Excel文件的开始位置包含一个多余的空行,为了研究产生这个问题的原因,我们可以在Excel文件中单独输出FORM对象的内容,如下所示: