本文原创地址: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) || " ".Equals(gvrNext.Cells[mergeKey.Value].Text)))) && ((mergeMode == 1 && gvr.Cells[cellNum].Text == gvrNext.Cells[cellNum].Text) || (mergeMode == 2 && " ".Equals(gvrNext.Cells[cellNum].Text.Trim())) || (mergeMode == 3 && (gvr.Cells[cellNum].Text == gvrNext.Cells[cellNum].Text || " ".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 }
函数调用如下:
PS: 以上代码可以生成下列Excel文件,但是未经严格测试,或有错漏,请引用或使用本文代码的诸君注意。
导出效果如下图: