在Asp.net 中,Web报表,是每个项目都不可避免的,而很多报表,还要求,将报表导出到 Excel 中,本文提供一种轻便的方法,来实现这一功能。
1、首先,需要在 Asp.net 项目中,添加一个类 Excel(文件名为 Excel.cs)
2、将如下代码,复制到 Excel.cs 中:
using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using ItsWeb.Common;
namespace ItsWeb.Common
{
/// <summary>
/// 实现将一个 System.Web.UI.WebControls.Table 或 DataTable 中的数据,输出到Excel中
/// 作者:海底捞针
/// </summary>
public class Excel
{
private Page m_Pg;
private System.Web.HttpResponse Response;
public Excel(Page pg)
{
this.m_Pg=pg;
Response=this.m_Pg.Response;
Response.Expires=-1;
Response.Buffer=true;
Response.ContentType="application/vnd.ms-excel";
Response.Charset="gb-2312";
Response.AppendHeader("content-disposition","inline");
Response.Write("<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'> <head> <meta name='ProgId' content='Excel.Sheet'> <meta name='Generator' content='Microsoft Excel 11'>/n"+
"<!--[if gte mso 9]><xml>/n"+
" <o:DocumentProperties>/n"+
" <o:Author>MC SYSTEM</o:Author>/n"+
" <o:LastAuthor>MC SYSTEM</o:LastAuthor>/n"+
" <o:Created>2005-03-22T05:13:09Z</o:Created>/n"+
" <o:LastSaved>2005-03-23T03:15:19Z</o:LastSaved>/n"+
" <o:Company>jtgd</o:Company>/n"+
" <o:Version>11.5606</o:Version>/n"+
" </o:DocumentProperties>/n"+
"</xml><![endif]-->/n"+
"<!--[if gte mso 9]><xml>/n"+
" <x:ExcelWorkbook>/n"+
" <x:ExcelWorksheets>/n"+
" <x:ExcelWorksheet>/n"+
" <x:Name>Sheet1</x:Name>/n"+
" <x:WorksheetOptions>/n"+
" <x:ProtectScenarios>False</x:ProtectScenarios>/n"+
" </x:WorksheetOptions>/n"+
" </x:ExcelWorksheet>/n"+
" </x:ExcelWorksheets>/n"+
" <x:WindowHeight>9675</x:WindowHeight>/n"+
" <x:WindowWidth>11700</x:WindowWidth>/n"+
" <x:WindowTopX>240</x:WindowTopX>/n"+
" <x:WindowTopY>105</x:WindowTopY>/n"+
" </x:ExcelWorkbook>/n"+
"</xml><![endif]-->/n"+
" <style>/n"+
" .brow{border-left:1px solid white;border-top:1px solid white;border-right:1px solid white;}"+
" </style>/n"+
" </head>/n"+
" <body>/n"+
" <table ID='Table1' border='1' cellPadding='1' cellspacing='1'>");
}
/// <summary>
/// 设置 Excel 中表格的标题、表眉
/// 本方法可以执行多次,每次在表格上添加一行,用于显示标题或表眉
/// </summary>
/// <param name="colSpan">跨列数,一般为表格占用列</param>
/// <param name="bCenter">是否居中</param>
/// <param name="brows">
/// 一个字符数组,如果是标题,则为1个元素的字符数组
/// 如果是表眉,则每个元素为一项
/// </param>
public void setHead(int colSpan,bool bCenter,string[] brows)
{
if(brows.Length>0)
{
Response.Write("<tr><td class=brow "+((bCenter)?"align='center' ":"")+"colspan="+colSpan.ToString()+">");
for(int i=0;i<brows.Length;i++)
Response.Write(" "+brows[i]+" ");
Response.Write("</td></tr>");
}
}
/// <summary>
/// 设置导出到Excel中的 DataTable、标题、表眉(数组)
/// </summary>
/// <param name="bEnd">执行本方法后,是否执行 Response.End()</param>
/// <param name="dt">数据表,如果DataTable 设置了列 Caption 属性,将用来做Excel的列标题,否则用字段名作列标题</param>
/// <param name="caption">标题</param>
/// <param name="brows">表眉</param>
public void setData(bool bEnd,System.Data.DataTable dt,string caption,string[] brows)
{
int ct=dt.Columns.Count;
bool[] abFmt=getFmt(dt);
string[] aTd=new string[ct];
for(int c=0;c<ct;c++)
{
aTd[c]=(abFmt[c])?"<td x:num>":"<td>";
}
setHead(ct,true,new string[]{caption});
setHead(ct,false,brows);
Response.Write("<tr align='center'>");
for(int c=0;c<ct;c++)
if(dt.Columns[c].Caption != "")
Response.Write("<td align=middle>"+dt.Columns[c].Caption+"</td>");
else
Response.Write("<td align=middle>"+dt.Columns[c].ColumnName+"</td>");
Response.Write("</tr>/n");
for(int r=0;r<dt.Rows.Count;r++)
{
Response.Write("<tr>");
for(int c=0;c<ct;c++)
Response.Write(aTd[c]+dt.Rows[r][c].ToString()+"</td>");
Response.Write("</tr>/n");
}
if(bEnd)
End();
}
/// <summary>
/// 设置导出到 Excel 中的 DataTable、标题、表眉
/// 在执行完本方法后,自动执行 Response.End()
/// </summary>
/// <param name="dt">数据表,如果DataTable 设置了列 Caption 属性,将用来做Excel的列标题,否则用字段名作列标题</param>
/// <param name="caption">标题</param>
/// <param name="brows">表眉</param>
public void setData(System.Data.DataTable dt,string caption,params string[] brows)
{
this.setData(true,dt,caption,brows);
}
/// <summary>
/// 设置导出到 Excel 中的 DataTable、标题、表眉
/// Excel 中的列,由 dispCols 参数指定,列标题由 colCaps指定
/// 在执行完本方法后,自动执行 Response.End()
/// </summary>
/// <param name="caption">标题</param>
/// <param name="dt">数据表</param>
/// <param name="dispCols">int 数组,用来设置输出那些列</param>
/// <param name="colCaps">string 数组,用来设置输出的列的标题</param>
/// <param name="brows">表眉</param>
public void setData(string caption,System.Data.DataTable dt,int[] dispCols,string[] colCaps,params string[] brows)
{
this.setData(true,caption,dt,dispCols,colCaps,brows);
}
/// <summary>
/// 设置导出到 Excel 中的 DataTable、标题、表眉
/// Excel 中的列,由 dispCols 参数指定,列标题由 colCaps指定
/// </summary>
/// <param name="bEnd">执行完本方法后,是否执行 Response.End()</param>
/// <param name="caption">标题</param>
/// <param name="dt">数据表</param>
/// <param name="dispCols">int 数组,用来设置输出那些列</param>
/// <param name="colCaps">string 数组,用来设置输出的列的标题</param>
/// <param name="brows">表眉</param>
public void setData(bool bEnd, string caption, System.Data.DataTable dt, int[] dispCols, string[] colCaps, string[] brows)
{
int ct=dispCols.Length;
bool[] abFmt=getFmt(dt,dispCols);
string[] aTd=new string[ct];
for(int c=0;c<ct;c++)
{
aTd[c]=(abFmt[c])?"<td x:num>":"<td>";
}
setHead(ct,true,new string[]{caption});
setHead(ct,false,brows);
Response.Write("<tr align='center'>");
for(int c=0;c<ct;c++)
Response.Write("<td align=middle>"+colCaps[c]+"</td>");
Response.Write("</tr>/n");
for(int r=0;r<dt.Rows.Count;r++)
{
Response.Write("<tr>");
for(int c=0;c<ct;c++)
Response.Write(aTd[c]+dt.Rows[r][dispCols[c]].ToString()+"</td>");
Response.Write("</tr>/n");
}
if(bEnd)
End();
}
/// <summary>
/// 关闭表格标签,结束页面
/// </summary>
public void End()
{
Response.Write("</table><!--#include file='chart.htm'--></body></html>");
Response.Flush();
this.m_Pg=null;
}
/// <summary>
/// 将参数 ctl 中的数据、格式,输出到 Excel
/// </summary>
/// <param name="ctl"></param>
public void RenderControl(System.Web.UI.WebControls.Table ctl)
{
HtmlTextWriter r=new HtmlTextWriter(Response.Output);
for(int i=0;i<ctl.Rows.Count;i++)
ctl.Rows[i].RenderControl(r);
}
private bool[] getFmt(System.Data.DataTable dt)
{
bool[] aFmt=new bool[dt.Columns.Count];
for(int c=0;c<dt.Columns.Count;c++)
{
string ct=dt.Columns[c].DataType.FullName;
if(ct=="System.String")
aFmt[c]=false;
else
aFmt[c]=true;
}
return aFmt;
}
private bool[] getFmt(System.Data.DataTable dt,int[] cols)
{
bool[] aFmt=new bool[cols.Length];
for(int c=0;c<aFmt.Length;c++)
{
string ct=dt.Columns[cols[c]].DataType.FullName;
if(ct=="System.String")
aFmt[c]=false;
else
aFmt[c]=true;
}
return aFmt;
}
}
}
3、在报表页面,需要有一个复选框控件 chkExcel,当打勾时,表示要输出到 Excel。
4、在报表页面,可用两种方式输出到 Excel:
4.1、在查询到最终的 DataTable dtData 后,创建 Excel 对象,并将 dtData 传递给 Excel 对象,调用 setData方法:
4.1.1、将 DataTable 全部列shuch
if (this.chkExcel.Checked)
{
Excel xl = new Excel(this);
xl.setData(true,dtData,"标题",new string[]{"日期:xxx","单位:yyy"});
xl=null;
}
4.1.2、将 DataTable 指定列输出到 Excel
if (this.chkExcel.Checked)
{
int[] cols=new int[]{0,2,3,4};
string[] caps=new string[]{"时间","车号","上车人数","下车人数"};
Excel xl = new Excel(this);
xl.setData("标题",dtData,cols,caps,new string[]{"日期:xxx","单位:yyy"});
xl=null;
}
4.2、先按正常报表,将数据填充到 System.Web.UI.WebControls.Table 中,并设置格式,最后,判断是否需要输出到 Excel,如果需要,则将该表格控件作为 RenderControl 方法的参数,传递到Excel对象,则将控件中的数据、格式,传递到 Excel 输出:
if (this.chkExcel.Checked)
{
Excel xl = new Excel(this);
int cols=xxx; //列数
xl.setHead(cols,true,new string[]{"标题"});
xl.setHead(cols,false,new string[]{"日期:xxx","单位:yyy"});
xl.RenderControl(this.svrTable);
xl.End();
xl=null;
}
完