菠萝大象
用心思考,用心写作
首页
新随笔
联系
管理
随笔-67 评论-522 文章-0 trackbacks-0
使用jxl生成复杂报表的分析与设计(一)
在实际项目中,特别是企业应用开发中,报表开发是其中很重要的一项功能,基本上都会要求将统计数据导出成
Excel
,不但如此,这些报表格式一般也比较复杂,尤其是显示的数据,往往都是很多业务数据综合而成的结果。大象根据自己以往做报表的经验,进行了一下总结,给刚开始做报表开发或是有需要的朋友一点借鉴。
由于大象以前做的报表距离现在时间已经很久了,有些相关的业务数据已经找不到,再加上这些数据涉及商业机密也不便公开,所以本篇主要着重于阐述解决问题的思路,而不是去关注代码实现,当然代码肯定会有,我主要想告诉大家怎么去解决这类问题。同时大象将在第二篇文章中,把自己遇到过的一些比较复杂的报表案例拿出来进行分析,用抽丝剥茧的方式,让报表开发变得不再那么让人无处下手,最多只是麻烦点而已。
^_^
目前
Java
开源报表比较有代表性的有
JasperReports
、
Cewolf
、
iReport
、
JfreeChart
等等
技术,它们大都是用来生成不同格式或图形化的报表。而本篇文章要讲的
jxl
,则是
Java Excel API
,它是
一个成熟开源的
Excel
电子表格读取,修改,写入的项目。我们可以利用它简单,便利的
API
生成我们想要的
Excel
数据报表。
除了
jxl
外,还有一个
apache
的
poi
开源项目,它的功能非常强大,不仅可以操作
Excel
,还可以支持
Word
、
PowerPoint
等等格式,
3.5
之后的版本,还加入了对
Excel 2007
以后版本的支持。
当然
jxl
也有不足的地方,最主要体现在,它支持生成的报表最大行数为
65535
,如果超过这个数量,将会产生异常,而且也不支持
Excel 2007+
版本。如果平时报表数据量不是很大的话,而且只是用来生成
Excel
格式的文件,大象建议还是用
jxl
比较好,它使用简单,性能也还不错。
根据大象的经验,定义一个报表模板,然后往里面填充数据,是开发复杂报表的一个比较不错的方法。大象将报表分为基本报表和复杂报表,所谓基本报表就是没有复合表头,每行一条数据,并且提供的数据不需要查询两张以上的表。而复杂报表正好与之相反。不管是基本报表还是复杂报表,代码有很多都是一样的,不一样的只是由业务复杂度产生的报表复杂度。
我们先来看看用
jxl
生成
Excel
报表的代码模板:
上面这个是
Cell(
单元格
)
的通用格式化设置,
WritableFont
构造函数的参数第
1
个是字体,第
2
个是字体大小,第
3
个是字体样式,第
4
个
false
指的是正常显示,默认为
italic
倾斜显示,第
5
个下划线样式,第
6
个指定字体颜色。设置完字体后,再设置单元格的格式,对于一般的单元格,不用设置背景色,除非报表显示需要。金额及百分比的显示要用到
NumberFormat
类,这里的格式指定为
0.00
而不是
#.##
是为了强制保留两位小数,对于这类数字一般在报表中都是设置为右对齐,这样出来的报表比较好看。当然最终还是要根据客户的要求来决定样式。
使用模板方式生成
Excel
除了已经定义好表头外,还有一个好处是可以预先定义
固定列
的宽度,这样就免去了用代码来设置列宽,如果是复杂表头,也省去了不少设置表头和合并单元格的代码。请注意我前面用红字加粗的固定列三个字,因为报表的表头不一定就是模板中设置的那样,还有一种情况就是根据查询条件的年和月,动态生成表头,这些表头被排列在固定列的后面,报表生成后,这些列下面都有相应的数据。关于这部分内容我会在第二篇文章中介绍。
上图中,红框的部分就是使用模板生成
Excel
的关键代码,
ResourceUtils
是
org.springframework.util
包中的工具类。
上图中的红框部分与使用模板方式相比是不是点些细微的差别?请一定注意这些细节部分的不同。
完全
用
jxl API
创建
Excel
所有内容都需要用代码来实现:
设置标题及表头并定义每列的宽度,
setColumnView
方法的第
1
个参数是列的索引,从
0
开始,第
2
个参数是宽度,这个数值既不是像素也不是长度,而是指字符数,比如第
1
列的宽度可以理解为相当于
20
个字符的宽度。以
10pt
的字体大小来算,实际上最多只能填充
19
个字符,而汉字最多
10
个,其实主要还是需要通过测试来调整最终效果。
接下来就是填充数据,这块代码不管是用模板方式还是
API
方式都是一样的。
对于简单的单行表头,填充数据很简单,将查询结果填充到单元格中。前面定义了标题和表头,已经占去了两行,所以应该从第
3
行开始添加数据,行的索引也是从
0
开始,
2
表示第
3
行。如果是数字型的
Cell
需要用
jxl.write.Number
来进行封装,这样生成的数据才不会因为可能过大或别的因素而被
Excel
自动转化成科学计数法。如果还是想用
Lable
来封装数字,可以使用
java.text.
NumberFormat
来做
格式化。最后执行关闭操作。
看到这里,有没有感觉用
jxl
做报表非常简单?可以说是,也可以说不是。因为这里面最麻烦的地方在于取得业务数据,另外对于复杂报表,
for
循环里面还会包含很多条件判断、其它
for
循环以及合并行或列等操作。
业务数据的获得有两种方式,第
1
种是按报表的样式建立一个对象模型,将要导出的数据全部填充到这个模型中,然后根据报表的格式添加数据。第
2
种是通过
SQL
语句,使用尽量少的查询次数将所有结果查询出来,填充到数据模型中。不管是第
1
种还是第
2
种最典型的就是简单表头,单表查询,所有的数据都在
Model
对象里面,执行一个循环操作就可以搞定了。但如果是复杂报表,第
1
种做法就不可取了,因为当你将这个数据对象的
List
实现后就会发现,代码之复杂,效率之低下
(
并不是指速度慢,而是指
SQL
查询次数非常多
)
简直令人发指。而如果采取第
2
种做法,
SQL
语句无疑会很复杂
(
不考虑视图
)
,会有很多关联查询,如果作了分表分库的设计,那这个方式就彻底完蛋了。
既然这两种都不是好的解决办法,那么究竟还有没有更好的解决方案呢?肯定是有的,就是分而治之,按照一种规则
(
比如时间
)
,提取出与报表相关的最基础数据至
Table1
中,然后对该
Table1
再进行一次处理合并至
Table2
中,提取
Table2
至
Table3,
如果有必要还可以对
Table3
再处理一次到
Table4
,从
Table1
到
Table4
每个表里面都是一种报表数据,如果按时间分组,假定
Table1
是按小时,
Table2
按天,
Table3
按月,
Table4
按年,那么相应的报表查询就可以做到只对一张表进行操作,而且报表需要的业务数据都已经存在该表中。我所举的这个方法是比业务较简单的情况,实际开发中要根据当前的业务来设计,因为有些项目的业务确实是非常的复杂,并不像我所说的这么简单。
大家一定不要过于迷信这种方式,世上是没有完美解决方案的,也即所谓的没有“银弹”,这样的处理方式对大部分报表还是适用的。但如果要是遇到所统计的业务基础数据发生了变化,或者本身业务出现变更,甚至报表都发生变更,那么之前所获得的这些数据就没有什么意义了。因此,报表的实现方案一定要根据实现情况来分析,不要总想着有什么通用的解决办法,一招鲜吃遍天这样的想法是非常不可取的,软件最不缺的就是变化,不要抗拒变化,因为你根本无法阻止它,所以你得拥抱变化,享受变化。
本篇主要介绍了使用
jxl
生成报表的代码模板以及获取报表数据的一种处理方式,下一篇将通过两个复杂报表案例的分析,来告诉大家如何进行实现。
本文为菠萝大象原创,如要转载请注明出处。
http://www.blogjava.net/
bolo
posted on 2014-01-07 16:12
菠萝大象
阅读(4944)
评论(2)
编辑
收藏
所属分类:
Java
评论:
#
re: 使用jxl生成复杂报表的分析与设计(一) 2014-06-06 09:12 |
小六夜疯狂
期待更多你的文章!
回复
更多评论
#
re: 使用jxl生成复杂报表的分析与设计(一)[未登录]
2016-05-27 14:44 |
java菜鸟
说明详细全面,讲解深入浅出,新手一看就懂了,感激!
回复
更多评论
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
知识库
C++博客
博问
管理
相关文章:
全局唯一ID生成器浅析
用Java实现MJD转UTC
使用XStream注解实现Java对象与XML互相转换的代码示例
m2eclipse安装小贴士
泛型与反射的使用总结之反射篇
泛型与反射的使用总结之泛型篇
使用jackson对Java对象与JSON字符串相互转换的一些总结
使用jxl生成复杂报表的分析与设计(二)
使用jxl生成复杂报表的分析与设计(一)
使用commons-httpclient发送请求的代码片断
<
2014年1月
>
日
一
二
三
四
五
六
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
随笔分类
(67)
Concurrency(3)
Database(4)
dom4j&jdom(3)
Eclipse(3)
Flex(4)
Hibernate(2)
Java(11)
jBPM(1)
jQuery(5)
Linux(1)
mybatis-generator(3)
Spring3(11)
Struts2(9)
随笔(7)
随笔档案
(67)
2015年9月 (1)
2015年8月 (1)
2015年7月 (1)
2015年5月 (1)
2015年4月 (1)
2015年3月 (3)
2015年2月 (1)
2015年1月 (2)
2014年8月 (1)
2014年6月 (2)
2014年5月 (2)
2014年4月 (3)
2014年3月 (1)
2014年2月 (1)
2014年1月 (2)
2013年12月 (3)
2013年11月 (2)
2013年10月 (2)
2013年9月 (2)
2012年5月 (1)
2012年4月 (2)
2011年8月 (1)
2011年6月 (1)
2011年5月 (3)
2010年9月 (1)
2010年8月 (1)
2010年7月 (1)
2010年6月 (1)
2010年5月 (2)
2010年4月 (4)
2010年3月 (2)
2010年2月 (7)
2008年9月 (2)
2008年8月 (6)
搜索
积分与排名
积分 - 779179
排名 - 54
最新随笔
1. 由Struts2Action代理和googlecode-jsonplugin产生的一个IllegalArgumentException异常问题
2. 在CentOS系统中同步时间
3. 全局唯一ID生成器浅析
4. 用Java实现MJD转UTC
5. 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(三)
6. 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(二)
7. 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
8. Quartz Spring与Spring Task总结
9. 常用的MySQL复杂查询语句写法
10. 常用的MySQL语句写法
11. 浅谈Java两种并发类型——计算密集型与IO密集型
12. 使用XStream注解实现Java对象与XML互相转换的代码示例
13. 浅谈volatile变量的理解
14. 浅谈Java共享变量
15. m2eclipse安装小贴士
最新评论
1. re: 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
评论内容较长,点击标题查看
--半湖思絮
2. re: 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
评论内容较长,点击标题查看
--菠萝大象
3. re: 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
评论内容较长,点击标题查看
--donghc
4. re: 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
@donghc
maven不是这样玩的呀,我的run是打包后用的,你仔细看了第三篇的内容么?在IDE里直接启动StartUp就行了,这个类是用来测试的
--菠萝大象
5. re: 修改mybatis-generator-1.3.2源码实现自定义代码生成详解(一)
评论内容较长,点击标题查看
--donghc
阅读排行榜
1. 使用jackson对Java对象与JSON字符串相互转换的一些总结(59313)
2. 在Eclipse中反编译Class文件完全详解(43543)
3. Quartz Spring与Spring Task总结(38534)
4. 使用XStream注解实现Java对象与XML互相转换的代码示例(33105)
5. Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(二)(32433)
评论排行榜
1. Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解(五)(69)
2. Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解(三)(47)
3. Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解(一)(35)
4. Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解(二)(27)
5. Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(三)(26)