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
ID: 41875290
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
ID: 41877033
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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 …
The ECB site provides FX rates for major currencies since its inception in 1999 in the form of an XML feed. The files have the following format (reducted for brevity) (CODE) There are three files available HERE (…
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: (…
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

911 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

24 Experts available now in Live!

Get 1:1 Help Now