在ASP.NET Web Forms中使用页面导出伪xls Excel表格

将数据导出为Excel表格是比较常见的需求,也有很多组件支持导出真正的Excel表格。由于Excel能打开HTML文件,并支持其中的table元素以及p之类的文本元素的显示,所以把.html扩展名改为.xls是比较常用的一种方式。当然这只是一种骗人的伎俩,所以我称之为伪xls表格。不过对于要求不高的需求,这种方法还是比较简单快捷的。

在Web Forms项目中,除了用代码拼凑HTML元素标记外,还可以直接用窗体页面渲染HTML表格。Web Forms就是用来渲染动态HTML的,直接利用它,支持代码提示、智能感知,何乐而不为呢?

现在就做一个用于导出表格的页面。为了实现代码复用,应该设计一个这样的类:它继承自Page基类,把它用作页面代码隐藏类的基类,只要执行这个页面,就能直接导出伪xls表格。实现代码如下:

using System;
using System.Web;
using System.Web.UI;

namespace FakeXlsExportWebForms
{
    /// <summary>
    /// 导出伪xls文件的页面基类。
    /// 用于导出表格文件的页面应该继承此类,并在页面生成表格元素。
    /// 重定向到派生类页面即可导出表格。
    /// </summary>
    public class FakeXlsPage : Page
    {
        protected string FileName { get; set; } = Guid.NewGuid().ToString();

        public FakeXlsPage()
        {
            // 不能注册更早的页面事件,否则文件名设置无效
            PreRender += (s, e) =>
            {
                Response.ContentType = "application/vnd.ms-excel";
                // 调用UrlEncode方法以编码中文,防止浏览器显示文件名乱码
                string fileName = HttpUtility.UrlEncode(FileName + ".xls");
                Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
            };
        }
    }
}

有了这个类,只消新建页面,修改基类,然后在页面上生成table元素即可。下面看一个实际的例子,导出一些学生信息。

首先建立一个表示表格数据模型的类:

namespace FakeXlsExportWebForms
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public char Gender { get; set; }
        public int Age { get; set; }
        public double ChineseScore { get; set; }
        public double MathScore { get; set; }
        public double EnglishScore { get; set; }
    }
}

然后新建一个用于生成表格的页面,其页面代码如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XlsExport.aspx.cs" Inherits="FakeXlsExportWebForms.XlsExport" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <%-- 设置border="1"以显示表格框线 --%>
    <table border="1">
        <%-- caption元素可以生成表标题,其单元格列跨度为表格的列数 --%>
        <caption>学生成绩表</caption>
        <tr>
            <%-- 可以使用rowspan和colspan来合并单元格 --%>
            <th rowspan="2">编号</th>
            <th rowspan="2">学号</th>
            <th rowspan="2">姓名</th>
            <th rowspan="2">性别</th>
            <th rowspan="2">年龄</th>
            <th colspan="3">成绩</th>
        </tr>
        <tr>
            <th>语文</th>
            <th>数学</th>
            <th>英语</th>
        </tr>
        <asp:Repeater ID="rptStudents" ItemType="FakeXlsExportWebForms.Student" SelectMethod="GetStudents" runat="server">
            <ItemTemplate>
                <tr>
                    <td><%# Container.ItemIndex + 1 %></td>
                    <td><%# Item.Id %></td>
                    <td><%# Item.Name %></td>
                    <td><%# Item.Gender %></td>
                    <td><%# Item.Age %></td>
                    <td><%# Item.ChineseScore %></td>
                    <td><%# Item.MathScore %></td>
                    <td><%# Item.EnglishScore %></td>
                </tr>
            </ItemTemplate>
        </asp:Repeater>
    </table>
    <%-- 表格后面的文字可作为表注,不要把它包含在p元素中,否则表格与表注之间会有一行空行 --%>
    注:共计<%= rptStudents.Items.Count %>人。
</body>
</html>

其后台代码如下,页面的基类已修改,并且其中包含页面中的Repeater控件使用的数据方法:

using System;
using System.Collections.Generic;

namespace FakeXlsExportWebForms
{
    public partial class XlsExport : FakeXlsPage
    {
        public void Page_Load(object sender, EventArgs e)
        {
            // 设置基类的文件名属性
            FileName = "学生成绩表";
        }

        public IEnumerable<Student> GetStudents()
        {
            // 简单生成一些测试数据
            for (int i = 0; i < 10; i++)
            {
                yield return new Student
                {
                    Id = 2016000 + i + 1,
                    Name = "学生" + (i + 1),
                    Gender = i % 2 == 0 ? ‘男‘ : ‘女‘,
                    Age = 10 + i,
                    ChineseScore = 90 + i,
                    MathScore = 80 + i,
                    EnglishScore = 70 + i
                };
            }
        }
    }
}

现在直接打开这个页面,浏览器就会下载表格文件了。也可以定义一个普通页面,在其中定义一个用于导出表格的链接:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FakeXlsExportWebForms.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <asp:HyperLink NavigateUrl="~/XlsExport.aspx" runat="server">导出学生成绩表</asp:HyperLink>
</body>
</html>

效果如图,点击链接,浏览器会下载表格文件:

打开文件如图:

不过话说回来,这种方式导出的表格还是有很多缺点的,比如:

  1. Excel 2003能直接打开,高版本的Excel会提示格式不正确,但点“是”之后也能打开;
  2. 包含数据的单元格以外的单元格不显示边框;
  3. 编辑导出的表格之后,直接保存会提示格式问题,如果确定保存,会生成另一个文件夹(如下图,伪xls文件现在需要此文件夹中的文件),导致表格文件不能通过一个单独的文件来维护。当然可以将其另存为真正的Excel文件,只要你的客户不会怨声载道。

时间: 2024-10-08 22:19:46

在ASP.NET Web Forms中使用页面导出伪xls Excel表格的相关文章

如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites]

如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites] 一.布局页面介绍[About Layout Pages] 很多网站有些内容需要显示在各个页面中,比如Header,Footer或者告诉用户已经登录的部分.ASP.NET允许你创建一个单独的文件来包含文本.标签和代码的内容块,从而搭建一个风格整齐的网站.接下来你就可以将这个内容块插入到任何你想要让它展示的页面中.采用这种方法

Asp.Net Web Forms/MVC/Console App中使用Autofac

本来简单介绍了Autofac在Asp.Net Web Forms中的应用,后来又添加了mvc.控制台应用程序中使用Autofac,详情请看源码. ASP.NET Web Forms使用Autofac,至少需要一下步骤: 1,引用Autofac程序集. 2,添加Autofac Web Modules 到 Web.config. 3,在Global.asax中实现IContainerProviderAccessor接口. 我们创建一个ASP.NET Web Forms项目,命名为WebFormStu

ASP.NET Web Forms 4.5的新特性

作者:Parry出处:http://www.cnblogs.com/parry/ 一.强类型数据控件 在出现强类型数据控件前,我们绑定数据控件时,前台一般使用Eval或者DataBinder.Eval(Container.DataItem,"FieldName")的形式. 1 <%# DataBinder.Eval(Container.DataItem,"FieldName") %>2 <%# Eval("FieldName")

ASP.NET Web Forms 的 DI 應用範例

跟 ASP.NET MVC 与 Web API 比起来,在 Web Forms 应用程式中使用 Dependency Injection 要来的麻烦些.这里用一个范例来说明如何注入相依物件至 Web Forms 的 ASPX 页面. 使用的开发工具与类别库: Visual Studio 2013 .NET Framework 4.5 Unity 3.5.x 问题描述 基于测试或其他原因,希望 ASPX 网页只依赖特定服务的介面,而不要依赖具象类别. 假设首页 Default.aspx 需要一个传

ASP.NET Web Forms的改进

虽然ASP.NET Web Forms不是vNext计划的一部分,但它并没有被忽视.作为Visual Studio 2013 Update 2的一部分,它重新开始支持新工具.EF集成和Roslyn. 为什么Web Forms不是ASP.NET vNext的一部分 作为开始,让我们先为这个坏消息做下解释.为了改进性能和跨平台可移植性,ASP.NET vNext正在消除对System.Web的依赖.与OWIN相比,它缓慢而庞大,使测试工作多了不必要的麻烦. 虽然他们已经多次尝试将其分离出来,但Web

【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

参考页面: http://www.yuanjiaocheng.net/webapi/create-crud-api-1-delete.html http://www.yuanjiaocheng.net/webapi/Consume-web-api.html http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-po

ASP.NET Web网站中App_Code文件夹的作用及使用场景

原文地址:Web Site项目和ASP.NET Web Application中App_Code文件夹的作用作者:宾的宾 我现在要建一个ASP.NET的网站了,不难吧,开始动手.如下图: 这种方法建立Web Site项目,使用过的开发者都知道,如果需要新建一个类,例如DataBase.cs.此类只服务于web页面,不适于放入网站自身类库中,因此希望其独立存在于类库之外,只是用于在web应用程序中被web页面调用.这样一来此类最好不要通过形成dll文件,并将其放入bin文件夹以供web页面调用.但

ASP.NET Web Application中使用链接文件

最近重构一个内部的平台系统,作为一个平台,其下有几个子系统,每个子系统有自己的网站系统.而每个网站使用的是统一的风格,统一的验证机制,反馈系统,等等.所以,为了避免几个子系统中重复出现相同的资源或文件,我打算将以前的ASP.NET Web Site全部转换为ASP.NET Web Application,然后通过链接外部公共文件的方式解决这个问题.同时: 1. Web Application是Web Site的升级产品.2. Web Application允许添加链接方式,把其他目录的文件作为链

在ASP.NET Web Forms中用System.Web.Optimization取代SquishIt

将一个ASP.NET Web Forms项目从.NET Framework 4.0升级至.NET Framework 4.5之后,发现SquishIt竟然引发了HTTP Error 500.0 - Internal Server Error. SquishIt是一个开源的支持ASP.NET的js/css打包工具,项目地址:https://github.com/jetheredge/SquishIt,出生早于Microsoft ASP.NET Web Optimization Framework(