WEB报表至WORD,打印工具类库

时间:2022-05-01 06:22:10

前些日子做了一个WEB报表工具类库,功能是在Word中定制表格。下文是设计文档。这个工具不大,而且有重新发明*的嫌疑,唉!不过既然已经做出来了,总不能扔掉吧。如有兴趣可以下载试试看。共同进步!

 

下载地址:http://icecloud.51.net/soft/ireport.rar

 

iReporter包设计文档

冰云 2004.1.5

版权所有 (C) 冰云

 

1 目标功能

    目前项目中的报表等方面都是直接通过IE打印。将数据转换成一个长字符串,然后经过JavaScript分割并填充到表格中。这种方法效率低并且难以进行格式定制。

    有的客户希望能够通过Word来打印,并且能够定制表头等方面。在每页都要显示固定的表头。并且支持多个表格打印在同一文件中。

    系统需要一个通用的模块来完成这项任务。

    本模块就是为了这一目标来设计。

 

2 用例说明

A 可通过一个模版来定制一份报表

B 用户输入若干List数据,可以将每个List转换成一个表格

  C 可定制页面头脚

  D 可定制多个表格的头,并且表头固定于每一页

  E 多个表格之间要进行分页

  F 模版中可以定义表格样式

  G 可以通过一个URL生成一份报表

 

3 关键技术

  A Doc文件的生成:

    DOC文件格式是微软专利,用Java很难直接生成doc文件。经过讨论与试验,发现IE可以将任意一个后缀名为docHTML文档当作Word来打开。因此,采用生成HTML的方式来取代word生成。待生成doc文件格式不是难题的时候,可以通过修改实现来完成。

 

 B 固定表头

    经过试验,在Word中固定表头可以通过<THEAD>标签来完成。而将<Caption>标签放入<THEAD>,可以实现每页都显示表名在顶部。

 

 C 表间分页

    表间分页在Word中是通过一个样式来指定的。<P style=”page-break:always”>

 

  D 对任意List生成表格

    对任意List生成表格,要求List中的对象必须是标准的JavaBean对象,即只有getset方法的对象。生成表格将依照模版中对该JavaBean的属性名称的引用而成。如getName(),则在模版中写#name#。这项功能通过jakartacommons-beanutils包来实现。

 

 E XML模版

    定制模版采用XML文件,其格式参见下文。XML解析通过DOM4J来实现。这个包的特点是灵活易用,速度比JDOM要快。

 

4 接口设计

    本包主要由ReportReportBuilderTemplateParser三个接口组成。其中Report是最终返回给用户的结果。ReportBuilderFactory是建立ReportBuilder的工厂。ReportFacade是提供给调用者的代理方法。本包主要异常为ReportException,是Unchecked Exception

 

WEB报表至WORD,打印工具类库   

5 使用方式

    使用实例请参见DemoServlet.java

  A 通过模版建立文档报表

PrintWriter out = response.getWriter();

 

// 建立新的DocumentBuilder,工厂方法,现在仅支持Word参数

ReportBuilder builder = ReportBuilderFactory.getBuilder("Word");

 

// Template建立InputStream

InputStream is =

    new FileInputStream(new File("d://template.xml"));

 

// isbuilder

builder.setTemplate(is);

 

// 建造List

List list = new ArrayList();

 

// 构造数据,其中的数据必须是JavaBean形式

... list.add(JavaBean) ...

 

// simpletable应改与模版中的表格名称一致,如id="simpletable"

builder.addData(list1, "simpletable");

builder.addData(list2, "styledtable");

 

// 构造并返回内容,默认将采用ISO-8859-1编码

Report doc = builder.buildReport();

 

// 输出或保存

doc.save(new File("d://a.doc"), "ISO-8859-1");

doc.print(out);

 

 

 

  B 通过URL建立文档

 

// 建立新的DocumentBuilder,工厂方法,现在仅支持Word参数

ReportBuilder builder = ReportBuilderFactory.getBuilder("Word");

 

// 构造report

Report report = builder.buildReport(new URL("http://www.hjsm.net"));

 

// 输出

report.print(System.out);

 

 

6 设计类图

com.zotn.util.report.wordimpl是上述接口的Word/XHTML实现。其主要是运用DOM4J解析模版,将数据与模版拼装,生成最终XHTML代码的过程。

Tree用于构建一个树形结构,保存模版生成的节点信息。XMLTree是其实现类

TreeNode,保存每个模版节点,XMLTreeNode是其实现类

NodeVisitor,遍历每个节点的Visitor,每个功能对应一个NodeVisitor

GenericXMLParser,是TemplateParser的实现类,用于分析模版

DataHolder,用于保存原始输入数据

ReportHandler,实现了DataHandler,用于处理输出结果并构造Report

WordTableReportBuilderReportBuilder的实现类

 

下图是实现的简图。

WEB报表至WORD,打印工具类库

7 已知缺陷

    A 当前版本无法处理动态页码的问题。

    B 不支持其他格式的输出

    C 对于URL的解析,无法处理相对路径的图片,样式表等。

 

8 第三方库

Dom4J; 用于xml解析

    Jakarta Commons Logging; 用于记录日志

    Jakarta Commons Lang; 用于字符串共用方法

    Jakarta Commons BeanUtils; 用于处理JavaBean

    Jakarta Commons Collections; BeanUtils需要

    Jakarta ORO; 处理正则表达式

   

9 相关软件

    在主提供能已经完成的后,我偶然注意到了JasperReport这个开源项目。它是一个专业报表库,可将数据转换为HTML,XML,PDF,XLS等格式报表。也是通过定义一个模版来定制格式。因此,很不幸,我重新发明了*,而且还是个不圆的*。

 

模版文件

 

<?xml version='1.0' encoding='ISO-8859-1'?>

<!-- 默认采用ISO-8859-1编码 -->

<!-- ROOT元素,一般不需要变 -->

<word>

    <!-- 页面头,内容可以写任意HTML,但尖括号应用&lt;&gt;代替 -->

    <header><![CDATA[

    <P align="center">页头</P>

    ]]></header>

    <!-- 第一个表格,表格别名用id表示 -->

    <table id="simpletable">

       <!-- 表格数据 -->

       <tbody>

           <!-- 每个TD单元格内,写 #属性名# name属性表示表头-->

           <td name="名称">#name#</td>

           <td name="颜色">#color#</td>

           <td name="颜色">#price#</td>

       </tbody>

    </table>

    <!-- 第二个表格,表格参数(与HTML相同)可作为属性或节点添加 -->

    <table id="styledtable" width="600">

       <!-- 表格的样式,如边框宽度等可当作节点 -->

       <style>color:blue;border:1px solid black</style>

       <!-- 复杂表头表格,TR表示行,TH表示单元表格 -->

       <thead>

       <!-- 固定表格头 -->

           <caption style="color:red"><![CDATA[

           <font size="+2">固定表格头</font>

           ]]></caption>

           <tr><th colspan="2" style="color:green">属性</th><th>价值</th></tr>

           <tr><th colspan="2">属性2</th><th>价值2</th></tr>

       </thead>

       <!-- 数据 -->

       <tbody>

           <td name="名称" style="color:red">#name#</td>

           <td name="颜色" width="12">#color#</td>

           <td name="价格" width="10%">#price#</td>

       </tbody>

    </table>

    <!-- 页面脚 -->

    <footer><![CDATA[

    <p>页脚</P>

    ]]></footer>

</word>