Reputation: 165
I create PDF document ant I have go problem with links to chapter of text. I use code of Bruno Lowagie from here, but it's Java and I have got some difficulties.
I'm doing like this:
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;
}
}
main
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);
}
I have got problems whith this:
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);
}
What am I doing wrong? I can't set links to chapters of text. I think, that i'm using wrong Dictionary<string, int>
. Where did i mistakes?
Thank you.
Upvotes: 1
Views: 3270
Reputation: 77528
You are creating a TOC like this:
| key | page number |
|-----------|-------------|
| Chapter 1 | 1 |
| Chapter 2 | 5 |
| Chapter 3 | 7 |
| Chapter 4 | 9 |
| Chapter 5 | 10 |
You render this information like this:
Chapter 1 ................... 1
Chapter 2 ................... 5
Chapter 3 ................... 7
Chapter 4 ................... 9
Chapter 5 .................. 10
You do this in such a way that, when you click a title in the TOC, or a page number, you trigger a link to a named destination with name Chapter X
where X is a number from 1 to 5.
Nothing happens when you click that link, and nothing should happen, because you haven't defined any destination with names Chapter X
anywhere.
You have copied code that I wrote for you in Java, more specifically the 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
However, you overlooked the fact that the TOCEvent
changed:
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;
}
}
In this new TOCEvent, we keep track of a counter
. Each time, a title is encountered, a new (unique!) name is created and the counter goes up.
String name = "dest" + (counter++);
With this name, you have to create a named destination. In this case, we create a /FitH
(fit horizontally) destination, at a specific Y position:
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()));
You do not add any such destinations, hence you can't link to any named destination in the document.
In my example, I pass the unique name to the 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 |
When I create the TOC, I use these names, dest0
, dest1
,... to create actions like this:
PdfAction.gotoLocalPage("dest0", false)
PdfAction.gotoLocalPage("dest1", false)
PdfAction.gotoLocalPage("dest2", false)
PdfAction.gotoLocalPage("dest3", false)
PdfAction.gotoLocalPage("dest4", false)
You use the wrong values, you create links like this:
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)
That can never work, unless you use Chapter 1
, Chapter 2
,... as names for your named destinations. As you can't be sure those names will always be unique, I think that my approach is the better choice.
The answer to your question What am I doing wrong? is simple: you are creating links, but you forgot to create the destinations.
Upvotes: 3