创建PDF目录,其中包含指向文本章节的链接

时间:2016-08-24 13:06:48

标签: java c# pdf itext

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

我这样做:

类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>。我哪里出错了?

谢谢。

1 个答案:

答案 0 :(得分:2)

您正在创建这样的TOC:

| 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

您这样做的方式是,当您单击TOC中的标题或页码时,您会触发指向名称为Chapter X的命名目标的链接,其中X是1到5之间的数字

单击该链接时没有任何反应,并且不会发生任何事情,因为您没有在任何地方定义名称为Chapter X的任何目标。

您复制了我用Java为您编写的代码,更具体地说是CreateTOC2示例。我根据您回答上一个问题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()));

您不添加任何此类目的地,因此您无法链接到文档中的任何指定目的地。

在我的例子中,我将唯一名称传递给TOC:

| 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)

您使用了错误的值,您可以创建如下链接:

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,...作为指定目的地的名称,否则无法使用。由于你不能确定这些名字总是独一无二的,我认为我的方法是更好的选择。

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