iText操作PDF问题总结

    xiaoxiao2024-07-26  91

    这个星期我的任务就是处理一些报表的打印问题,因为我算项目组里对jasperreport比较熟悉的了,这个东东也是我引进到这个项目。ireport画报表,使用struts的action输出PDF到浏览器,这是我们目前的解决方案。今天遇到一个ireport解决不了的要求——合并单元格。类似下面这样的表结构: ----------------------------------------------           |          |__c_____________    dept   | value    |__b_____________           |          |  a -------------------------------------------------------- 也就是需要跨行,跨列!-_-。在html表格中解决这个很简单,只要设置单元格的colspan和rowspan即可。我在ireport没有找到解决方案,如果您知道,请不吝赐教。查找资料弄了两个小时没进展,决定自己用iText写吧,通过google、baidu资料顺利达到了我的要求,仅在此记录下遇到的问题和解决方法。 一。一个HelloWorld实例: package  com.lowagie.examples.general; import  java.io.FileOutputStream; import  java.io.IOException; import  com.lowagie.text. * ; import  com.lowagie.text.pdf.PdfWriter; /**  * Generates a simple 'Hello World' PDF file.  *  *  @author  blowagie   */ public   class  HelloWorld { /**  * Generates a PDF file with the text 'Hello World'  *  *  @param  args no arguments needed here   */ public   static   void  main(String[] args) { System.out.println( " Hello World " ); //  step a: creation of a document-object       Document document  =   new  Document(); try  { //  step b: //  we create a writer that listens to the document //  and directs a PDF-stream to a file         PdfWriter.getInstance(document, new  FileOutputStream( " HelloWorld.pdf " )); //  step c: we open the document         document.open(); //  step d: we add a paragraph to the document         document.add( new  Paragraph( " Hello World " )); }  catch  (DocumentException de) { System.err.println(de.getMessage()); }  catch  (IOException ioe) { System.err.println(ioe.getMessage()); } //  step e: we close the document         document.close(); } } 可以看到一个PDF文件的输出,总共只需要5个步骤 a.创建一个Document实例 Document document = new Document(); b.将Document实例和文件输出流用PdfWriter类绑定在一起 PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf")); c.打开文档 document.open(); d.在文档中添加文字 document.add(new Paragraph("Hello World")); e.关闭文档 document.close(); 这样5个步骤,就可以生成一个PDF文档了。 二。如何使用jsp、servlet输出iText生成的pdf?   如果每次都在服务端生成一个PDF文件给用户,不仅麻烦,而且浪费服务器资源,最好的方法就是以二进制流的形式输送到客户端。 1)JSP输出: <% @ page  import = " java.io.*,java.awt.Color,com.lowagie.text.*,com.lowagie.text.pdf.* " %> <% response.setContentType (  " application/pdf "  ); Document document  =   new  Document(); ByteArrayOutputStream buffer =   new  ByteArrayOutputStream(); PdfWriter writer = PdfWriter.getInstance( document, buffer ); document.open(); document.add( new  Paragraph( " Hello World " )); document.close(); DataOutput output  = new  DataOutputStream ( response.getOutputStream() ); byte [] bytes  =  buffer.toByteArray(); response.setContentLength(bytes.length); for int  i  =   0 ; i  <  bytes.length; i ++  ) { output.writeByte( bytes[i] ); } %> 2)servlet输出,稍微改造下就可以使用在struts中: import  java.io. * ; import  javax.servlet. * ; import  javax.servlet.http. * ; import  com.lowagie.text. * ; import  com.lowagie.text.pdf. * ; public   void  doGet (HttpServletRequest request, HttpServletResponse response) throws  IOException,ServletException { Document document  = new  Document(PageSize.A4,  36 , 36 , 36 , 36 ); ByteArrayOutputStream ba =   new  ByteArrayOutputStream(); try { PdfWriter writer  = PdfWriter.getInstance(document, ba); document.open(); document.add( new Paragraph( " Hello World " )); } catch (DocumentException de) { de.printStackTrace(); System.err.println ( " A Document error: "   + de.getMessage()); } document.close(); response.setContentType ( " application/pdf " ); response.setContentLength(ba.size()); ServletOutputStream out =  response.getOutputStream(); ba.writeTo(out); out.flush(); } 三。如何输出中文?     首先需要下载iTextAsian.jar包,可以到iText的主站上下,ireport也是需要这个包的。然后定义中文字体:      private   static   final  Font getChineseFont() {         Font FontChinese  =   null ;          try  {             BaseFont bfChinese  =  BaseFont.createFont( " STSong-Light " ,                      " UniGB-UCS2-H " , BaseFont.NOT_EMBEDDED);             FontChinese  =   new  Font(bfChinese,  12 , Font.NORMAL);         }  catch  (DocumentException de) {             System.err.println(de.getMessage());         }  catch  (IOException ioe) {             System.err.println(ioe.getMessage());         }          return  FontChinese;     } 我将产生中文字体封装在方法内,自定义一个段落PDFParagraph继承自Paragraph,默认使用中文字体: class  PDFParagraph  extends  Paragraph {          public  PDFParagraph(String content) {              super (content, getChineseFont());         }     } 使用的时候就可以简化了: Paragraph par  =   new  PDFParagraph( " 你好 " ); 四。如何设置PDF横向显示和打印? Rectangle rectPageSize  =   new  Rectangle(PageSize.A4); //  定义A4页面大小 rectPageSize  =  rectPageSize.rotate(); //  加上这句可以实现A4页面的横置 Document doc  =   new  Document(rectPageSize, 50 , 50 , 50 , 50 ); // 4个参数,设置了页面的4个边距 五。如何设置跨行和跨列? 使用PdfPTable和PdfPCell 是没办法实现跨行的,只能跨列,要跨行使用com.lowagie.text.Table和com.lowagie.text.Cell类,Cell类有两个方法:setRowspan()和setColspan()。 六。如何设置单元格边界宽度? Cell类的系列setBorderWidthXXXX()方法,比如setBorderWidthTop(),setBorderWidthRight()等 七。如何设置表头? 希望每一页都有表头,可以通过设置表头来实现。对于PdfPTable类来说,可以这样设置: PdfPTable table  =   new  PdfPTable( 3 ); table.setHeaderRows( 2 );  //  设置了头两行为表格头 而对于om.lowagie.text.Table类,需要在添加完所有表头的单元格后加上一句代码: table.endHeaders(); 八。如何设置列宽? Table table  =   new  Table( 8 ); float [] widths  =  {  0.10f 0.15f 0.21f 0.22f 0.08f 0.08f 0.10f ,                      0.06f  }; table.setWidths(widths); 上面的代码设置了一个有8列的表格,通过一个float数组设置列宽,这里是百分比。 九。单元格内段落文字居中和换行? 居中通过Cell类来设置,一开始我以为设置段落对齐就可以了,没想到是需要设置单元格: cell.setHorizontalAlignment(Element.ALIGN_CENTER); 转义符\n实现。在我的这个应用中,因为数据库取出的数据是为了显示在html上的,所以有很多<br>标签,可以使用正则表达式替换成"\n" " <br>1.测试<br>2.测试2 " .replaceAll( " <br>|</br> " , " \n " ); 十。如何显示页码? 复杂的页码显示和水印添加,需要使用到 PdfPageEventHelper、 PdfTemplate等辅助类,具体的例子参见iText的文档,如果只是为了简单的显示页数,可以使用下面的代码:             HeaderFooter footer  =   new  HeaderFooter( new  Phrase( " 页码: " ,getChineseFont()),  true );             footer.setBorder(Rectangle.NO_BORDER);             document.setFooter(footer);             document.open(); 你可能注意到了,添加footer需要在document.open之前。 相关资源:敏捷开发V1.0.pptx
    最新回复(0)