将表格内容导出为Excel文件是实际项目中的常见需求,怎么来实现呢?
首先我们需要理解的一点是,导出的文件其实一个HTML片段,只不过Excel会按照自身的格式自动格式化而已。
来看一个导出文件的典型示例:
1: <table border="1">
2: <tr><th>姓名</th><th>性别</th></tr>
3: <tr><th>张三</th><th>男</th></tr>
4: <tr><th>李四</th><th>男</th></tr>
5: <tr><th>春花</th><th>女</th></tr>
6: </table>
将此文件后缀改成xls,并用Excel打开后可见:
首先来看下如何将Asp.Net的GridView导出为Excel文件,网上已经有很好的参考资料,这是博客园中的中文译本。
概括说来有如下几个技巧:
下面来看一个示例,示例的ASPX标签结构如下:
1: <asp:GridView ID="GridView1" Width="900px" DataKeyNames="Id,Name" AutoGenerateColumns="False"
2: runat="server">
3: <Columns>
4: <asp:TemplateField>
5: <ItemTemplate>
6: <asp:Label ID="Label1" runat="server" Text='<%# Container.DataItemIndex + 1 %>'></asp:Label>
7: </ItemTemplate>
8: </asp:TemplateField>
9: <asp:BoundField DataField="Name" HeaderText="姓名" />
10: <asp:TemplateField HeaderText="性别">
11: <ItemTemplate>
12: <asp:Label ID="Label2" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></asp:Label>
13: </ItemTemplate>
14: </asp:TemplateField>
15: <asp:BoundField DataField="EntranceYear" HeaderText="入学年份" />
16: <asp:CheckBoxField DataField="AtSchool" HeaderText="是否在校" />
17: <asp:HyperLinkField HeaderText="所学专业" DataTextField="Major" DataTextFormatString="{0}"
18: DataNavigateUrlFields="Major" DataNavigateUrlFormatString="http://gsa.ustc.edu.cn/search?q={0}"
19: Target="_blank" />
20: <asp:ImageField DataImageUrlField="Group" DataImageUrlFormatString="~/images/16/{0}.png"
21: HeaderText="分组">
22: </asp:ImageField>
23: </Columns>
24: </asp:GridView>
表格初始化代码省略,我们来看下和导出相关的代码:
1: public override void VerifyRenderingInServerForm(Control control)
2: {
3:
4: }
5:
6: protected void Button2_Click(object sender, EventArgs e)
7: {
8: // ResolveGridView(GridView1);
9:
10: Response.ClearContent();
11: Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
12: Response.ContentType = "application/excel";
13:
14: StringWriter sw = new StringWriter();
15: HtmlTextWriter htw = new HtmlTextWriter(sw);
16: GridView1.RenderControl(htw);
17:
18: Response.Write(sw.ToString());
19: Response.End();
20: }
这里做了如下几件事情:
我们来看下页面的UI显示和导出的Excel的内容:
在上面导出的Excel表格中,有两个地方需要进一步优化:
实现起来也很简单,只需要遍历GridView实例,修改其中的复选框控件和图片控件即可,如下所示:
1: private void ResolveGridView(Control ctrl)
2: {
3: for (int i = 0; i < ctrl.Controls.Count; i++)
4: {
5: // 图片的完整URL
6: if (ctrl.Controls[i].GetType() == typeof(AspNet.Image))
7: {
8: AspNet.Image img = ctrl.Controls[i] as AspNet.Image;
9: img.ImageUrl = Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, Page.ResolveUrl(img.ImageUrl));
10: }
11:
12: // 将CheckBox控件转化为静态文本
13: if (ctrl.Controls[i].GetType() == typeof(AspNet.CheckBox))
14: {
15: Literal lit = new Literal();
16: lit.Text = (ctrl.Controls[i] as AspNet.CheckBox).Checked ? "√" : "×";
17: ctrl.Controls.RemoveAt(i);
18: ctrl.Controls.AddAt(i, lit);
19: }
20:
21: if (ctrl.Controls[i].HasControls())
22: {
23: ResolveGridView(ctrl.Controls[i]);
24: }
25: }
26: }
最终的结果:
前面介绍了如何将Asp.Net的GridView控件导出为Excel,简单来说就是将GridView重新渲染到HtmlTextWriter流中,然后将流内容输入为响应正文。
那么我们是否也可以照葫芦画瓢来实现将Grid导出为Excel文件呢?
下面就来试一试,首先来看ASPX标签结构:
1: <ext:Grid ID="Grid1" Title="表格" ShowBorder="true" ShowHeader="true" Width="900px"
2: AutoHeight="true" runat="server" DataKeyNames="Id,Name">
3: <Columns>
4: <ext:TemplateField Width="60px">
5: <ItemTemplate>
6: <asp:Label ID="Label1" runat="server" Text='<%# Container.DataItemIndex + 1 %>'></asp:Label>
7: </ItemTemplate>
8: </ext:TemplateField>
9: <ext:BoundField Width="100px" DataField="Name" DataFormatString="{0}" HeaderText="姓名" />
10: <ext:TemplateField Width="60px" HeaderText="性别">
11: <ItemTemplate>
12: <asp:Label ID="Label3" runat="server" Text='<%# GetGender(Eval("Gender")) %>'></asp:Label>
13: </ItemTemplate>
14: </ext:TemplateField>
15: <ext:BoundField Width="60px" DataField="EntranceYear" HeaderText="入学年份" />
16: <ext:CheckBoxField Width="60px" RenderAsStaticField="true" DataField="AtSchool" HeaderText="是否在校" />
17: <ext:HyperLinkField HeaderText="所学专业" DataToolTipField="Major" DataTextField="Major"
18: DataTextFormatString="{0}" DataNavigateUrlFields="Major" DataNavigateUrlFormatString="http://gsa.ustc.edu.cn/search?q={0}"
19: DataNavigateUrlFieldsEncode="true" Target="_blank" ExpandUnusedSpace="True" />
20: <ext:ImageField Width="60px" DataImageUrlField="Group" DataImageUrlFormatString="~/images/16/{0}.png"
21: HeaderText="分组"></ext:ImageField>
22: <ext:BoundField Width="100px" DataField="LogTime" DataFormatString="{0:yy-MM-dd}"
23: HeaderText="注册日期" />
24: </Columns>
25: </ext:Grid>
26: <ext:Button ID="Button1" EnableAjax="false" DisableControlBeforePostBack="false"
27: runat="server" Text="将Grid导出为Excel文件" OnClick="Button1_Click">
28: </ext:Button>
请注意这里ext:Button的属性:
来看下后台按钮事件处理函数:
1: protected void Button1_Click(object sender, EventArgs e)
2: {
3: Response.ClearContent();
4: Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
5: Response.ContentType = "application/excel";
6:
7: StringWriter sw = new StringWriter();
8: HtmlTextWriter htw = new HtmlTextWriter(sw);
9: Grid1.RenderControl(htw);
10:
11: Response.Write(sw.ToString());
12: Response.End();
13: }
点击导出按钮,用记事本打开生成的Excel文件:
1: <div id="Grid1_wrapper">
2: <div id="Grid1_tpls" class="x-grid-tpls x-hide-display">
3: <div class="x-grid-tpl" id="Grid1_c0r0">
4: <span id="Grid1_c0r0_Label1">1</span>
5: </div>
6: <div class="x-grid-tpl" id="Grid1_c2r0">
7: <span id="Grid1_c2r0_Label3">女</span>
8: </div>
9: <div class="x-grid-tpl" id="Grid1_c0r1">
10: <span id="Grid1_c0r1_Label1">2</span>
11: </div>
12: // 省略类似的部分...
13: </div>
14: </div>
结果只看到一些DIV,而非Table结构。仔细观察这些DIV,你会发现它们是模板列渲染后的值,其他列的值哪去了?
如果你理解extjs的工作原理,这个结果并不奇怪。
Grid渲染到页面中的只有一些简单的DIV标签,至于内部的内容则是通过JavaScript来生成的,这个JavaScript就隐藏在页面的底部,如果你观察生成的页面源代码的话,就能看到类似的代码:
而这些Values值正是渲染后的HTML片段,并且我们可以通过行GridRow的Values属性拿到这些值!
如此一来就好办了,拿到这些值后手工拼装成一个表格不就可以了,最终的代码如下所示:
1: protected void Button1_Click(object sender, EventArgs e)
2: {
3: Response.ClearContent();
4: Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
5: Response.ContentType = "application/excel";
6: Response.Write(GetGridTableHtml(Grid1));
7: Response.End();
8: }
9:
10: private string GetGridTableHtml(Grid grid)
11: {
12: StringBuilder sb = new StringBuilder();
13:
14: sb.Append("<table cellspacing=\"0\" rules=\"all\" border=\"1\" style=\"border-collapse:collapse;\">");
15:
16: sb.Append("<tr>");
17: foreach (GridColumn column in grid.Columns)
18: {
19: sb.AppendFormat("<td>{0}</td>", column.HeaderText);
20: }
21: sb.Append("</tr>");
22:
23:
24: foreach (GridRow row in grid.Rows)
25: {
26: sb.Append("<tr>");
27: foreach (object value in row.Values)
28: {
29: string html = value.ToString();
30: // 处理CheckBox
31: if (html.Contains("box-grid-static-checkbox"))
32: {
33: if (html.Contains("box-grid-static-checkbox-uncheck"))
34: {
35: html = "×";
36: }
37: else
38: {
39: html = "√";
40: }
41: }
42:
43: // 处理图片
44: if (html.Contains("<img"))
45: {
46: string prefix = Request.Url.AbsoluteUri.Replace(Request.Url.AbsolutePath, "");
47: html = html.Replace("src=\"", "src=\"" + prefix);
48: }
49:
50: sb.AppendFormat("<td>{0}</td>", html);
51: }
52: sb.Append("</tr>");
53: }
54:
55: sb.Append("</table>");
56:
57: return sb.ToString();
58: }
正如你看到的,这里面也对复选框和图片进行了处理:
来看最终的效果:
将表格内容导出为Excel文件在实际项目中经常会遇到,本篇文章从导出Asp.Net的GridView开始,循序渐进地讲解如何导出FineUI的Grid控件,最终得到我们满意的结果。
下一篇文章我们会开始新的征程,接着讲解树控件、选项卡控件、手风琴控件以及窗体控件。