创建包含文本章节链接的 PDF Table 目录

Create PDF Table of Contents with links to chapter of text

我在创建 PDF 文档时遇到文本章节链接的问题。 我使用 here 的 Bruno Lowagie 代码,但它是 Java,我遇到了一些困难。

我是这样做的:

class TOCEvents

public class TOCEvents : PdfPageEventHelper
{

    //protected System.Collections.Generic.List<TitleTOC> toc = new System.Collections.Generic.List<TitleTOC>();
    protected Dictionary<string, int> toc = new Dictionary<string, int>(5);

    public override void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text)
    {
        toc.Add(text, writer.PageNumber);
    }

    public Dictionary<string, int> GetTOC()
    {
        return toc;
    }

}

主要

                    for (int i = 0; i < 10; i++)
                {
                    String title = "This is title " + i;
                    Chunk c = new Chunk(title, f14);
                    c.SetGenericTag(title);
                    doc.Add(new Paragraph(c));
                    for (int j = 0; j < 50; j++)
                    {
                        doc.Add(new Paragraph("Line " + j + " of title " + i));
                    }
                }
                doc.NewPage();

                doc.Add(new Paragraph("Table of Contents", f24));

                Chunk dottedLine = new Chunk(new iTextSharp.text.pdf.draw.DottedLineSeparator());
                Dictionary<string, int> entries = ev.GetTOC();
                Paragraph p;

                foreach (KeyValuePair<string, int> entry in entries)
                {
                    Chunk chunk = new Chunk(entry.Key);
                    chunk.SetAction(PdfAction.GotoLocalPage(entry.Key, false));

                    p = new Paragraph(chunk);
                    p.Add(dottedLine);

                    chunk = new Chunk(entry.Value.ToString());
                    chunk.SetAction(PdfAction.GotoLocalPage(entry.Key, false));

                    p.Add(chunk);

                    doc.Add(p);


                }

我遇到了这个问题:

foreach (KeyValuePair<string, int> entry in entries)
                {
                    Chunk chunk = new Chunk(entry.Key);
                    chunk.SetAction(PdfAction.GotoLocalPage(entry.Key, false));

                    p = new Paragraph(chunk);
                    p.Add(dottedLine);

                    chunk = new Chunk(entry.Value.ToString());
                    chunk.SetAction(PdfAction.GotoLocalPage(entry.Key, false));

                    p.Add(chunk);

                    doc.Add(p);


                }

我做错了什么?我无法设置指向文本章节的链接。我想,我用错了 Dictionary<string, int>。我哪里错了?

谢谢。

您正在创建这样的目录:

| key       | page number |
|-----------|-------------|
| Chapter 1 |    1        |
| Chapter 2 |    5        |
| Chapter 3 |    7        |
| Chapter 4 |    9        |
| Chapter 5 |   10        |

您这样呈现此信息:

Chapter 1 ................... 1
Chapter 2 ................... 5
Chapter 3 ................... 7
Chapter 4 ................... 9
Chapter 5 .................. 10

您这样做的方式是,当您单击目录中的标题或页码时,您会触发 link 到名称为 Chapter X 的指定目的地,其中 X 是从 1 到 5 的数字。

单击 link 时没有任何反应,也不应该发生任何反应,因为您尚未在任何地方定义名称为 Chapter X 的任何目的地。

您复制了我在 Java 中为您编写的代码,更具体地说是 CreateTOC2 example. I wrote this example based on an example that was written in answer to your previous question How to create Table Of Contents in iTextSharp

但是,您忽略了 TOCEvent 更改的事实:

public class TOCEvent extends PdfPageEventHelper {

    protected int counter = 0;
    protected List<SimpleEntry<String, SimpleEntry<String, Integer>>> toc = new ArrayList<>();

    @Override
    public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) {
        String name = "dest" + (counter++);
        int page = writer.getPageNumber();
        toc.add(new SimpleEntry<String, SimpleEntry<String, Integer>>(text, new SimpleEntry<String, Integer>(name, page)));
        writer.addNamedDestination(name, page, new PdfDestination(PdfDestination.FITH, rect.getTop()));
    }

    public List<SimpleEntry<String, SimpleEntry<String, Integer>>> getTOC() {
        return toc;
    }
}

在这个新的 TOCEvent 中,我们跟踪 counter。每次遇到标题时,都会创建一个新的(唯一的!)名称,并且计数器会增加。

 String name = "dest" + (counter++);

使用这个名称,您必须创建一个命名目的地。在这种情况下,我们在特定的 Y 位置创建一个 /FitH(水平放置)目的地:

writer.addNamedDestination(
    name,  // the unique name
    page,  // the current page number where the title is added
    new PdfDestination(        // the destination on that page
        PdfDestination.FITH, rect.getTop()));

您没有添加任何此类目的地,因此您不能 link 到文档中的任何命名目的地。

在我的示例中,我将唯一名称传递给目录:

| key       | named destination | page number |
|-----------|-------------------|-------------|
| Chapter 1 |    dest0          |    1        |
| Chapter 2 |    dest1          |    5        |
| Chapter 3 |    dest2          |    7        |
| Chapter 4 |    dest3          |    9        |
| Chapter 5 |    dest4          |   10        |

当我创建 TOC 时,我使用这些名称,dest0dest1,...来创建这样的操作:

PdfAction.gotoLocalPage("dest0", false)
PdfAction.gotoLocalPage("dest1", false)
PdfAction.gotoLocalPage("dest2", false)
PdfAction.gotoLocalPage("dest3", false)
PdfAction.gotoLocalPage("dest4", false)

您使用了错误的值,您创建的 link 是这样的:

PdfAction.gotoLocalPage("Chapter 1", false)
PdfAction.gotoLocalPage("Chapter 2", false)
PdfAction.gotoLocalPage("Chapter 3", false)
PdfAction.gotoLocalPage("Chapter 4", false)
PdfAction.gotoLocalPage("Chapter 5", false)

这永远行不通,除非您使用 Chapter 1Chapter 2、... 作为您指定目的地的名称。由于您无法确定这些名称将始终是唯一的,因此我认为我的方法是更好的选择。

您的问题我做错了什么?的答案很简单:您正在创建 link,但您忘记创建目的地。