我需要在PDF中创建一个到表格内容的页面。我将创建PDF阅读书签。
对于iText,我使用:
tmp = SimpleBookmark.getBookmark (reader);使用此PDF进行测试:
返回此地图:
[{Action = GoTo, Named = __ WKANCHOR_2, Title = Secretariat Teste0}, {Action = GoTo, Named = __ WKANCHOR_4, Title = Secretariat TestBook1}, {Action = GoTo, Named = __ WKANCHOR_6, Title = Secretariat Test2}, {Action = GoTo , Named = __ WKANCHOR_8 ...没有页码。
如何用标题和页码显示表格中的一个内容?
我想展示这一点:

发布于 2016-08-19 07:14:53
请阅读这个问题的答案:Java:用itext读取PDF书签名称
它解释了如何使用SimpleBookmark方法获取大纲树的标题(这是在PDF规范中调用“书签”的方式)。
public void inspectPdf(String filename) throws IOException, DocumentException {
PdfReader reader = new PdfReader(filename);
List<HashMap<String,Object>> bookmarks = SimpleBookmark.getBookmark(reader);
for (int i = 0; i < bookmarks.size(); i++){
showTitle(bookmarks.get(i));
}
reader.close();
}
public void showTitle(HashMap<String, Object> bm) {
System.out.println((String)bm.get("Title"));
List<HashMap<String,Object>> kids = (List<HashMap<String,Object>>)bm.get("Kids");
if (kids != null) {
for (int i = 0; i < kids.size(); i++) {
showTitle(kids.get(i));
}
}
}然后阅读这个问题的答案:将“继承缩放(动作属性)”设置为pdf文件中的书签
您将看到,HashMap<String, Object>不仅包含带键"Title"的条目,而且还可以包含带键"Page"的条目。当书签指向一个页面时,情况就是这样。该值将是一个显式目标。它将包括页码,一个值,如Fit、FitH、FitB、XYZ,后面跟着一些标记位置的参数。
如果您查看CreateOutlineTree示例,您将看到还可以将书签提取为XML文件:
public void createXml(String src, String dest) throws IOException {
PdfReader reader = new PdfReader(src);
List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(reader);
SimpleBookmark.exportToXML(list,
new FileOutputStream(dest), "ISO8859-1", true);
reader.close();
}这是我写的一本关于iText的书中的截图,它向您展示了您可以在书签条目中看到哪些键:

从这个表中可以看出,链接也可以表示为指定的目标。在这种情况下,您不会得到页码,而是一个名称。要获取页面编号,您需要提取指定目的地的列表。此列表将为您提供与指定目的地对应的显式目的地。
这一点在书中和正式文件中都有解释。
一旦您有了标题和页码(使用基于上述指针编写的代码检索),就可以使用PdfStamper和insertPage()方法将页面插入到PDF文件中。您可以使用ColumnText将TOC放在这些页面上,也可以为TOC创建一个单独的PDF格式,并将其与原始页面合并。有关这两种技术的更多信息,请参见如何在现有的iText文档中添加cover/PDF。
您还将从这个示例中获益:使用java中的itext库为合并pdf创建索引文件(TOC)
至于标题和页码之间的虚线,使用分隔符,更具体地说,是虚线分隔符。你应该先读这个问题:iTextSharp -是否可以在同一单元格中为文本设置不同的对齐方式
然后阅读这个问题:如何为包装文本的最后一行在PdfPCell中生成数字点表示符 (或这个问题在一段的末尾,是否有可能剩余的空格充满了脚本?)
请注意,你的问题实际上是离题的。它的用词是“家庭工作”问题。它邀请人们在你的地方做你的工作。现在您已经具备了所需的所有元素,您应该能够自己完成这项工作。如果你没有成功,你应该写一个关于主题堆栈溢出的问题。在这个问题中,您展示了您尝试过的内容,并解释了您所经历的技术问题。
更新:
您与下列大纲树共享了一个文档:

如您所见,书签是使用命名目的地(如/__WKANCHOR_2、/__WKANCHOR_4等)定义的。从/字符中可以看出,名称存储为PDF对象(PDF1.1),而不是PDF对象(自1.2起)。最新的PDF标准建议使用PDF字符串对象而不是PDF名称对象,您可能需要要求PDF生成软件的供应商更新该软件,以满足最新PDF标准的建议。
然而,我们可以很容易地获得与那些命名目的地相对应的显式目的地。它们存储在根字典的/Dests条目中:

当您查看目的地的方式时,您会看到另一个应该报告给wkhtmltopdf的问题。让我们看看ISO标准告诉我们的目的地语法:

PDF中不存在页码的概念。使用页面字典描述页面,并从页面树中的页面位置导出页码。在页面树中遇到的第一个页面是第1页,遇到的第二个页面是第2页,依此类推。
在您的示例中,解释目的地的定义如下:[9/XYZ 30.2400000 524.179999 0]、[9/XYZ 30.2400000 231.379999 0]等等。
这是错误的。ISO标准指出,数组中的第一个值需要是一个间接引用。间接引用具有9 0 R格式,而不是9格式。我查看了文档的结构,我看到wkhtmltopdf使用一个页码-1,而不是间接引用。如果我看一下/__WKANCHOR_2,它指的是[0/XYZ 30.240000 781.459999 0],0应该指向第1页。由于Adobe容忍糟糕的软件,这在Adobe中有效,但是由于文件违反了ISO-32000,iText不知道如何处理那些误导性的目的地,至少iText不知道如何处理它。
幸运的是,iText是一个非常通用的库,它允许您深入到PDF的幕后。在这种情况下,我们只需要做一个更深的层次。我们可以使用以下方法来代替SimpleNamedDestination.getNamedDestination(reader, true):
HashMap<String, PdfObject> names = reader.getNamedDestinationFromNames();
for (Map.Entry<String, PdfObject> entry: names.entrySet()) {
System.out.print(entry.getKey());
System.out.print(": p");
PdfArray arr = (PdfArray)entry.getValue();
System.out.println(arr.getAsNumber(0).intValue() + 1);
}
reader.close();该方法的输出是:
__WKANCHOR_w: p7
__WKANCHOR_y: p7
__WKANCHOR_2: p1
__WKANCHOR_4: p1
__WKANCHOR_16: p9
__WKANCHOR_14: p8
__WKANCHOR_18: p9
__WKANCHOR_1s: p13
__WKANCHOR_a: p2
__WKANCHOR_1q: p13
__WKANCHOR_1o: p12
__WKANCHOR_12: p8
__WKANCHOR_1m: p12
__WKANCHOR_e: p3
__WKANCHOR_10: p7
__WKANCHOR_1k: p12
__WKANCHOR_c: p3
__WKANCHOR_1i: p11
__WKANCHOR_i: p4
__WKANCHOR_8: p2
__WKANCHOR_g: p3
__WKANCHOR_1g: p11
__WKANCHOR_6: p1
__WKANCHOR_1e: p10
__WKANCHOR_m: p5
__WKANCHOR_1c: p10
__WKANCHOR_k: p4
__WKANCHOR_q: p5
__WKANCHOR_1a: p9
__WKANCHOR_o: p5
__WKANCHOR_u: p6
__WKANCHOR_s: p6如果我们检查__WKANCHOR_2,我们会发现它正确地指向了第1页,我检查了大纲中的最后一个链接,它指向了名为__WKANCHOR_1s的指定目的地,实际上:它应该链接到第13页。
您的问题是“垃圾中的垃圾输出”问题的一个明显例子。您的工具产生的PDF违反了ISO的PDF标准,因此您会浪费大量的时间来找出问题所在。但更糟糕的是:你让我因为别人的错而浪费时间。
https://stackoverflow.com/questions/39027586
复制相似问题