Table of Contents Functionality with C# and .NET

Creating a Table of Contents (TOC) in a PDF document is a crucial feature for enhancing document navigation and user experience. With Sautinsoft.Pdf.Net, you can easily generate a TOC using C# and .NET. This article will guide you through the process of creating a TOC in a PDF document using Sautinsoft PDF.Net.

To add a TOC, you need to create a list of entries that will be included in the TOC. Each entry should have a title and a page number. Here’s how you can do it:

  1. Add SautinSoft.PDF from NuGet.
  2. Create a new PDF document and merge multiple PDF documents the new single PDF.
  3. Create a table of contents.
  4. Remove empty (placeholder) pages.
  5. Insert TOC pages and update TOC links.
  6. Save document as PDF.

Input file:

Output result:

Complete code

using System;
using System.IO;
using System.Reflection;
using SautinSoft;
using SautinSoft.Document;
using SautinSoft.Pdf;
using SautinSoft.Pdf.Annotations;
using SautinSoft.Pdf.Content;

namespace Sample
{
    class Sample
    {
        /// <summary>
        /// Merge PDF files and create TOC.
        /// </summary>
        /// <remarks>
        /// Details: https://sautinsoft.com/products/pdf/help/net/developer-guide/table-of-content.php
        /// </remarks>
        static void Main(string[] args)
        {
            // Before starting this example, please get a free 100-day trial key:
            // https://sautinsoft.com/start-for-free/

            // Apply the key here:
            // PdfDocument.SetLicense("...");
            
            string[] inpFiles = new string[] {
                        Path.GetFullPath(@"..\..\..\Simple Text.pdf"),
                        Path.GetFullPath(@"..\..\..\Potato Beetle.pdf"),
                        Path.GetFullPath(@"..\..\..\Text and Graphics.pdf")};

            string outFile = Path.GetFullPath(@"Merged.pdf");
            var tocEntries = new List<(string Title, int PagesCount)>();
            // Create a new PDF document.
            using (var pdf = new PdfDocument())
            {
                // Merge multiple PDF documents the new single PDF.
                foreach (var inpFile in inpFiles)
                    using (var source = PdfDocument.Load(inpFile))
                    {
                        pdf.Pages.Kids.AddClone(source.Pages);
                        tocEntries.Add((Path.GetFileNameWithoutExtension(inpFile), source.Pages.Count));
                    }

                int pagesCount;
                int tocPagesCount;

                // Create PDF with Table of Contents.
                using (var tocDocument = PdfDocument.Load(CreatePdfWithToc(tocEntries)))
                {
                    pagesCount = tocDocument.Pages.Count;
                    tocPagesCount = pagesCount - tocEntries.Sum(entry => entry.PagesCount);

                    // Remove empty (placeholder) pages.
                    for (int i = pagesCount - 1; i >= tocPagesCount; i--)
                        tocDocument.Pages.RemoveAt(i);

                    // Insert TOC pages.
                    pdf.Pages.Kids.InsertClone(0, tocDocument.Pages);
                }

                int entryIndex = 0;
                int entryPageIndex = tocPagesCount;

                // Update TOC links and outlines so that they point to adequate pages instead of placeholder pages.
                for (int i = 0; i < tocPagesCount; i++)
                    foreach (var annotation in pdf.Pages[i].Annotations.OfType<PdfLinkAnnotation>())
                    {
                        var entryPage = pdf.Pages[entryPageIndex];
                        annotation.SetDestination(entryPage, PdfDestinationViewType.FitPage);

                        entryPageIndex += tocEntries[entryIndex].PagesCount;
                        ++entryIndex;
                    }

                pdf.Save(outFile);
            }
            // Show the result.
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(outFile) { UseShellExecute = true });
        }

        static Stream CreatePdfWithToc(List<(string Title, int PagesCount)> tocEntries)
        {
            // Create new document.
            var document = new DocumentCore();
            var section = new Section(document);
            document.Sections.Add(section);

            // Add Table of Content.
            var toc = new TableOfEntries(document, FieldType.TOC);
            section.Blocks.Add(toc);

            // Create heading style.
            var heading1Style = (ParagraphStyle)document.Styles.GetOrAdd(StyleTemplateType.Heading1);
            heading1Style.ParagraphFormat.PageBreakBefore = true;

            // Add heading paragraphs and empty (placeholder) pages.
            foreach (var tocEntry in tocEntries)
            {
                section.Blocks.Add(
                    new Paragraph(document, tocEntry.Title)
                    { ParagraphFormat = { Style = heading1Style } });

                for (int i = 0; i < tocEntry.PagesCount; i++)
                    section.Blocks.Add(
                        new Paragraph(document,
                            new SpecialCharacter(document, SpecialCharacterType.PageBreak)));
            }

            // Remove last extra-added empty page.
            section.Blocks.RemoveAt(section.Blocks.Count - 1);

            // When updating TOC element, an entry is created for each paragraph that has heading style.
            // The entries have the correct page numbers because of the added placeholder pages.
            toc.Update();

            // Save document as PDF.
            var pdfStream = new MemoryStream();
            document.Save(pdfStream, new SautinSoft.Document.PdfSaveOptions());
            return pdfStream;
        }
    }
}

Download

Imports System
Imports System.IO
Imports System.Reflection.Metadata
Imports SautinSoft
Imports SautinSoft.Document
Imports SautinSoft.Pdf
Imports SautinSoft.Pdf.Annotations
Imports SautinSoft.Pdf.Content

Namespace Sample
    Class Sample
        ''' <summary>
        ''' Merge PDF files and create TOC.
        ''' </summary>
        ''' <remarks>
        ''' Details: https://sautinsoft.com/products/pdf/help/net/developer-guide/table-of-content.php
        ''' </remarks>
        Shared Sub Main(args As String())
            ' Before starting this example, please get a free 100-day trial key:
            ' https://sautinsoft.com/start-for-free/

            ' Apply the key here:
            ' PdfDocument.SetLicense("...")

            Dim inpFiles As String() = {
                Path.GetFullPath("..\..\..\Simple Text.pdf"),
                Path.GetFullPath("..\..\..\Potato Beetle.pdf"),
                Path.GetFullPath("..\..\..\Text and Graphics.pdf")
            }

            Dim outFile As String = Path.GetFullPath("Merged.pdf")
            Dim tocEntries As New List(Of (Title As String, PagesCount As Integer))

            ' Create a new PDF document.
            Using pdf As New PdfDocument()
                ' Merge multiple PDF documents the new single PDF.
                For Each inpFile In inpFiles
                    Using source As PdfDocument = PdfDocument.Load(inpFile)
                        pdf.Pages.Kids.AddClone(source.Pages)
                        tocEntries.Add((Path.GetFileNameWithoutExtension(inpFile), source.Pages.Count))
                    End Using
                Next

                Dim pagesCount As Integer
                Dim tocPagesCount As Integer

                ' Create PDF with Table of Contents.
                Using tocDocument As PdfDocument = PdfDocument.Load(CreatePdfWithToc(tocEntries))
                    pagesCount = tocDocument.Pages.Count
                    tocPagesCount = pagesCount - tocEntries.Sum(Function(entry) entry.PagesCount)

                    ' Remove empty (placeholder) pages.
                    For i As Integer = pagesCount - 1 To tocPagesCount Step -1
                        tocDocument.Pages.RemoveAt(i)
                    Next

                    ' Insert TOC pages.
                    pdf.Pages.Kids.InsertClone(0, tocDocument.Pages)
                End Using

                Dim entryIndex As Integer = 0
                Dim entryPageIndex As Integer = tocPagesCount

                ' Update TOC links and outlines so that they point to adequate pages instead of placeholder pages.
                For i As Integer = 0 To tocPagesCount - 1
                    For Each annotation In pdf.Pages(i).Annotations.OfType(Of PdfLinkAnnotation)()
                        Dim entryPage As PdfPage = pdf.Pages(entryPageIndex)
                        annotation.SetDestination(entryPage, PdfDestinationViewType.FitPage)

                        entryPageIndex += tocEntries(entryIndex).PagesCount
                        entryIndex += 1
                    Next
                Next

                pdf.Save(outFile)
            End Using

            ' Show the result.
            System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(outFile) With {.UseShellExecute = True})
        End Sub

        Shared Function CreatePdfWithToc(tocEntries As List(Of (Title As String, PagesCount As Integer))) As Stream
            ' Create new document.
            Dim document As New DocumentCore()
            Dim section As New Section(document)
            document.Sections.Add(section)

            ' Add Table of Content.
            Dim toc As New TableOfEntries(document, FieldType.TOC)
            section.Blocks.Add(toc)

            ' Create heading style.
            Dim heading1Style As ParagraphStyle = CType(document.Styles.GetOrAdd(StyleTemplateType.Heading1), ParagraphStyle)
            heading1Style.ParagraphFormat.PageBreakBefore = True

            ' Add headings and placeholder pages.
            For Each entry In tocEntries
                Dim heading As New Paragraph(document)
                heading.ParagraphFormat.Style = heading1Style
                heading.Content.Start.Insert(entry.Title)
                section.Blocks.Add(heading)

                For i As Integer = 1 To entry.PagesCount
                    section.Blocks.Add(New Paragraph(document))
                Next
            Next

            ' Save the document to a memory stream.
            Dim stream As New MemoryStream()
            document.Save(stream, New SautinSoft.Document.PdfSaveOptions())
            stream.Position = 0
            Return stream
        End Function
    End Class
End Namespace


Download


If you need a new code example or have a question: email us at support@sautinsoft.com or ask at Online Chat (right-bottom corner of this page) or use the Form below:



Questions and suggestions from you are always welcome!

We are developing .Net components since 2002. We know PDF, DOCX, RTF, HTML, XLSX and Images formats. If you need any assistance with creating, modifying or converting documents in various formats, we can help you. We will write any code example for you absolutely free.