如何使用itext创建多页TOC?

如何使用itext创建多页TOC?,itext,Itext,我需要在PDF中创建TOC。它可以是一页或多页,具体取决于PDF中的页数。我了解到可以使用PdfStamper,pdprotion,pdfarnotation来实现这一点 我目前正在合并多个文档,并为JAVA中的所有文档创建书签和TOC。我已经摆脱了书签,但被困在多页目录 另外,请解释代码的这一行-link=newpdfantation(copy,36,ct.getYLine(),559,y,action);。。。我所理解的是,在单击链接(,36,ct.getYLine(),559,y,)之后,

我需要在PDF中创建TOC。它可以是一页或多页,具体取决于PDF中的页数。我了解到可以使用
PdfStamper
pdprotion
pdfarnotation
来实现这一点

我目前正在合并多个文档,并为JAVA中的所有文档创建书签和TOC。我已经摆脱了书签,但被困在多页目录

另外,请解释代码的这一行-link=newpdfantation(copy,36,ct.getYLine(),559,y,action);。。。我所理解的是,在单击链接(,36,ct.getYLine(),559,y,)之后,您正在传递页面上矩形的尺寸。。因此,如果页面大小与我们的字母肖像不同,我将面临一个问题,即在点击链接时无法纠正页面的位置

下面是片段-

int tocPages = 1;
Document tocDocument = new Document();
String tocFilename ="toc-filename";
Phrase tocPhrase =
            new Phrase("Table of Contents", new Font(Font.FontFamily.HELVETICA, 20, Font.BOLD, BaseColor.BLACK));
PdfWriter writer = PdfWriter.getInstance(tocDocument, new FileOutputStream(tocFilename));
tocDocument.open();
tocDocument.add(new Paragraph(tocPhrase));
PdfReader reader = new PdfReader(tocFilename);
page = copy.getImportedPage(reader, tocPages);
stamp = copy.createPageStamp(page);

float y = 770;
ColumnText ct = new ColumnText(stamp.getOverContent());
ct.setSimpleColumn(36, 36, 559, y);
for (Map.Entry<Integer, String> entry : toc.entrySet()) {
if (y <= 20) {
copy.addPage(page);
                copy.newPage(); //(tried with writer.newPage() and tocDocument.newPage(), not working )
               page = copy.getImportedPage(reader, ++tocPages);
            }
            p = new Paragraph(entry.getValue());
            p.add(new Chunk(new DottedLineSeparator()));
            p.add(String.valueOf(entry.getKey() + 1));
            ct.addElement(p);
            ct.go();
            action = PdfAction.gotoLocalPage("p" + entry.getKey(), false);
            link = new PdfAnnotation(copy, 36, ct.getYLine(), 559, y, action);
            stamp.addAnnotation(link);
            y = ct.getYLine();
        }
        ct.go();
        stamp.alterContents();
        copy.addPage(page);
        tocDocument.close();
        reader.close();          
int-tocPages=1;
Document tocDocument=新文档();
字符串tocFilename=“toc filename”;
短语对短语=
新短语(“目录”,新字体(Font.FontFamily.HELVETICA,20,Font.BOLD,BASECLOR.BLACK));
PdfWriter writer=PdfWriter.getInstance(tocDocument,新文件输出流(tocFilename));
tocDocument.open();
添加(新的段落(短语));
PdfReader reader=新的PdfReader(文件名);
page=copy.getImportedPage(读卡器,tocPages);
stamp=copy.createPageStamp(第页);
浮动y=770;
ColumnText ct=新的ColumnText(stamp.getOverContent());
ct.setSimpleColumn(36,36559,y);
for(Map.Entry:toc.entrySet()){

如果(y您已经修改了您的问题,使其成为关于我对的回答中的这一片段的问题

我已经粘贴了完整的片段,因为这一行不能断章取义地解释

在代码段中,我们使用
pdfantation
类创建了一个链接注释。链接注释是页面上某个地方的一个区域,单击该区域时会触发一个操作

在这种情况下会触发哪个动作?这就是
动作
对象的内容,在这种情况下,它会跳转到由指定目的地定义的本地页面。这与HTML非常相似,HTML中有

创建
PdfAnotation
时,始终需要一个
PdfWriter
实例。在这种情况下,我们使用名为
copy
PdfCopy
实例合并文档。随着
PdfCopy
扩展
PdfWriter
,我们可以将
copy
实例作为参数传递

最后,我们定义了可点击区域。这始终是一个矩形,使用两个坐标定义:左下角的坐标和右上角的坐标

在上面的代码片段中,我们使用
ColumnText
添加段落
ColumnText
允许您在添加内容后获取有关当前
y
位置的信息。例如,当我们这样做时:

ct.addElement(p);
ct.go();
我们可以这样做以获得当前的Y坐标:

float y = ct.getYLine();
在我们的代码片段中,我们跟踪前面的
y
值(添加
p
之前的y位置),并使用
ct.getYLine()
的当前值来获取当前的
y
位置

这样,我可以像这样定义左下角的坐标:

float llx = 36;
float lly = ct.getYLine();
float urx = 559;
float ury = y;
右上角的坐标如下:

float llx = 36;
float lly = ct.getYLine();
float urx = 559;
float ury = y;
这些是在构造链接注释时可以看到的值

我对
x
值进行了硬编码。它们基于这样一个事实,即我正在创建一个具有A4大小页面和半英寸页边距的文档。a-4页面的宽度为595个用户单位。左侧,我有36个用户单位的页边距;右侧,我还有36个用户单位的页边距,我必须从页面宽度中减去:595-36=559

如果您有一个格式为字母的页面,则需要调整这些值。但是:最好根据现有页面的MediaBox/CropBox的实际值来计算这些值。这样,当您意外遇到具有不同页面大小的文档时,您的代码会继续工作


在我对这个问题的回答中,你可以阅读更多关于MediaBox和CropBox的信息:

有一个例子回答了重复的问题。你还应该解释更多关于这个过程的信息。你需要创建一个大纲树(也称书签)吗也是。您参考了
PdfStamper
,但不清楚如果您是从头开始创建文档,为什么需要它。请澄清您是否想要一个准确的答案。让我重复一下:如果您希望得到这个问题的答案,请说明您已经在做什么:您是从头开始创建文档吗?您是否正在尝试创建TOC对于现有文档(如果有,是否有书签)?您是在合并文档吗?您是在用Java还是C#编写代码?请将您的评论表述为一个真实的问题,提供足够的上下文,以便人们知道您的问题是关于什么的。您的问题不是独立的。我在回答中为其他人提供了理解问题所需的上下文。@Kapil如果您是从po开始的话,可能会这样问一个问题,解释你想做什么。你想创建一个TOC,但基于什么?这在你的问题中是绝对不清楚的。坏问题=坏答案。有什么区别?当有多个页面时,什么不起作用?