为PDF文档添加目录也是经常会用到的功能,itext做目录的思路一般有2种。

第一种:先将正文文档生成出来,同时保存正文文件的每一个模块以及对应的页码,然后生成一个新的文档,同时读取正文文件,复制正文文件的每一页,并通过正文模块与对应的页码数生成目录

第二种:先将正文文档生成出来,同时保存正文文件的每一个模块以及对应的页码,然后通过移动页面的方式生成目录,此方式在实际过程中当目录超过2页时会有问题。

我的案例以第一种方式生成目录,简单起见,正文文件先生成好,总共有5个模块,6个页面,其中一个模块占了2页,模块与页面的对应关系如下代码。

public List<Map<String, Object>> getCatalogList() {final List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();final Map<String, Object> catalogMap = new HashMap<String, Object>();catalogMap.put("title", "关于公司");catalogMap.put("number", 1);list.add(catalogMap);final Map<String, Object> catalogMap2 = new HashMap<String, Object>();catalogMap2.put("title", "阅读指南");catalogMap2.put("number", 2);list.add(catalogMap2);final Map<String, Object> catalogMap4 = new HashMap<String, Object>();catalogMap4.put("title", "测评目的");catalogMap4.put("number", 4);list.add(catalogMap4);final Map<String, Object> catalogMap5 = new HashMap<String, Object>();catalogMap5.put("title", "综合评价");catalogMap5.put("number", 5);list.add(catalogMap5);final Map<String, Object> catalogMap6 = new HashMap<String, Object>();catalogMap6.put("title", "关于报告");catalogMap6.put("number", 6);list.add(catalogMap6);return list;}

正文源文件页面如下图 (source.pdf)

生成目录代码

    @Testpublic void test() {final List<Map<String, Object>> list = this.getCatalogList();PdfDocument sourcePdf = null;Document document = null;try {final PdfFont heiTi = this.getHeiTiFont();// ***源文件:也即需要添加目录的文件final String sourcePdfPath = "D:/itext-pdf/source.pdf";sourcePdf = new PdfDocument(new PdfReader(sourcePdfPath));final int totalPageNumber1 = sourcePdf.getNumberOfPages();System.out.println("totalPageNumber****" + totalPageNumber1);// ***添加目录后重新生成的文件final String dest = "D:/itext-pdf/004.pdf";final PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));document = new Document(pdfDoc);document.add(new Paragraph(new Text("目录").setFont(heiTi)).setTextAlignment(TextAlignment.CENTER));// 用于做书签使用final PdfOutline root = pdfDoc.getOutlines(true);// 生成的目录需要几页,在实际过程中是需要根据目录的条数计算得出final int catalogNumber = 1;if (catalogNumber > 1) {for (int i = 1; i < catalogNumber; i++) {pdfDoc.addNewPage();}}// 上一页的页数,这个主要是因为在实际的文档中,会存在一个条目占多页的情况,例如本例中“阅读指南”就占2页int upPageNumber = 0;for (final Map<String, Object> map : list) {final String title = map.get("title").toString();final int curTotalPageNumber = pdfDoc.getNumberOfPages();final Integer pageNumber = Integer.valueOf(map.get("number").toString());// Copy pageSystem.out.println(title + "**" + pageNumber + "**" + upPageNumber + "********" + curTotalPageNumber);// 当本页的页码与上一页页码直接多余1的时候,说明上一页后面还存在其它页,例如本例中的复制"测评目的"时要把 “阅读指南”的第2页先复制到新文档中。if (pageNumber - upPageNumber > 1) {for (int startNum = upPageNumber + 1; startNum < pageNumber; startNum++) {final PdfPage page = sourcePdf.getPage(startNum).copyTo(pdfDoc);pdfDoc.addPage(page);}}upPageNumber = pageNumber;final PdfPage page = sourcePdf.getPage(pageNumber).copyTo(pdfDoc);pdfDoc.addPage(page);System.out.println("page *****" + page + " ** " + page.getPdfObject());// 用于点击目录条目做跳转的处理,类始于锚点定位的功能final String destinationKey = "p" + pdfDoc.getNumberOfPages();final PdfArray destinationArray = new PdfArray();destinationArray.add(page.getPdfObject());destinationArray.add(PdfName.XYZ);destinationArray.add(new PdfNumber(0));destinationArray.add(new PdfNumber(page.getMediaBox().getHeight()));destinationArray.add(new PdfNumber(1));pdfDoc.addNamedDestination(destinationKey, destinationArray);// 书签final Text text = new Text(title);text.setFont(this.getSongTiFont());final TOCTextRenderer renderer = new TOCTextRenderer(root, text);text.setNextRenderer(renderer);// 生成目录final Paragraph p = new Paragraph();p.setFont(heiTi);p.addTabStops(new TabStop(540, TabAlignment.RIGHT, new DottedLine()));p.add(text);p.add(new Tab());p.add(String.valueOf(pdfDoc.getNumberOfPages() - catalogNumber));p.setProperty(Property.ACTION, PdfAction.createGoTo(destinationKey));document.add(p);}          } catch (final Exception e) {e.printStackTrace();} finally {sourcePdf.close();document.close();}}

TOCTextRenderer.java

public class TOCTextRenderer extends TextRenderer {protected PdfOutline parentOutline;public TOCTextRenderer(final PdfOutline parentOutline, final Text modelElement) {super(modelElement);this.parentOutline = parentOutline;}@Overridepublic void draw(final DrawContext drawContext) {super.draw(drawContext);Text t = (Text) this.modelElement;Rectangle rect = this.getOccupiedAreaBBox();PdfDestination dest = PdfExplicitDestination.createXYZ(drawContext.getDocument().getLastPage(), rect.getLeft(),rect.getTop(), 0);PdfOutline curOutline = this.parentOutline.addOutline(t.getText());curOutline.addDestination(dest);// PdfOutline secOutline = curOutline.addOutline(t.getText() + " - 2");// secOutline.addDestination(dest);// System.out.println(curOutline.getTitle());}}

最终生成的文档如下图

在实际生成带目录的PDF文档时,则要比上面的例子复杂一些,例如目录是有层级的,目录可能超过一页,目录可能也需要有页眉页脚等等,那就要做特殊的一些处理了,这些在接下来的搭建PDF脚手架里说明了。

iText7 学习笔记3--目录相关推荐

  1. 软件工程学习笔记《目录》

    软件工程学习笔记<目录> 软件工程学习笔记<一>什么是软件工程 软件工程学习笔记<二>代码规范 软件工程学习笔记<三>代码优化和性能测试 软件工程学习笔 ...

  2. 设计模式学习笔记(目录篇)

    设计模式学习笔记(目录篇) 为了方便查看,特此将设计模式学习笔记系列单独做一个目录. 1   设计模式学习笔记(一:命令模式) 2   设计模式学习笔记(二:观察者模式) 3   设计模式学习笔记(三 ...

  3. itext7学习笔记——第2章实践example

    本章的例子,请参考我翻译的博文:itext7学习笔记--第2章,里面有详细的解释,有什么不懂得也可以评论或者私信我! 例子1:简单的坐标系 简单地画一个x和y轴坐标系,代码如下: import com ...

  4. itext7学习笔记——第7章

    作者:CuteXiaoKe 微信公众号:CuteXiaoKe 前言 在1-4章中,我们使用了iText7来创建PDF文档.在5-6章中,我们操作和重用了现有的PDF文档.在这些章节中我们操作的PDF文 ...

  5. 华为HCIA-datacom 学习笔记汇总目录

    华为HCIA-datacom 学习笔记汇总目录 华为HCIA-datacom 学习笔记1--网络参考模型 华为HCIA-datacom 学习笔记2--华为VRP系统 华为HCIA-datacom 学习 ...

  6. SQL Server 2008中SQL应用系列及BI学习笔记系列--目录索引 @邀月

    邀月 的数据库学习 http://www.cnblogs.com/downmoon/archive/2011/03/10/1980172.html SQL Server 2008中SQL应用系列及BI ...

  7. SQL Server 2008/2012中SQL应用系列及BI学习笔记系列--目录索引

    SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流. 3w@live.cn  ◆0.SQL应用系列 1.SQL Server 2008中SQL增强之一:Values新用途 ...

  8. Solr6.7 学习笔记(01) -- 目录结构

    Solr解压后的目录结构 --contrib: Solr的一些扩展 --analysis-extras: 包含一些文本分析组件及其依赖 --clustering: 包含一个用于集群搜索结果的引擎 -- ...

  9. 36篇博文带你学完opencv :python3+opencv学习笔记汇总目录(基础版)

    经过几天的学习,opencv基础部分学习完啦.整理出来. OpenCV opencv学习笔记1:图片读入,显示与保存(有代码) opencv学习笔记2:图像处理基础 opencv学习笔记3:像素处理 ...

  10. Linux命令学习笔记之一目录与文件基本操作

    目录操作 cd:进入目录 基本格式:cd 目录名 例子: 1).在当前目录进入子目录a,输入"cd a" 2).在当前目录进入根目录下的子目录tmp,输入"cd /tmp ...

最新文章

  1. 安装centos后无法引导启动windows7的解决方法
  2. 【BZOJ 4555】 4555: [Tjoi2016Heoi2016]求和 (NTT)
  3. 【机器学习】SVM理论与python实践系列
  4. mysql表主键类型_mysql表结构主键类型
  5. linux 统计命令执行后的行数或者统计目录下文件数目
  6. matlab中的libsvm怎么录入数据啊,LibSVM在MATLAB中使用时的几个问题
  7. 第3节 中间层创建与设置
  8. ROS 控制台:rqt_console 因为比较简单。。。
  9. GridView中的全选操作(转)
  10. struts2错误:The Struts dispatcher cannot be found.
  11. Python学习笔记—— 面向对象1. 面向对象基础
  12. 链接脚本在编程中的高级运用之一:可变长数组
  13. 中小学课外培训机构陷入无序竞争,怎么才能异军突起?
  14. 软件测试常见的问题概略
  15. 拉卡拉支付开启生态化移动支付新趋势
  16. 图片高斯模糊效果的实现
  17. 【树莓派C语言开发】实验15:电位计传感器(关联PCF8951)
  18. OpenGL3.3-SSAO
  19. 用生物知识解读“新冠病毒”,生物竞赛、高考考点,先马后看!
  20. 常用的几种时间系统GMT、UTC等以及使用Python代码GPS时间转UTC时间

热门文章

  1. 如何查看linux管道的内容,linux 查看资料和管道命令
  2. 手拉手-富春山居千人微商群星峰会 到场人数爆棚
  3. c语言 整数除以分数,3.12数学与应用数学专业人才培养模式改革创新的具体措施与.PDF...
  4. 转载: IE、FF、Safari、OP不同浏览器兼容报告
  5. 打印机连接电脑正常但是文件被挂起是怎么回事?
  6. 阿里敏捷教练全面解析淘宝直播敏捷实践之路
  7. 三星A7计算机,5.5寸大屏纤薄金属机 三星GALAXY A7评测
  8. 苹果更新系统服务器,苹果发布紧急公告:11月3日前部分设备不更新系统将停止部分服务...
  9. python不识别pip命令
  10. lsnrctl reload 命令简介