Java做报表——JEditorPane+iText

时间:2022-05-04 11:44:16

Boss给了我工作以来的第一个任务:在Java Application里面做个报表。一开始Boss强烈要求用水晶报表做,虽然我对那个一点概念也没有,但还是无奈的水晶报表的API。经过了一个星期的努力,终于被我找到了,但是做出来的结果让人很失望,Boss看了使劲的摇头,还说了一句,到时候不行的话就放弃这个项目吧。。。。郁闷,第一次任务就失败了吗?

后来跟Boss了解一下需求,发现其实要求也很简单,只要能显示报表(最好还能操作一下报表数据),然后还能打印出来(生成PDF然后打印就OK拉)。一开始我觉得前面一个需求很简单,用JTable显示就可以了,后面一个,上网上找个PDF的API就行了。

经过一轮的苦苦寻找,终于找到了iText,一套开源的Java处理PDF/RTF/HTML的API,并且它开源的要求不是那种基于它开发的也要全部开源,完全满足了我的要求。iText还有专门处理表格的类,用来做报表就最合适了。

用iText主要需要解决3个问题:

1、要知道一些基本的生成PDF的流程,会使用几个基本的类,包括PdfPTable,PdfPCell,Document,Font等(我就用这几个类而已)。生成一个PDF的基本流程是:

Java做报表——JEditorPane+iTextDocument doc;
Java做报表——JEditorPane+iTextdoc 
=   new  Document(PageSize.A4,  50 50 50 50 );
Java做报表——JEditorPane+iTextPdfWriter.getInstance(doc, 
new  FileOutputStream(file));
Java做报表——JEditorPane+iText
// 设置页码
Java做报表——JEditorPane+iText
HeaderFooter hf = new  HeaderFooter( new  Phrase( " " ,pageNumFont), new  Phrase( " " ,pageNumFont));
Java做报表——JEditorPane+iTexthf.setBorder(Rectangle.NO_BORDER);
Java做报表——JEditorPane+iTexthf.setAlignment(Element.ALIGN_RIGHT);
Java做报表——JEditorPane+iTextdoc.setFooter(hf);
Java做报表——JEditorPane+iTextdoc.open();
Java做报表——JEditorPane+iTextdoc.add(Paragraph);
Java做报表——JEditorPane+iTextdoc.add(PdfPTable);
Java做报表——JEditorPane+iTextdoc.close;

设置页码要在PdfWriter获取实例之后,doc open之前设置。最后要把doc close了才能真正的生成需要的PDF文件的。

2、PDF中显示中文的问题。iText默认的jar包是不支持中文输出的,需要下载一个额外iTextAsian.jar才支持中文显示。(iText跟iTextAsian.jar在sourceforge上都可以下载)

Java做报表——JEditorPane+iTextBaseFont cnBaseFont  =  BaseFont.createFont( " STSong-Light " " UniGB-UCS2-H " ,BaseFont.NOT_EMBEDDED);
Java做报表——JEditorPane+iTextFont titleFont 
=   new  Font(cnBaseFont,  20 , Font.BOLD);
Java做报表——JEditorPane+iTextFont typeFont 
=   new  Font(cnBaseFont,  12 , Font.BOLD);
Java做报表——JEditorPane+iTextFont pageNumFont 
=   new  Font(cnBaseFont,  9 , Font.BOLD);

要注意的是,下面那个Font不是java.awt.Font,而是com.lowagie.text.Font。要是在同一个类里面需要用上这2个包的Font,就要连包名也加上去了。

Java做报表——JEditorPane+iTextcom.lowagie.text.Font pageNumFont  =   new  com.lowagie.text.Font(cnBaseFont,  9 , com.lowagie.text.Font.BOLD);
3、PdfPTable跨行的问题。PdfPTable默认是没有跨行的方法,跨列的倒是有。但是可以用跨列+嵌套实现跨行。具体的就是:
Java做报表——JEditorPane+iTexttable.addCell( " 跨行的单元格 " );
Java做报表——JEditorPane+iTextPdfPTable innerTable
= new  PdfPTable(n);
Java做报表——JEditorPane+iTextinnerTable.addCell();
Java做报表——JEditorPane+iText.
Java做报表——JEditorPane+iText.
Java做报表——JEditorPane+iText.
Java做报表——JEditorPane+iText
// 一共add了n*m个
Java做报表——JEditorPane+iText
PdfPCell cell = new  PdfPCell(innerTable);
Java做报表——JEditorPane+iTextcell.setColspan(n);
Java做报表——JEditorPane+iTexttable.addCell(cell)

出来的效果就是那个“跨行的单元格”跨了m行。

用iText的老式Table是有个跨行的方法的,但是我用它生成跨页的的表格的时候,总是会出现单元格截断的问题,即使用它的方法设置避免单元格/表格跨页截断的问题也不行。所以还是用较新的PdfPTable类吧,表格嵌套也不是很难写代码吧。

打印那块做好了,才发现在程序里面显示是比较难的——JTable标题栏跨行是很难做到的。在网上找了好多的源码,都是直接跑到最基本的绘制组件那个方法里面改。这样改,复杂就不说了,最重要的是这样好像还不能动态的生成标题栏,而且JTable有多个实例的时候,显示就不正常。算了算了,与其研究人家的代码,还不如自己写。但是那个高深的方法我是写不出来的,汗。。。

这个时候,Boss给了我一点意见,说Swing里面有个Html的控件(他好像不是这样说的),然后JEditorPane就出场了。JEditorPane可以解析html代码(不一定是完整的html文件),由于以前做过一些网页,知道html里面的table很好用,就用html的table做前台显示。实现起来也不难,就是在程序里写html代码(汗!)。尽管看起来很烦,但是用html实现的话,表格的外观比较好控制。最终做出来的界面,Boss连说几个“好”(个人认为其实也不是太好,不过比JTable那样死板的外表,确实colorful了很多^-^)。

后来发现这样的话,还只是显示好看了一点,功能还是就只有显示!我就给标题栏每个列都加了个超链接,一点就进行排序,功能就不那么单调了。写排序算法的时候,用2个小时还是写不出快速排序算法(^-^!),刚毕业就把东西都忘了。。。最终用1分钟写了个冒泡就完事了,反正排序的数据量又不大,并且只对索引排序而已,效率还是挺高的,嘿嘿。

工作的第一次任务就这样差不多结束了(还要等客户验收呢),感觉这一次学了不少东西,为了不让自己忘记所学的东西(偶没什么记性),就把它们都写下来了。