3

I am trying to use PDFsharp and MigraDoc to create a PDF report file from many other files.

Basically the workflow is as follows:

  1. The user uploads 2 or more documents to concatenate
  2. The user selects what pages they want to include in the TOC
  3. The documents are concatenated together and a table of contents is generated

Now I am able to easily concatenate the documents and add bookmarks/outlines in PDFsharp. Where I have run into problems is when using MigraDoc to create the TOC referencing the PDFsharp created bookmarks/outlines as the targets of the hyperlinks.

Code to add bookmark/outline in PDFsharp (successfully adds the bookmarks):

// Current document is a PdfDocument and Title is the name of the bookmark
CurrentDocument.Outlines.Add(title, page, true, PdfOutlineStyle.Bold);

MigraDoc code to create the TOC page and render it to the current PDFsharp document:

// Create blank page
            PdfPage page = (!hasTitlePage)
                ? AddPage(null, 0, TOC_BOOKMARK_TITLE) // Add to start
                : AddPage(null, 1, TOC_BOOKMARK_TITLE); // Add after title page

            // Get Graphics obj
            XGraphics gfx = XGraphics.FromPdfPage(page);
            gfx.MUH = PdfFontEncoding.Unicode;

            // Create MigraDoc document + Setup styles
            Document document = new Document();
            DefineStyles(document);

            // Add header
            Section section = document.AddSection();
            Paragraph paragraph = section.AddParagraph("Table of Contents");
            paragraph.Format.Font.Size = 14;
            paragraph.Format.Font.Bold = true;
            paragraph.Format.SpaceAfter = 24;
            paragraph.Format.OutlineLevel = OutlineLevel.Level1;

            // Add links - these are the PdfSharp outlines/bookmarks added previously when concatinating the pages
            foreach (var bookmark in CurrentDocument.Outlines)
            {
                paragraph = section.AddParagraph();
                paragraph.Style = "TOC";
                Hyperlink hyperlink = paragraph.AddHyperlink(bookmark.Title);
                hyperlink.AddText($"{bookmark.Title}\t");
                hyperlink.AddPageRefField(bookmark.Title);
            }

            // Render document
            DocumentRenderer docRenderer = new DocumentRenderer(document);
            docRenderer.PrepareDocument();
            docRenderer.RenderPage(gfx, 1);

            return page;

Note - the MigraDoc code adds the TOC page but it doesn't recognize the PDFsharp bookmarks.

Screenshot of the TOC: The TOC page is added at the start (although the TOC bookmark is listed at the end) but I cannot link to PDFsharp bookmarks This is what the TOC looks like

I am certain that the issue is with my understanding of MigraDoc and/or PDFsharp.

First prize would be to only use PDFsharp to add the TOC. I would appreciate any help in being pointed in the right direction.

lukejkw
  • 1,054
  • 13
  • 19

1 Answers1

2

MigraDoc is a world of its own - it uses PDFsharp to create PDF files, but cannot access internals of PDF files creates with PDFsharp (like Bookmarks in your case).

One approach: create the TOC with PDFsharp (as you already suggested).

Other approach: use MigraDoc to add pages from existing PDF files to a MigraDoc document to create the final PDF (you can add pages from PDF files like you add images).

With the second approach you can use the formatting capabilities of MigraDoc for the TOC and MigraDoc will insert the correct page numbers, provided you add MigraDoc Bookmarks for every image (imported PDF page).

With the first approach, you will have to do the formatting and insert the page numbers yourself, but you'll have more control over the final PDF.

Which is the "best" approach? Depends a bit on the extent of formatting you need for your TOC. With the second approach the TOC can have two or more pages and MigraDoc will take care of that automatically and entries in the TOC can have two or more lines and MigraDoc will also take care of that automatically. But I think a hack will be needed to add the Outlines (e.g. draw very small white text with the outline text somewhere on the page).

Update: For the PDFsharp only approach, you will add links with code like this:

PdfRectangle prect = new PdfRectangle(gfx.Transformer.WorldToDefaultPage(rect));
page.AddDocumentLink(prect, 1);

The second parameter to AddDocumentLink is the target page.

  • I see. Since I have already written the majority of the code in PdfSharp, I will try the PdfSharp TOC approach. Would you be able to point me in the direction of how to actually create the PdfSharp Equivelent of a "link" to a bookmark? I am battling to find an example through my searches of your site. Thanks! – lukejkw Apr 28 '16 at 07:51
  • Thanks for the help and continued work on a fantastic library. One more question, what does the `rect` param denote? You didn't specify it's initialization. – lukejkw Apr 28 '16 at 08:13
  • The `rect` is the clickable area for the hyperlink. The hyperlink exists of its own - you do not have to draw anything there, but in your case make the rect around the text of your TOC line. – I liked the old Stack Overflow Apr 28 '16 at 09:14
  • Got it, thanks. FYI - The AddDocumentLink is not 0-based as mentioned in your answer. It is based on the page numbers. – lukejkw Apr 28 '16 at 09:51
  • AddDocumentLink causes a rectangle box to appear around the text. Is there an option to make the text look like a link instead of adding a rectangle aroung it? Does PDFSharp support this? – SandhraPrakash Oct 30 '17 at 12:43
  • @Sandy How old is your PDFsharp version? Very old, I presume. Time for an upgrade, I suppose. – I liked the old Stack Overflow Nov 06 '17 at 09:20
  • 1
    @Sandy You can patch the v1.32 source code if you have to stick to the old version: http://forum.pdfsharp.net/viewtopic.php?p=6161#p6161 – I liked the old Stack Overflow Nov 07 '17 at 10:36
  • @IlikedtheoldStackOverflow Im dealing with same issue here and im stuck on how can i add PdfDocument's Pages to the MigraDoc document ? And I want to keep the outline, that is very important.. basically I have similar situation - I have pdf which have an outline and I want to prepend page which takes ourline and makes "Table of contents" as a first page with links to the document – vmachacek May 06 '22 at 18:17
  • @vmachacek did you solve your problem and if you did then how? – deralbert Dec 30 '22 at 17:08
  • @deralbert here https://gist.github.com/vmachacek/7e13fc9c41e8ef189aef815ee200e83c if you create new console app and paste it there and update csproj as per snippet it should work. This work on my machine, but no grantees. Also it takes reference on WPF which is okay in my case but less than ideal for most applications.. I hope it will help you – vmachacek Dec 30 '22 at 18:03
  • @deralbert also you can checkout my question here https://stackoverflow.com/questions/72146010/generate-table-of-contents-from-outline-and-prepend-to-existing-pdf-file-with-pd – vmachacek Dec 30 '22 at 18:10