How do I add bookmarks to PDF using iTextSharp in Visual Studio

Posted on 2016-11-04
Last Modified: 2016-11-25
I am trying to add a bookmark when I merge PDFs into one PDF.  It's, of course, not working.  Any help or direction would be greatly appreciated.

Here is my code:

                        Dim merged As Boolean = True

                        Using Stream As New FileStream(jfFile, FileMode.Create)

                            Dim document As New Document()
                            Dim pdf As New PdfCopy(document, Stream)
                            Dim reader As PdfReader = Nothing
                            Dim writer As PdfWriter = Nothing
                            Dim pNumber As Integer = 0

                                Dim getPDF = (From id In d.tbl645s _
                                   Where id.closedDate = "" _
                                    Or id.closedDate Is Nothing _
                                    Order By id.projName1 Ascending _
                                    Select id.hardcopyLink).ToList

                                getPDF.Insert(0, jfFileOrg)

                                Dim chpNo As Integer = 1

                                For Each file As String In getPDF

                                    Dim getName = (From id In d.tbl645s _
                                                  Where id.hardcopyLink = file _
                                                  Select id.projNumber2).ToList

                                    If getName.Count = 1 Then

                                        reader = New PdfReader(file)
                                        Dim chap As New Chapter("Chapter ", chpNo)
                                        chap.BookmarkTitle = CStr(getName.Item(0))
                                        chap.BookmarkOpen = True
                                        chpNo += 1
                                        reader = New PdfReader(file)
                                    End If


                            Catch generatedExceptionName As Exception
                                merged = False
                                If reader IsNot Nothing Then
                                End If
                                If document IsNot Nothing Then
                                End If
                            End Try
                        End Using

Open in new window

Question by:Karen Wilson
LVL 32

Accepted Solution

Robberbaron (robr) earned 500 total points
Comment Utility
I use PDFSharp, similar but has a better licence.

In it, bookmark page is called Outline..

and to that I add DocumentLinks
XRect docid_rect = new XRect(new PdfSharp.Drawing.XPoint(marginX, yIdx - contentBoxHt), new PdfSharp.Drawing.XPoint(gfx.PageSize.Width, yIdx));
	outlineEntry = string.Format("{0} ({1}) : {2} ", id.DocId, id.RevId, id.DocName);
	gfx.DrawString(outlineEntry, font, XBrushes.CadetBlue, docid_rect, XStringFormats.TopLeft);

	//have to transform to Defult page orientation
	PdfRectangle linkzone = new PdfRectangle(gfx.Transformer.WorldToDefaultPage(docid_rect));
	pageIdx.AddDocumentLink(linkzone, outPDF.PageCount + indexpages);  //link to page about to be added
	idxCount++;  //count the number of indexs written

	// Create a sub bookmark
	//outline.Outlines.Add(id.FileName, page, true);
	outline.Outlines.Add(outlineEntry, page, true);  //add full index entry

Open in new window

hope this helps

Author Closing Comment

by:Karen Wilson
Comment Utility
After doing more research I found a different solution.  I will give you the credit because you answered and your answer falls in line with what I did.  Here is the code I used for others who may read this question.

I created a function to perform the bookmarking.  I got this from a previous answer in Expert Exchange and converted it to  It, of course, uses information that I require so you'll have to change bits of it to meet your need.

 Public Function MergePdfFiles(ByVal pdfFiles() As String, ByVal outputPath As String) As Boolean

        Dim result As Boolean = False
        Dim pdfCount As Integer = 0 'total input pdf file count
        Dim f As Integer = 0 'pointer to current input pdf file
        Dim fileName As String = String.Empty 'current input pdf filename
        Dim reader As iTextSharp.text.pdf.PdfReader = Nothing
        Dim pageCount As Integer = 0 'current input pdf page count
        Dim pdfDoc As iTextSharp.text.Document = Nothing 'the output pdf document
        Dim writer As PdfWriter = Nothing
        Dim cb As PdfContentByte = Nothing
        'Declare a variable to hold the imported pages
        Dim page As PdfImportedPage = Nothing
        Dim rotation As Integer = 0
        'Declare a font to used for the bookmarks
        Dim bookmarkFont As iTextSharp.text.Font = iTextSharp.text.FontFactory.GetFont(iTextSharp.text.FontFactory.HELVETICA, _
        8, iTextSharp.text.Font.NORMAL, iTextSharp.text.BaseColor.GRAY)

            pdfCount = pdfFiles.Length

            If pdfCount > 1 Then
                'Open the 1st pad using PdfReader object
                fileName = pdfFiles(f)
                reader = New iTextSharp.text.pdf.PdfReader(fileName)
                'Get page count
                pageCount = reader.NumberOfPages
                'Instantiate an new instance of pdf document and set its margins. This will be the output pdf.
                'NOTE: bookmarks will be added at the 1st page of very original pdf file using its filename. The location
                'of this bookmark will be placed at the upper left hand corner of the document. So you'll need to adjust
                'the margin left and margin top values such that the bookmark won't overlay on the merged pdf page. The
                'unit used is "points" (72 points = 1 inch), thus in this example, the bookmarks' location is at 1/4 inch from
                'left and 1/4 inch from top of the page.
                pdfDoc = New iTextSharp.text.Document(reader.GetPageSizeWithRotation(1), 18, 18, 18, 18)
                'Instantiate a PdfWriter that listens to the pdf document
                writer = PdfWriter.GetInstance(pdfDoc, New System.IO.FileStream(outputPath, System.IO.FileMode.Create))
                'Set metadata and open the document
                With pdfDoc
                    'Use the filename as the title... You can give it any title of course.
                    .AddTitle("PMP Data Pack")
                    'Add keywords, whatever keywords you want to attach to it
                    .AddKeywords("Report, Merged PDF, " & System.IO.Path.GetFileName(outputPath))
                End With
                'Instantiate a PdfContentByte object
                cb = writer.DirectContent
                'Now loop thru the input pdfs
                While f < pdfCount
                    'Declare a page counter variable
                    Dim i As Integer = 0
                    'Loop thru the current input pdf's pages starting at page 1
                    While i < pageCount
                        i += 1
                        'Get the input page size
                        'Create a new page on the output document
                        'If it is the 1st page, we add bookmarks to the page
                        If i = 1 Then
                            'First create a paragraph using the filename as the heading

                            Dim getTO = (From id In d.tbl645s _
                                        Where id.hardcopyLink = CStr(fileName) _
                                        Select id.projNumber2).ToList

                            Dim fName As String = "Task Orders"

                            If getTO.Count = 1 Then
                                fName = CStr(getTO.Item(0))
                            End If

                            Dim para As New iTextSharp.text.Paragraph(fName.ToUpper(), bookmarkFont)
                            'Then create a chapter from the above paragraph
                            Dim chpter As New iTextSharp.text.Chapter(para, f + 1)
                            'Finally add the chapter to the document
                        End If
                        'Now we get the imported page
                        page = writer.GetImportedPage(reader, i)
                        'Read the imported page's rotation
                        rotation = reader.GetPageRotation(i)
                        'Then add the imported page to the PdfContentByte object as a template based on the page's rotation
                        If rotation = 90 Then
                            cb.AddTemplate(page, 0, -1.0F, 1.0F, 0, 0, reader.GetPageSizeWithRotation(i).Height)
                        ElseIf rotation = 270 Then
                            cb.AddTemplate(page, 0, 1.0F, -1.0F, 0, reader.GetPageSizeWithRotation(i).Width + 60, -30)
                            cb.AddTemplate(page, 1.0F, 0, 0, 1.0F, 0, 0)
                        End If
                    End While
                    'Increment f and read the next input pdf file
                    f += 1
                    If f < pdfCount Then
                        fileName = pdfFiles(f)
                        reader = New iTextSharp.text.pdf.PdfReader(fileName)
                        pageCount = reader.NumberOfPages
                    End If
                End While
                'When all done, we close the docum went so that the pdfwriter object can write it to the output file
                result = True
            End If
        Catch ex As Exception
            Throw New Exception(ex.Message)
        End Try
        Return result
    End Function


I then made a list of all the PDFs I require and put it into an array.  I ran it through the function and added adding page numbers to my merged PDF.

 Dim getPDF = (From id In d.tbl645s _
                            Where id.closedDate = "" _
                            Or id.closedDate Is Nothing _
                            Order By id.projName1 Ascending _
                            Select id.hardcopyLink).ToList

                       getPDF.Insert(0, jfFileOrg) 'I am adding the cover page I created to the list of PDFs

                        Dim input() As String = getPDF.ToArray
                        Dim output As String = jfFile 'Then call the function to merge the files
                        If MergePdfFiles(input, output) = True Then

                            '=========  Add Page Numbers ========================

                            Dim bytes As Byte() = File.ReadAllBytes(jfFile)

                            Dim blackFont As iTextSharp.text.Font = FontFactory.GetFont("Arial", 9, Font.Bold, BaseColor.BLACK)

                            Using stream As New MemoryStream()

                                Dim reader As New PdfReader(bytes)

                                Using stamper As New PdfStamper(reader, stream)

                                    Dim pages As Integer = reader.NumberOfPages

                                    For i As Integer = 1 To pages
                                        ColumnText.ShowTextAligned(stamper.GetUnderContent(i), Element.ALIGN_LEFT, New Phrase(i.ToString() & " of " & CStr(pages), blackFont), 568.0F, 15.0F, 0)

                                End Using

                                bytes = stream.ToArray()

                            End Using

                            File.WriteAllBytes(jfFile, bytes)

                            MessageBox.Show("Files did not merged successfully")
                        End If

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

It’s quite interesting for me as I worked with Excel using for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Here's a very brief overview of the methods PRTG Network Monitor ( offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor ( If you're looking for how to monitor bandwidth using netflow or packet s…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now