成都心情

  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 2 文章 :: 501 评论 :: 1 Trackbacks
很久没更新 blog 了,工作和一些事情占用了大部分精力,实在是身不由己。今天终于有空整理一下最近用到的东西。

有个朋友的项目需要用到 PDF 报表下载,之前我只做过 Excel 的,相信再做一次 PDF 的下载一定很有趣吧。在网上找了一大圈,似乎 iText 比较符合我的要求,而且这个工具很早很早以前就有了,生命力很旺盛。进入 iText 的主页(http://www.lowagie.com/iText/),发现作者很勤劳,最近2个月都有新版本发布。哪知道现在高兴得太早了,一堆问题接踵而至。

下载倒是很简单,一个iText-2.1.4.jar搞定,然后去找入门文档,进了文档页面,一股浓郁的商业气氛迎面而来,这里只提供了部分文档,除非去买"iText in Action",随后被踢到 iText by Example 页面。好吧,既然这是老牌工具了,肯定有不少中文资料吧,找了一圈,没发现什么和生成并下载相关的 out of box 文档,很多都是经验性的总结和进阶文章。无奈又啃 iText by Example,在这里找到些有用的资源,iText in a Web Application正是我要找的,不过这个例子很简单。通过 Google 之后,又发现要下载一个 CJK 的包(iTextAsian.jar)才能正确显示中文,好吧我去找。很幸运的是在 iText by Example 里找到了这个 jar 的 link,兴致勃勃的跑去下载,结果这是个无效链接,最后在 sourceForge 上才找到,不容易啊。解决了这些问题,想必能够安稳的使用了吧,由于这个项目比较急,没什么耐心一个个的翻阅 iText by Example,想找点捷径,据说 iText 可以从 html 直接生成 PDF,窃喜!找了 apache common 的 httpclient,动态模拟 http 请求来抓 html,根据控制台的 print,的确把 html 抓到了,然后开始转换到 PDF,先解决了中文显示问题,可是后面的问题解决不了了,html 的 table 和 div 这些,转换到 PDF 都走样了... ...

很不爽,看来还是只有老老实实的啃 iText by Example实在点。这次稍微耐心点,一点点的看,首先搞清楚了它的 Font 设置,然后是 Table 和 Cell 的关系,经过反复调试,有点效果了。把代码贴出来,做个标记吧。以免以后又抓狂。

  1 package org.rosenjiang.servlet;
  2 
  3 import java.awt.Color;
  4 import java.io.IOException;
  5 import java.util.HashMap;
  6 import java.util.List;
  7 import java.util.Map;
  8 
  9 import javax.servlet.ServletException;
 10 import javax.servlet.http.HttpServlet;
 11 import javax.servlet.http.HttpServletRequest;
 12 import javax.servlet.http.HttpServletResponse;
 13 
 14 import org.springframework.web.context.WebApplicationContext;
 15 import org.springframework.web.context.support.WebApplicationContextUtils;
 16 
 17 import org.rosenjiang.service.UserService;
 18 import com.lowagie.text.Document;
 19 import com.lowagie.text.DocumentException;
 20 import com.lowagie.text.Font;
 21 import com.lowagie.text.Paragraph;
 22 import com.lowagie.text.pdf.BaseFont;
 23 import com.lowagie.text.pdf.PdfPCell;
 24 import com.lowagie.text.pdf.PdfPTable;
 25 import com.lowagie.text.pdf.PdfWriter;
 26 
 27 /*
 28  * ReportServlet
 29  * @author rosen jiang
 30  * @since 2008-12
 31   */ 
 32 public class ReportServlet extends HttpServlet {
 33        
 34     /**
 35      * Return a PDF document for download.
 36      * 
 37      */
 38     public void doGet (HttpServletRequest request, HttpServletResponse response)
 39     throws IOException, ServletException {
 40         String account_id = request.getParameter("account_id");
 41         String search_date_from = request.getParameter("search_date_from");
 42         String to = request.getParameter("to");
 43         WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
 44         UserService userService = (UserService)ctx.getBean("userService");
 45         List<Map<String, Object>> list = userService.getAccountActivity(account_id, search_date_from, to);
 46         // create PDF document
 47         Document document = new Document();
 48         try {
 49             //set response info
 50             response.setContentType("application/x-msdownload;charset=UTF-8");
 51             response.setHeader("Content-Disposition","attachment;filename=report.pdf");
 52             //open output stream
 53             PdfWriter.getInstance(document, response.getOutputStream());
 54             // open PDF document
 55             document.open();
 56             // set chinese font
 57             BaseFont bfChinese = BaseFont.createFont("STSong-Light""UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);  
 58             Font f2 = new Font(bfChinese, 2, Font.NORMAL);
 59             Font f6 = new Font(bfChinese, 6, Font.NORMAL);
 60             Font f8 = new Font(bfChinese, 8, Font.NORMAL);
 61             Font f10 = new Font(bfChinese, 10, Font.NORMAL);
 62             Font f12 = new Font(bfChinese, 12, Font.BOLD);
 63             //set title
 64             document.add(new Paragraph("金融报表", f12)); 
 65             //<br>
 66             document.add(new Paragraph(" ",f6)); 
 67             //set sub title
 68             document.add(new Paragraph("账户信息", f10)); 
 69             //<br>
 70             document.add(new Paragraph(" ", f2));
 71             //process business data
 72             if(list.size()>0 && list.get(0).get("bankbook_no")!=null){
 73                 float openBalance = 0;
 74                 //create table with 7 columns
 75                 PdfPTable table = new PdfPTable(7);
 76                 //100% width
 77                 table.setWidthPercentage(100);
 78                 table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
 79                 //create cells
 80                 PdfPCell cell = new PdfPCell();
 81                 //set color
 82                 cell.setBackgroundColor(new Color(21314169));
 83                 cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
 84                 //
 85                 cell.setPhrase(new Paragraph("交易日", f8));
 86                 table.addCell(cell);
 87                 cell.setPhrase(new Paragraph("类型", f8));
 88                 table.addCell(cell);
 89                 cell.setPhrase(new Paragraph("备注", f8));
 90                 table.addCell(cell);
 91                 cell.setPhrase(new Paragraph("ID", f8));
 92                 table.addCell(cell);
 93                 cell.setPhrase(new Paragraph("票号", f8));
 94                 table.addCell(cell);
 95                 cell.setPhrase(new Paragraph("合计", f8));
 96                 table.addCell(cell);
 97                 cell.setPhrase(new Paragraph("余额", f8));
 98                 table.addCell(cell);
 99                 //create another cell
100                 PdfPCell newcell = new PdfPCell();
101                 newcell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
102                 
103                 Map<String, Object> map = new HashMap<String, Object>();
104                 for(int i = 0; i < list.size(); i++){
105                     map = list.get(i);
106                     String cashInout = map.get("cash_inout").toString();
107                     newcell.setPhrase(new Paragraph(map.get("trade_date").toString(), f8));
108                     table.addCell(newcell);
109                     newcell.setPhrase(new Paragraph(map.get("bankbook_type").toString(), f8));
110                     table.addCell(newcell);
111                     newcell.setPhrase(new Paragraph(map.get("memo").toString(), f8));
112                     table.addCell(newcell);
113                     newcell.setPhrase(new Paragraph(map.get("account_id").toString(), f8));
114                     table.addCell(newcell);
115                     newcell.setPhrase(new Paragraph(map.get("ticket_no").toString(), f8));
116                     table.addCell(newcell);
117                     newcell.setPhrase(new Paragraph(map.get("amount").toString(), f8));
118                     table.addCell(newcell);
119                     newcell.setPhrase(new Paragraph(openBalance+"", f8));
120                     table.addCell(newcell);
121                     if(cashInout.equals("I")){
122                         openBalance = openBalance + Float.valueOf(map.get("amount").toString());
123                     }else if(cashInout.equals("O")){
124                         openBalance = openBalance - Float.valueOf(map.get("amount").toString());
125                     }
126                 }
127                 //print total column
128                 newcell.setPhrase(new Paragraph("合计"+openBalance, f8));
129                 table.addCell("");
130                 table.addCell("");
131                 table.addCell("");
132                 table.addCell("");
133                 table.addCell("");
134                 table.addCell("");
135                 table.addCell(newcell);
136                 document.add(table);
137             }else{
138                 PdfPTable table = new PdfPTable(1);
139                 table.setWidthPercentage(100);
140                 table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
141                 PdfPCell cell = new PdfPCell(new Paragraph("暂无数据"));
142                 cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
143                 table.addCell(cell);
144                 document.add(table);
145             }
146         }
147         catch(DocumentException de) {
148             de.printStackTrace();
149             System.err.println("document: " + de.getMessage());
150         }finally{
151             // close the document and the outputstream is also closed internally
152             document.close();
153         }        
154     }
155 }

itext.JPG

代码结构清晰,本来也没什么东西,就是通过 Spring 调用 service 方法,获取数据后按照 iText 结构输出即可。不过代码里面有个很愚蠢的动作:document.add(new Paragraph(" ",f6)),主要是找不到如何输出空白行,所以只好出此下策。如果哪位有解法,请告知一下。

做技术的确不能太着急,慢慢来,总会找到出口的。

请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处:http://www.blogjava.net/rosen
posted on 2008-12-07 13:27 Rosen 阅读(9565) 评论(3)  编辑  收藏 所属分类: Java EE 服务器端

评论

# re: 利用 iText 实现 PDF 报表下载 2008-12-31 16:02 chis
不错,很有用。  回复  更多评论
  

# re: 利用 iText 实现 PDF 报表下载[未登录] 2009-02-25 21:47 Max
Document.add(Chunk.NEWLINE); //Try this for add blank row

or

Paragraph.add(Chunk.NEWLINE);  回复  更多评论
  

# re: 利用 iText 实现 PDF 报表下载 2009-02-26 09:53 Rosen
@Max
感谢Max同学的热心。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: