前些日子做了一个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可以将任意一个后缀名为doc的HTML文档当作Word来打开。因此,采用生成HTML的方式来取代word生成。待生成doc文件格式不是难题的时候,可以通过修改实现来完成。
B 固定表头
经过试验,在Word中固定表头可以通过<THEAD>标签来完成。而将<Caption>标签放入<THEAD>,可以实现每页都显示表名在顶部。
C 表间分页
表间分页在Word中是通过一个样式来指定的。<P style=”page-break:always”>
D 对任意List生成表格
对任意List生成表格,要求List中的对象必须是标准的JavaBean对象,即只有get,set方法的对象。生成表格将依照模版中对该JavaBean的属性名称的引用而成。如getName(),则在模版中写#name#。这项功能通过jakarta的commons-beanutils包来实现。
E XML模版
定制模版采用XML文件,其格式参见下文。XML解析通过DOM4J来实现。这个包的特点是灵活易用,速度比JDOM要快。
4 接口设计
本包主要由Report,ReportBuilder和TemplateParser三个接口组成。其中Report是最终返回给用户的结果。ReportBuilderFactory是建立ReportBuilder的工厂。ReportFacade是提供给调用者的代理方法。本包主要异常为ReportException,是Unchecked Exception。
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"));
// 将is给builder 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
WordTableReportBuilder,ReportBuilder的实现类
下图是实现的简图。
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,但尖括号应用<>代替 -->
<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>