错误备忘_ASP.NET_ASP.NET GridView 导出 Excel 时发现的有趣现象

当我还在之前的公司时(那时刚毕业,我在之前的公司干了三年)领导让我能够将 GridView 显示出来的数据导出成 Excel 和 TXT 文件。本来这是一个很简单的功能,但是在实现过程中,还是经历了很多波折,期间还发现了一个很有趣的现象——原来微软的 Word 和 Excel 文件可以识别 HTML 标记。

本文内容

  • GridView 导出
  • 导出分析
  • 多 sheet 的 Excel
  • 补充

导出

本文旨在说明微软的 Word 和 Excel 文件可以识别 HTML 标记,它们的内部实现也是使用 HTML 标记。因此,只是简单说明一下。

对于导出时,涉及的一些问题,暂不考虑,如:

  • 导出的编码,否则,导出的 Excel 文件会乱码;
  • 要重构 VerifyRenderingInServerForm 方法,否则,会出现如下错误信息:

1_1R0Y3[@}28GAFQ%NG_GDR

  • 导出时的文件名应为 ".xls",而不能是 ".xlsx",这样,Word 2003 和 2007 都能打开。

导出 GridView 的数据代码如下:

<%@ Page Language="C#" %>
 
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
 
    <script runat="server">
   1:  
   2:         protected void Page_Load(object sender, EventArgs e)
   3:         {
   4:             if (!IsPostBack)
   5:             {
   6:                 DataTable dt = ExcelCharacteristic.DS.GetDataSource();
   7:                 this.GridView1.DataSource = dt;
   8:                 this.GridView1.DataBind();
   9:             }
  10:         }
  11:         protected void Button1_Click(object sender, EventArgs e)
  12:         {
  13:             Response.ClearContent();
  14:             Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
  15:             Response.AddHeader("content-disposition", "attachment; filename=MyExcel.xls");
  16:             Response.ContentType = "application/excel";
  17:             StringWriter sw = new StringWriter();
  18:             HtmlTextWriter htw = new HtmlTextWriter(sw);
  19:             this.GridView1.RenderControl(htw);
  20:             Response.Write(sw.ToString());
  21:             Response.End();
  22:         }
  23:         /// <summary>
  24:         /// 必须有
  25:         /// </summary>
  26:         /// <param name="control"></param>
  27:         public override void VerifyRenderingInServerForm(Control control)
  28:         {
  29:  
  30:         }
  31:     
</script>
 
</head>
<body>
    <form id="form1" runat="server">
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
        <Columns>
            <asp:BoundField DataField="EMPNO" HeaderText="员工编号" />
            <asp:BoundField DataField="ENAME" HeaderText="员工姓名" />
            <asp:BoundField DataField="JOB" HeaderText="职位" />
            <asp:BoundField DataField="MGR" HeaderText="上级编号" />
            <asp:BoundField DataField="HIREDATE" HeaderText="出生日期" />
            <asp:BoundField DataField="SAL" HeaderText="工资" />
            <asp:BoundField DataField="DEPTNO" HeaderText="部门" />
        </Columns>
    </asp:GridView>
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="导出" />
    </form>
</body>
</html>

运行界面:

L$1[1H_T579M]])]K(RCN}G

图1 运行界面

说明:

1,导出的文件为 "MyExcel.xls"。

导出分析

当点击“导出”按钮并保存后,用文本编辑器查看导出后的 "MyExcel.xls" 文件,看到的竟然是 HTML 代码。 如下所示:

<div>
    <table cellspacing="0" rules="all" border="1" id="GridView1" style="border-collapse:collapse;">
        <tr>
            <th scope="col">员工编号</th><th scope="col">员工姓名</th><th scope="col">职位</th><th scope="col">上级编号</th><th scope="col">出生日期</th><th scope="col">工资</th><th scope="col">部门</th>
        </tr><tr>
            <td>7369</td><td>SMITH</td><td>CLERK</td><td>7902</td><td>1980-12-17</td><td>800</td><td>20</td>
        </tr><tr>
            <td>7499</td><td>ALLEN</td><td>SALESMAN</td><td>7698</td><td>1981-02-20</td><td>1600</td><td>30</td>
        </tr><tr>
            <td>7521</td><td>WARD</td><td>SALESMAN</td><td>7698</td><td>1981-02-22</td><td>1250</td><td>30</td>
        </tr><tr>
            <td>7566</td><td>JONES</td><td>MANAGER</td><td>7839</td><td>1981-04-02</td><td>2975</td><td>20</td>
        </tr><tr>
            <td>7654</td><td>MARTIN</td><td>SALESMAN</td><td>7698</td><td>1981-09-28</td><td>1250</td><td>30</td>
        </tr><tr>
            <td>7698</td><td>BLAKE</td><td>MANAGER</td><td>7839</td><td>1981-05-01</td><td>2850</td><td>30</td>
        </tr><tr>
            <td>7782</td><td>CLARK</td><td>MANAGER</td><td>7839</td><td>1981-06-09</td><td>2450</td><td>10</td>
        </tr><tr>
            <td>7788</td><td>SCOTT</td><td>ANALYST</td><td>7566</td><td>1987-04-19</td><td>3000</td><td>20</td>
        </tr><tr>
            <td>7839</td><td>KING</td><td>PRESIDENT</td><td>&nbsp;</td><td>1981-11-17</td><td>5000</td><td>10</td>
        </tr><tr>
            <td>7844</td><td>TURNER</td><td>SALESMAN</td><td>7698</td><td>1981-09-08</td><td>1500</td><td>30</td>
        </tr><tr>
            <td>7876</td><td>ADAMS</td><td>CLERK</td><td>7788</td><td>1987-05-23</td><td>1100</td><td>20</td>
        </tr><tr>
            <td>7900</td><td>JAMES</td><td>CLERK</td><td>7698</td><td>1981-12-03</td><td>950</td><td>30</td>
        </tr><tr>
            <td>7902</td><td>FORD</td><td>ANALYST</td><td>7566</td><td>1981-12-03</td><td>3000</td><td>20</td>
        </tr><tr>
            <td>7934</td><td>MILLER</td><td>CLERK</td><td>7782</td><td>1982-01-23</td><td>1300</td><td>10</td>
        </tr>
    </table>
</div>

代码段1 用 文本编辑器打开

而用 Microsoft Excel 打开该文件:

用 Microsoft Excel 打开

图2 用 Microsoft Excel 打开

注意:

对比代码段1 和 图2。代码段1的最外层是一个 <div>,里边是一个 <table>。这个 HTML 代码让 Microsoft Excel 出来后,就变成了图2。

多 sheet 的 Excel

现在,在这个 Excel 文件里新建一个 sheet。

新建一个名为 "NewMyExcel" sheet

图3 新建一个名为 "NewMyExcel" sheet

这么看不出什么来,看下你的电脑,Microsoft Excel 竟然为 "MyExcel.xls" 创建了一个文件夹。

Microsoft Excel 为 "MyExcel.xls" 创建了一个文件夹

图4 Microsoft Excel 为 "MyExcel.xls" 创建了一个文件夹

MyExcel.files 文件夹的内容

图5 MyExcel.files 文件夹的内容

补充

当初,我有两方面的导出工作要做。

  • 一方面是像系统日志、统计信息等,这样简单导出,只要按本文的 GridView 导出即可。
  • 另一方面是业务的导出,需要在服务端进行相当复杂的处理后导出成 Excel 或 文本文件。现在想来,这种情况的导出,导出成 Excel 完全是扯淡,客户完全用不了,这些数据是通过机器采集记录到文本文件,也就是说,每行的每列都有特殊含义(对应数据库某个表的某个字段),用程序搞到数据库的多个表里,导出是想把这些数据恢复成文本文件。

起初,我想用微软的 COM 组件,但是在 Web 系统下,总出现权限问题,服了,领导催得急,我又突然发现这个现象,于是就用程序,直接创建 HTML 标记,导出得了。考虑若是导出超过 6 万行,就用程序创建多个 sheet。

我还没扩展我的程序,就跳槽了……谢天谢地……

下载 Demo

原文地址:https://www.cnblogs.com/liuning8023/p/2199038.html