【Itext】7步制作Itext5页眉页脚pdf实现第几页共几页

itext5页眉页脚工具类,实现page x of y 完美兼容各种格式大小文档A4/B5/B3,兼容各种文档格式自动计算页脚XY轴坐标

 

鉴于没人做的这么细致,自己就写了一个itext5页眉页脚工具类,实现第几页/共几页,方便各位刚进入itext的童鞋调用。2013年9月16日 14:51:01

 

背景:网上流传的都是一些简单的demo,直接扔个A4文档就说实现了,其实很坑的,换个A4横版打印,那些代码就不行了,所以自己搞了这个出来。

 

如果页面看着排版不好,请移步我的百度空间 :http://hi.baidu.com/ae6623/item/08abce3ce29359119dc65ecf

 

工具类PdfReportM1HeaderFooter.java

[java] view plaincopy
 
  1. <span style="font-family:Microsoft YaHei; font-size:12px">/** 
  2.  * Project Name:report 
  3.  * File Name:PdfReportM1HeaderFooter.java 
  4.  * Package Name:com.riambsoft.report.pdf 
  5.  * Date:2013-9-16上午08:59:00 
  6.  * Copyright (c) 2013, riambsoft All Rights Reserved. 
  7.  * 
  8.  */  
  9.     
  10. package com.riambsoft.report.pdf;  
  11.     
  12. import java.io.IOException;  
  13.     
  14. import com.itextpdf.text.Document;  
  15. import com.itextpdf.text.DocumentException;  
  16. import com.itextpdf.text.Element;  
  17. import com.itextpdf.text.Font;  
  18. import com.itextpdf.text.PageSize;  
  19. import com.itextpdf.text.Phrase;  
  20. import com.itextpdf.text.Rectangle;  
  21. import com.itextpdf.text.pdf.BaseFont;  
  22. import com.itextpdf.text.pdf.ColumnText;  
  23. import com.itextpdf.text.pdf.PdfContentByte;  
  24. import com.itextpdf.text.pdf.PdfPageEventHelper;  
  25. import com.itextpdf.text.pdf.PdfTemplate;  
  26. import com.itextpdf.text.pdf.PdfWriter;  
  27.     
  28. /** 
  29.  * ClassName:PdfReportM1HeaderFooter <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-9-13 上午08:59:00 <br/> 
  30.  * 
  31.  * @author 落雨 
  32.  * @version 394263788(QQ) 
  33.  * @since JDK 1.5 
  34.  * @see http://hi.baidu.com/ae6623 
  35.  */  
  36. public class PdfReportM1HeaderFooter extends PdfPageEventHelper {  
  37.     
  38.     /** 
  39.      * 页眉 
  40.      */  
  41.     public String header = "";  
  42.     
  43.     /** 
  44.      * 文档字体大小,页脚页眉最好和文本大小一致 
  45.      */  
  46.     public int presentFontSize = 12;  
  47.     
  48.     /** 
  49.      * 文档页面大小,最好前面传入,否则默认为A4纸张 
  50.      */  
  51.     public Rectangle pageSize = PageSize.A4;  
  52.     
  53.     // 模板  
  54.     public PdfTemplate total;  
  55.     
  56.     // 基础字体对象  
  57.     public BaseFont bf = null;  
  58.     
  59.     // 利用基础字体生成的字体对象,一般用于生成中文文字  
  60.     public Font fontDetail = null;  
  61.     
  62.     /** 
  63.      * 
  64.      * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法. 
  65.      * 
  66.      */  
  67.     public PdfReportM1HeaderFooter() {  
  68.     
  69.     }  
  70.     
  71.     /** 
  72.      * 
  73.      * Creates a new instance of PdfReportM1HeaderFooter 构造方法. 
  74.      * 
  75.      * @param yeMei 
  76.      *            页眉字符串 
  77.      * @param presentFontSize 
  78.      *            数据体字体大小 
  79.      * @param pageSize 
  80.      *            页面文档大小,A4,A5,A6横转翻转等Rectangle对象 
  81.      */  
  82.     public PdfReportM1HeaderFooter(String yeMei, int presentFontSize, Rectangle pageSize) {  
  83.         this.header = yeMei;  
  84.         this.presentFontSize = presentFontSize;  
  85.         this.pageSize = pageSize;  
  86.     }  
  87.     
  88.     public void setHeader(String header) {  
  89.         this.header = header;  
  90.     }  
  91.     
  92.     public void setPresentFontSize(int presentFontSize) {  
  93.         this.presentFontSize = presentFontSize;  
  94.     }  
  95.     
  96.     /** 
  97.      * 
  98.      * TODO 文档打开时创建模板 
  99.      * 
  100.      * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document) 
  101.      */  
  102.     public void onOpenDocument(PdfWriter writer, Document document) {  
  103.         total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高  
  104.     }  
  105.     
  106.     /** 
  107.      * 
  108.      * TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。 
  109.      * 
  110.      * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document) 
  111.      */  
  112.     public void onEndPage(PdfWriter writer, Document document) {  
  113.     
  114.         try {  
  115.             if (bf == null) {  
  116.                 bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);  
  117.             }  
  118.             if (fontDetail == null) {  
  119.                 fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体  
  120.             }  
  121.         } catch (DocumentException e) {  
  122.             e.printStackTrace();  
  123.         } catch (IOException e) {  
  124.             e.printStackTrace();  
  125.         }  
  126.     
  127.         // 1.写入页眉  
  128.         ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase(header, fontDetail), document.left(), document.top() + 20, 0);  
  129.            
  130.         // 2.写入前半部分的 第 X页/共  
  131.         int pageS = writer.getPageNumber();  
  132.         String foot1 = "第 " + pageS + " 页 /共";  
  133.         Phrase footer = new Phrase(foot1, fontDetail);  
  134.     
  135.         // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len  
  136.         float len = bf.getWidthPoint(foot1, presentFontSize);  
  137.     
  138.         // 4.拿到当前的PdfContentByte  
  139.         PdfContentByte cb = writer.getDirectContent();  
  140.     
  141.         // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了 ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。  
  142.         ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, footer, (document.rightMargin() + document.right() + document.leftMargin() - document.left() - len) / 2.0F + 20F, document.bottom() - 20, 0);  
  143.     
  144.         // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F + len , y 轴和之前的保持一致,底边界-20  
  145.         cb.addTemplate(total, (document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F + 20F, document.bottom() - 20); // 调节模版显示的位置  
  146.     
  147.     }  
  148.     
  149.     /** 
  150.      * 
  151.      * TODO 关闭文档时,替换模板,完成整个页眉页脚组件 
  152.      * 
  153.      * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document) 
  154.      */  
  155.     public void onCloseDocument(PdfWriter writer, Document document) {  
  156.         // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。  
  157.         total.beginText();  
  158.         total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色  
  159.         String foot2 = " " + (writer.getPageNumber() - 1) + " 页";  
  160.         total.showText(foot2);// 模版显示的内容  
  161.         total.endText();  
  162.         total.closePath();  
  163.     }  
  164. }</span>  

如何调用?

这样调用即可,下面的代码就是 第几页/共几页的实现方式!推荐大家使用,直接扔到自己的工程,在创建pdf的时候,直接把此event set进去即可。

 

 

[java] view plaincopy
 
  1. <span style="font-family:Microsoft YaHei; font-size:12px">/** 
  2. * Project Name:report 
  3. * File Name:PDFBuilder.java 
  4. * Package Name:com.riambsoft.report.itext 
  5. * Date:2013-9-13下午03:35:53 
  6. * Copyright (c) 2013, riambsoft All Rights Reserved. 
  7. */  
  8.     
  9. package com.riambsoft.report.itext;  
  10.     
  11. import java.io.FileOutputStream;  
  12. import java.io.IOException;  
  13.     
  14. import com.itextpdf.text.Document;  
  15. import com.itextpdf.text.DocumentException;  
  16. import com.itextpdf.text.PageSize;  
  17. import com.itextpdf.text.Rectangle;  
  18. import com.itextpdf.text.pdf.ColumnText;  
  19. import com.itextpdf.text.pdf.PdfContentByte;  
  20. import com.itextpdf.text.pdf.PdfWriter;  
  21. import com.riambsoft.report.pdf.PdfReportM1HeaderFooter;  
  22.     
  23. /** 
  24. * ClassName:PDFBuilder <br/> 
  25. * Function: TODO ADD FUNCTION. <br/> 
  26. * Reason:   TODO ADD REASON. <br/> 
  27. * Date: 2013-9-13 下午03:35:53 <br/> 
  28. * @author Administrator 
  29. * @version 
  30. * @since JDK 1.5 
  31. * @see   
  32. */  
  33. public class PDFBuilder {  
  34. private int pageHeight;  
  35. private int pageWidth;  
  36. private PDFBuilder(){  
  37. }  
  38. public static PDFBuilder getInstance(){  
  39. return new PDFBuilder();  
  40. }  
  41. public void generatePDF()throws Exception {  
  42. Document document = new Document(new Rectangle(pageWidth, pageHeight));  
  43. PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(""));  
  44. this.setFooter(writer);  
  45. writer.setFullCompression();  
  46. writer.setPdfVersion(PdfWriter.VERSION_1_4);  
  47. document.open();  
  48. // Set pdf version to 1.4  
  49. PdfContentByte cb = writer.getDirectContent();  
  50. ColumnText ct=new ColumnText(cb);  
  51. for(int i=0;i<10;i++){  
  52. document.newPage();  
  53. //如果不设置 空白页无法单独显示  
  54. writer.setPageEmpty(false);  
  55. }  
  56. document.close();  
  57. }  
  58.     
  59. private void setFooter(PdfWriter writer) throws DocumentException, IOException {  
  60. //HeaderFooter headerFooter = new HeaderFooter(this);  
  61. //更改事件,瞬间变身 第几页/共几页 模式。  
  62. PdfReportM1HeaderFooter headerFooter = new PdfReportM1HeaderFooter();//就是上面那个类  
  63. writer.setBoxSize("art",PageSize.A4);  
  64. writer.setPageEvent(headerFooter);  
  65. }  
  66. public int getPageHeight() {  
  67. return pageHeight;  
  68. }  
  69. public void setPageHeight(int pageHeight) {  
  70. this.pageHeight = pageHeight;  
  71. }  
  72. public int getPageWidth() {  
  73. return pageWidth;  
  74. }  
  75. public void setPageWidth(int pageWidth) {  
  76. this.pageWidth = pageWidth;  
  77. }  
  78. public static void main(String[] args) throws Exception {  
  79. PDFBuilder builder=new PDFBuilder();  
  80. builder.setPageHeight(400);  
  81. builder.setPageWidth(600);  
  82. builder.generatePDF();  
  83. }  
  84. }</span>  

 

核心算法:就是计算文档的长宽,算出中点,记得中文字体是需要占用宽度的,所以也要计算进去,其次没什么重点,研究一下中点的计算吧,初中知识。

paga x 这种好做,page x of y 按照官方 itext in action 2这本书上面说的那种办法,无法准确计算各种文档的x轴和y轴坐标。

 

我按照书上所写的实现方式如下,不推荐使用,因为只适合于A4纸张。

PdfReportM1HeaderFooter2.java

 

[java] view plaincopy
 
  1. <span style="font-family:Microsoft YaHei; font-size:12px">/** 
  2. * Project Name:report 
  3. * File Name:PdfReportM1HeaderFooter.java 
  4. * Package Name:com.riambsoft.report.pdf 
  5. * Date:2013-9-13上午08:59:00 
  6. * Copyright (c) 2013, riambsoft All Rights Reserved. 
  7. */  
  8.   
  9. package com.riambsoft.report.pdf;  
  10.   
  11. import java.io.IOException;  
  12.   
  13. import com.itextpdf.text.Document;  
  14. import com.itextpdf.text.DocumentException;  
  15. import com.itextpdf.text.Element;  
  16. import com.itextpdf.text.ExceptionConverter;  
  17. import com.itextpdf.text.Font;  
  18. import com.itextpdf.text.Image;  
  19. import com.itextpdf.text.Phrase;  
  20. import com.itextpdf.text.Rectangle;  
  21. import com.itextpdf.text.pdf.BaseFont;  
  22. import com.itextpdf.text.pdf.ColumnText;  
  23. import com.itextpdf.text.pdf.PdfPCell;  
  24. import com.itextpdf.text.pdf.PdfPTable;  
  25. import com.itextpdf.text.pdf.PdfPageEventHelper;  
  26. import com.itextpdf.text.pdf.PdfTemplate;  
  27. import com.itextpdf.text.pdf.PdfWriter;  
  28.   
  29. /** 
  30. * ClassName:PdfReportM1HeaderFooter2 <br/> Function: TODO ADD FUNCTION. <br/> Reason: TODO ADD REASON. <br/> Date: 2013-9-13 上午08:59:00 <br/> 
  31. *  
  32. * @author Administrator 
  33. * @version  
  34. * @since JDK 1.5 
  35. * @see  
  36. */  
  37. public class PdfReportM1HeaderFooter2 extends PdfPageEventHelper {  
  38.   
  39. String header;  
  40. int presentFontSize = 12;  
  41. PdfTemplate total;  
  42. BaseFont bf = null;  
  43. Font fontDetail = null;  
  44.   
  45. public void setHeader(String header) {  
  46. this.header = header;  
  47. }  
  48.   
  49. public void onOpenDocument(PdfWriter writer, Document document) {  
  50. total = writer.getDirectContent().createTemplate(30, 16);  
  51. }  
  52.   
  53. public void onEndPage(PdfWriter writer, Document document) {  
  54.   
  55. Rectangle pageSize = writer.getBoxSize("art");  
  56.   
  57. try {  
  58. if (bf == null) {  
  59. bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);  
  60. }  
  61. if (fontDetail == null) {  
  62. fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体  
  63. }  
  64. catch (DocumentException e) {  
  65. e.printStackTrace();  
  66. catch (IOException e) {  
  67. e.printStackTrace();  
  68. }  
  69. int pageN = writer.getPageNumber();  
  70. String text = "第 " + pageN + "页/共 ";  
  71.   
  72. // 页眉  
  73. ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase("我是页眉,土豪我们做朋友吧",fontDetail), document.left(), document.top() + 20, 0);  
  74.   
  75. PdfPTable table = new PdfPTable(2);  
  76.   
  77. try {  
  78. table.setWidths(new int[] { 1, 1 });  
  79. table.setWidthPercentage(100F);// 占据百分百宽度  
  80. table.setTotalWidth(pageSize.getRight() - pageSize.getLeft() - 100);  
  81.   
  82. PdfPCell cell1 = new PdfPCell(new Phrase(text, fontDetail));  
  83. PdfPCell cell2 = new PdfPCell(Image.getInstance(total));  
  84.   
  85. cell1.setHorizontalAlignment(Element.ALIGN_RIGHT);  
  86. cell1.setBorder(Rectangle.NO_BORDER);  
  87. cell2.setHorizontalAlignment(Element.ALIGN_LEFT);  
  88. cell2.setBorder(Rectangle.NO_BORDER);  
  89.   
  90. table.addCell(cell1);  
  91. table.addCell(cell2);  
  92. table.writeSelectedRows(0, -1, document.left(), document.bottom(), writer.getDirectContent());  
  93. catch (DocumentException de) {  
  94. throw new ExceptionConverter(de);  
  95. }  
  96.   
  97. }  
  98.   
  99. public void onCloseDocument(PdfWriter writer, Document document) {  
  100.   
  101. try {  
  102. if (bf == null) {  
  103. bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);  
  104. }  
  105. if (fontDetail == null) {  
  106. fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体  
  107. }  
  108. catch (DocumentException e) {  
  109. e.printStackTrace();  
  110. catch (IOException e) {  
  111. e.printStackTrace();  
  112. }  
  113.   
  114. ColumnText.showTextAligned(total, Element.ALIGN_LEFT, new Phrase(String.format("%d页", writer.getPageNumber() - 1), fontDetail), 2, 2, 0);  
  115. }  
  116. }</span>  

 

 

这种只能自己去计算Y轴坐标,很容易不在一行。所以不如我的第一种方便。具体就看你使用了。

posted @ 2015-10-29 17:31  疯子110  阅读(873)  评论(0编辑  收藏  举报