[转载]DataSet导出Excel,比以往的方法导出的Excel外观更加好看

碰到将数据库的数据导出Excel中问题,常规做法可能是通过System.Data.OleDb的对象来处理,但好像针对Word\Excel的版本不同给出的数据库访问连接串也不同。好像还有客户端\服务端是否安装office程序的问题,保证创建的文件正常打开、下载。自己就找了一篇相对较好的一种通过XHTML以输出流的形式导出,当然只适用于B/S对于C/S无法适用,但使用Microsoft.Office.Interop.Excel.dll处理的Excel对象的导出可以封装好,在B/S和C/S下都可以用。

原文名称DataSet导出Excel,比以往的方法导出的Excel外观更加好看
原文链接http://hi.baidu.com/handboy/item/e61e509418e9974af04215eb
原文如下

======目前方法=========== #region 生成Excel
/// <summary>
/// DataSet导出Excel
/// </summary>
/// <param name="arrTitle">列标题,若为null,则直接取dataset列标题</param>
/// <param name="ds">要导出的DataSet</param>
/// <param name="fileName">Excel文件名,不需要传入扩展名</param>
protected void CreateExcel(string[] arrTitle, DataSet ds, string fileName)
{
StringBuilder strb = new StringBuilder();
strb.Append(" <html xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
strb.Append("xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
strb.Append("xmlns=\"http://www.w3.org/TR/REC-html40\"");
strb.Append(" <head> <meta http-equiv='Content-Type' content='text/html; charset=gb2312'>");
strb.Append(" <style>");
strb.Append(".xl26");
strb.Append(" {mso-style-parent:style0;");
strb.Append(" font-family:\"Times New Roman\", serif;");
strb.Append(" mso-font-charset:0;");
strb.Append(" mso-number-format:\"@\";}");
strb.Append(" </style>");
strb.Append(" <xml>");
strb.Append(" <x:ExcelWorkbook>");
strb.Append("  <x:ExcelWorksheets>");
strb.Append("  <x:ExcelWorksheet>");
strb.Append("    <x:Name>Sheet1 </x:Name>");
strb.Append("    <x:WorksheetOptions>");
strb.Append("    <x:DefaultRowHeight>285 </x:DefaultRowHeight>");
strb.Append("    <x:Selected/>");
strb.Append("    <x:Panes>");
strb.Append("      <x:Pane>");
strb.Append("      <x:Number>3 </x:Number>");
strb.Append("      <x:ActiveCol>1 </x:ActiveCol>");
strb.Append("      </x:Pane>");
strb.Append("    </x:Panes>");
strb.Append("    <x:ProtectContents>False </x:ProtectContents>");
strb.Append("    <x:ProtectObjects>False </x:ProtectObjects>");
strb.Append("    <x:ProtectScenarios>False </x:ProtectScenarios>");
strb.Append("    </x:WorksheetOptions>");
strb.Append("  </x:ExcelWorksheet>");
strb.Append("  <x:WindowHeight>6750 </x:WindowHeight>");
strb.Append("  <x:WindowWidth>10620 </x:WindowWidth>");
strb.Append("  <x:WindowTopX>480 </x:WindowTopX>");
strb.Append("  <x:WindowTopY>75 </x:WindowTopY>");
strb.Append("  <x:ProtectStructure>False </x:ProtectStructure>");
strb.Append("  <x:ProtectWindows>False </x:ProtectWindows>");
strb.Append(" </x:ExcelWorkbook>");
strb.Append(" </xml>");
strb.Append("");
strb.Append(" </head> <body> <table align=\"center\" style='border-collapse:collapse;table-layout:fixed'> <tr>");

if (ds.Tables.Count > 0)
{
//写列标题 
if (arrTitle != null && arrTitle.Length > 0)
{
foreach (string strCol in arrTitle)
{
strb.Append(" <td> <b>" + strCol + " </b> </td>");
}
strb.Append(" </tr>");
}
else
{
int columncount = ds.Tables[0].Columns.Count;
for (int columi = 0; columi < columncount; columi++)
{
strb.Append(" <td> <b>" + ds.Tables[0].Columns[columi] + " </b> </td>");
}
strb.Append(" </tr>");
}

//写数据    
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
strb.Append(" <tr>");
for (int j = 0; j < ds.Tables[0].Columns.Count; j++)
{
strb.Append(" <td class='xl26'>" + ds.Tables[0].Rows[i][j].ToString() + " </td>");
}
strb.Append(" </tr>");
}
}
strb.Append(" </body> </html>");
Response.Clear();
Response.Buffer = true;
Response.Charset = "GB2312";
Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8) + ".xls");
Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");//设置输出流为简体中文  
Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。  
this.EnableViewState = false;
Response.Write(strb);
Response.End();
}
#endregion

//不过为什么导出Excel,单元格是受保护呢!
//导出word,只要把扩展名 .xls 改成 .doc即可。
//这个人也是用这个方法:http://wyf.javaeye.com/blog/531171


===============以往方法===============
#region 生成Excel
/// <summary>
/// DataSet导出Excel
/// </summary>
/// <param name="arrTitle">列标题,若为null,则直接取dataset列标题</param>
/// <param name="ds">要导出的DataSet</param>
/// <param name="fileName">Excel文件名,不需要传入扩展名</param>
protected void CreateExcel(string[] arrTitle, DataSet ds, string fileName)
{
HttpResponse resp;
resp = Page.Response;
resp.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
resp.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8) + ".xls");
string colHeaders = "", ls_item = "";
//定义表对象与行对象,同时用DataSet对其值进行初始化
System.Data.DataTable dt = ds.Tables[0];
DataRow[] myRow = dt.Select();//可以类似dt.Select("id>10")之形式达到数据筛选目的
int i = 0;
int cl = dt.Columns.Count;

//取得数据表各列标题,各标题之间以t分割,最后一个列标题后加回车符
if (arrTitle != null && arrTitle.Length > 0)
{
for (i = 0; i < arrTitle.Length; i++)
{
if (i == (arrTitle.Length - 1))//最后一列,加n
{
colHeaders += arrTitle[i] + "\n";
}
else
{
colHeaders +=arrTitle[i] + "\t";
}
}
}
else
{
for (i = 0; i < cl; i++)
{
if (i == (cl - 1))//最后一列,加n
{
colHeaders += dt.Columns[i].Caption.ToString() + "\n";
}
else
{
colHeaders += dt.Columns[i].Caption.ToString() + "\t";
}
}
}

resp.Write(colHeaders);
//向HTTP输出流中写入取得的数据信息
//逐行处理数据 
foreach (DataRow row in myRow)
{
//当前行数据写入HTTP输出流,并且置空ls_item以便下行数据   
for (i = 0; i < cl; i++)
{
if (i == (cl - 1))//最后一列,加n
{
ls_item += row[i].ToString() + "\n";
}
else
{
ls_item += row[i].ToString() + "\t";
}
}
resp.Write(ls_item);
ls_item = "";

}
resp.End();
}
#endregion

*****************************************************
细节说明

1.样式最好用css,即设style属性或class属性,有些样式属性excel不认的。th、td的宽度最好在colgroup中设

2.在excel的格子中换行,可以用这个<br style='mso-data-placement:same-cell;'/>

3.关于边框宽度的问题,如果你的table是全边框,可以设置table的border属性,其中0=不显示边框。

如果表的格式比较复杂,特别是表头,有些边要隐藏的,这个要先把table的border=0,之后对每个th td用css的边框样式进行设置,但这里有个地方要注意,就是宽度,设为0.5pt(例:border-left: 0.5pt solid #000;),如果设为1px输出的边框会很粗。

4.excel空余部分边框的问题。用此方法输出的excel,空余部分边框都不显示,如果要做成想普通excel的样子,需在输出流的head部分加上excel的设置,也可用于显示网格,例子如下:

<!--[if gte mso 9]>
<xml>
<x:ExcelWorkbook>
<x:ExcelWorksheets>
   <x:ExcelWorksheet>   
   <x:Name></x:Name>
    <x:WorksheetOptions>   
     <x:Selected/>   
     <x:Print>
       <x:ValidPrinterInfo/>
     </x:Print>  
    </x:WorksheetOptions>
   </x:ExcelWorksheet> 
</x:ExcelWorksheets>
</x:ExcelWorkbook>
</xml>
<![endif]-->

5.可能你要的数据就可以完全通过SQL查询操作返回一个DataSet,但是如果你的Excel想要的数据效果较复杂,通过SQL无法查询出或储存过程处理对应的逻辑也不好解决或查询性能各方面很不好,通过一些条件在重新取回不同的DataSet,来拼接对应的Excel的数据呈现,你就需要添加列,添加行,对一些数据的处理了。也可将多个DataSet处理,动态创建一个DataSet或DataView的处理,感兴趣可以试一下。

通过后台使用Microsoft.Office.Interop.Excel.dll如何实现DataSet保存为Excel的示例

找到博客园邀月两篇不错的博客,分享一下:

博客:DataSet导出到Excel比较完整的解决方案(一)--客户端生成文件
链接:http://www.cnblogs.com/downmoon/archive/2009/01/15/1376693.html

博客:DataSet导出到Excel比较完整的解决方案(二)--服务器端生成文件(downmoon)
链接:http://www.cnblogs.com/downmoon/archive/2009/01/16/1376702.html

还有两篇不错的:

博客:C# 导出Excel的示例
链接:http://www.cnblogs.com/springyangwc/archive/2011/08/12/2136498.html

博客:C# 将数据导出到Excel汇总
链接:http://www.cnblogs.com/xiaotao823/archive/2008/09/26/1299364.html

(注:你会发现互联网的好处和大家的分享精神,也让自己加入到这种分享知识中,为需要的人提供帮助,互联网的知识宝库!)

posted @ 2012-08-30 16:44  SanMaoSpace  阅读(2724)  评论(0编辑  收藏  举报