iText 实现 PDF 报表下载

本文分享了使用iText工具生成包含中文内容的PDF报表的经验。从安装配置到具体实现,包括字体设置、表格布局等关键步骤进行了详细介绍。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很久没更新 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( 213 141 69 ));
 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)),主要是找不到如何输出空白行,所以只好出此下策。如果哪位有解法,请告知一下。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值