【转】C# DataTable 导出 Excel 进阶 多行表头、合并单元格、中文文件名乱码

本文原创地址:http://blog.csdn.net/ranbolwb/article/details/8083983 ,转载请保留本行。

本例子是上一篇 DataTable 导出 Excel 的进阶,除了上一篇提到的处理乱码问题,本例还添加了处理多行表头、合并单元格的功能及处理中文文件名乱码问题,应该可以满足日常开发的需要了。

废话不多说了,直接上代码:

[C#] 可以写单独类
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Web;
  4 using System.Configuration;
  5 using System.Data;
  6 using System.Data.Common;
  7 using System.Data.OleDb;
  8 using System.Web.UI.WebControls;
  9 using System.Text.RegularExpressions;
 10 
 11 /// <summary>
 12 /// Common 的摘要说明
 13 /// 作者:李伟波
 14 /// 时间:2012-10-18
 15 /// </summary>
 16 public class Common
 17 {
 18     public Common()
 19     {
 20         //
 21         //TODO: 在此处添加构造函数逻辑
 22         //
 23     }
 24 
 25     /// <summary>
 26     /// 描述:把DataTable内容导出excel并返回客户端 
 27     /// 作者:李伟波
 28     /// 时间:2012-10-18
 29     /// </summary>
 30     /// <param name="dtData"></param>
 31     /// <param name="header"></param>
 32     /// <param name="fileName"></param>
 33     /// <param name="mergeCellNums">要合并的列索引字典 格式:列索引-合并模式(合并模式 1 合并相同项、2 合并空项、3 合并相同项及空项)</param>
 34     /// <param name="mergeKey">作为合并项的标记列索引</param>
 35     public static void DataTable2Excel(System.Data.DataTable dtData, TableCell[] header, string fileName, Dictionary<int, int> mergeCellNums, int? mergeKey)
 36     {
 37         System.Web.UI.WebControls.GridView gvExport = null;
 38         // 当前对话 
 39         System.Web.HttpContext curContext = System.Web.HttpContext.Current;
 40         // IO用于导出并返回excel文件 
 41         System.IO.StringWriter strWriter = null;
 42         System.Web.UI.HtmlTextWriter htmlWriter = null;
 43 
 44         if (dtData != null)
 45         {
 46             // 设置编码和附件格式 
 47             curContext.Response.ContentType = "application/vnd.ms-excel";
 48             curContext.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
 49             curContext.Response.Charset = "gb2312";
 50             if (!string.IsNullOrEmpty(fileName))
 51             {
 52                 //处理中文名乱码问题
 53                 fileName = System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);
 54                 curContext.Response.AppendHeader("Content-Disposition", ("attachment;filename=" + (fileName.ToLower().EndsWith(".xls") ? fileName : fileName + ".xls")));
 55             }
 56             // 导出excel文件 
 57             strWriter = new System.IO.StringWriter();
 58             htmlWriter = new System.Web.UI.HtmlTextWriter(strWriter);
 59 
 60             // 重新定义一个无分页的GridView 
 61             gvExport = new System.Web.UI.WebControls.GridView();
 62             gvExport.DataSource = dtData.DefaultView;
 63             gvExport.AllowPaging = false;
 64             //优化导出数据显示,如身份证、12-1等显示异常问题
 65             gvExport.RowDataBound += new System.Web.UI.WebControls.GridViewRowEventHandler(dgExport_RowDataBound);
 66 
 67             gvExport.DataBind();
 68             //处理表头
 69             if (header != null && header.Length > 0)
 70             {
 71                 gvExport.HeaderRow.Cells.Clear();
 72                 gvExport.HeaderRow.Cells.AddRange(header);
 73             }
 74             //合并单元格
 75             if (mergeCellNums != null && mergeCellNums.Count > 0)
 76             {
 77                 foreach (int cellNum in mergeCellNums.Keys)
 78                 {
 79                     MergeRows(gvExport, cellNum, mergeCellNums[cellNum], mergeKey);
 80                 }
 81             }
 82 
 83             // 返回客户端 
 84             gvExport.RenderControl(htmlWriter);
 85             curContext.Response.Clear();
 86             curContext.Response.Write("<meta http-equiv=\"content-type\" content=\"application/ms-excel; charset=gb2312\"/>" + strWriter.ToString());
 87             curContext.Response.End();
 88         }
 89     }
 90     /// <summary>
 91     /// 描述:行绑定事件
 92     /// </summary>
 93     /// <param name="sender"></param>
 94     /// <param name="e"></param>
 95     protected static void dgExport_RowDataBound(object sender, GridViewRowEventArgs e)
 96     {
 97         if (e.Row.RowType == DataControlRowType.DataRow)
 98         {
 99             foreach (TableCell cell in e.Row.Cells)
100             {
101                 //优化导出数据显示,如身份证、12-1等显示异常问题
102                 if (Regex.IsMatch(cell.Text.Trim(), @"^\d{12,}$") || Regex.IsMatch(cell.Text.Trim(), @"^\d+[-]\d+$"))
103                 {
104                     cell.Attributes.Add("style", "vnd.ms-excel.numberformat:@");
105                 }
106             }
107         }
108     }
109 
110     /// <summary>   
111     /// 描述:合并GridView列中相同的行
112     /// 作者:李伟波
113     /// 时间:2012-10-18
114     /// </summary>   
115     /// <param   name="gvExport">GridView对象</param>   
116     /// <param   name="cellNum">需要合并的列</param>   
117     /// <param name="mergeMode">合并模式 1 合并相同项、2 合并空项、3 合并相同项及空项</param>
118     /// <param name="mergeKey">作为合并项的标记列索引</param>
119     public static void MergeRows(GridView gvExport, int cellNum, int mergeMode, int? mergeKey)
120     {
121         int i = 0, rowSpanNum = 1;
122         System.Drawing.Color alterColor = System.Drawing.Color.LightGray;
123         while (i < gvExport.Rows.Count - 1)
124         {
125             GridViewRow gvr = gvExport.Rows[i];
126             for (++i; i < gvExport.Rows.Count; i++)
127             {
128                 GridViewRow gvrNext = gvExport.Rows[i];
129                 if ((!mergeKey.HasValue || (mergeKey.HasValue && (gvr.Cells[mergeKey.Value].Text.Equals(gvrNext.Cells[mergeKey.Value].Text) || "&nbsp;".Equals(gvrNext.Cells[mergeKey.Value].Text)))) && ((mergeMode == 1 && gvr.Cells[cellNum].Text == gvrNext.Cells[cellNum].Text) || (mergeMode == 2 && "&nbsp;".Equals(gvrNext.Cells[cellNum].Text.Trim())) || (mergeMode == 3 && (gvr.Cells[cellNum].Text == gvrNext.Cells[cellNum].Text || "&nbsp;".Equals(gvrNext.Cells[cellNum].Text.Trim())))))
130                 {
131                     gvrNext.Cells[cellNum].Visible = false;
132                     rowSpanNum++;
133                     gvrNext.BackColor = gvr.BackColor;
134                 }
135                 else
136                 {
137                     gvr.Cells[cellNum].RowSpan = rowSpanNum;
138                     rowSpanNum = 1;
139                     //间隔行加底色,便于阅读
140                     if (mergeKey.HasValue && cellNum == mergeKey.Value)
141                     {
142                         if (alterColor == System.Drawing.Color.White)
143                         {
144                             gvr.BackColor = System.Drawing.Color.LightGray;
145                             alterColor = System.Drawing.Color.LightGray;
146                         }
147                         else
148                         {
149                             alterColor = System.Drawing.Color.White;
150                         }
151                     }
152                     break;
153                 }
154                 if (i == gvExport.Rows.Count - 1)
155                 {
156                     gvr.Cells[cellNum].RowSpan = rowSpanNum;
157                     if (mergeKey.HasValue && cellNum == mergeKey.Value)
158                     {
159                         if (alterColor == System.Drawing.Color.White)
160                             gvr.BackColor = System.Drawing.Color.LightGray;
161                     }
162                 }
163             }
164         }
165     }
166 }

 

 

函数调用如下:
[C#]
 1         TableCell[] header = new TableCell[29];
 2         for (int i = 0; i < header.Length; i++)
 3         {
 4             header[i] = new TableHeaderCell();
 5         }
 6         header[0].ColumnSpan = 7;
 7         header[0].Text = "订单基本信息";
 8         header[1].ColumnSpan = 4;
 9         header[1].Text = "收货人信息";
10         header[2].ColumnSpan = 4;
11         header[2].Text = "快递信息";
12         header[3].ColumnSpan = 3;
13         header[3].Text = "支付信息";
14         header[4].ColumnSpan = 6;
15         header[4].Text = "商品信息</th></tr><tr>";
16         //第二行
17         header[5].Text = "订单编号";
18         header[6].Text = "订单类型";
19         header[7].Text = "订单状态";
20         header[8].Text = "下单时间";
21         header[9].Text = "支付时间";
22         header[10].Text = "发货时间";
23         header[11].Text = "备注";
24 
25         header[12].Text = "收货人姓名";
26         header[13].Text = "地址";
27         header[14].Text = "手机号码";
28         header[15].Text = "配送方式";
29 
30         header[16].Text = "物流公司名称";
31         header[17].Text = "物流发货单";
32         header[18].Text = "运费收入";
33         header[19].Text = "实际配送费";
34 
35         header[20].Text = "订单总额";
36         header[21].Text = "支付方式";
37         header[22].Text = "订单支付金额";
38 
39         header[23].Text = "商品编号";
40         header[24].Text = "商品名称";
41         header[25].Text = "商品价格";
42         header[26].Text = "购买数量";
43         header[27].Text = "商品总金额";
44         header[28].Text = "优惠金额</th>";
45 
46         DataTable dt = Common.DbHelper.DBClass_GetDataToTable(sqlDHD, sqlParam, ref rMsg);
47 
48         Dictionary<int, int> mergeCellNums = new Dictionary<int, int>();
49         for (int i = 0; i < dt.Columns.Count; i++)
50         {
51             mergeCellNums.Add(i, 2);
52         }
53         Common.DataTable2Excel(dt, header, "数据导出" + DateTime.Now.ToString("yyyyMMdd"), mergeCellNums, 0);

 

PS: 以上代码可以生成下列Excel文件,但是未经严格测试,或有错漏,请引用或使用本文代码的诸君注意。

导出效果如下图:


 
posted @ 2015-01-14 17:48  火中泪  阅读(1320)  评论(0编辑  收藏  举报