# Create a Table of Contents for Merged PDF Documents

## Environment

| Version    | Product          | Author                                                                |
| ---------- | ---------------- | --------------------------------------------------------------------- |
| 2026.1.304 | RadPdfProcessing | [Yoan Karamanov](https://www.telerik.com/blogs/author/yoan-karamanov) |

## Description

This article describes how to merge multiple PDF documents into a single file and then add a Table of Contents (TOC) page at the beginning of the merged document. Each TOC entry is a clickable link that navigates to the first page of the respective source document.

## Solution

Create the TOC **after** you merge all source documents. The key considerations are:

* The [FixedContentEditor](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/editing/fixedcontenteditor) requires manual position calculations when placing content elements on a page.
* Use the `Measure` method of the [Block](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/editing/block) to determine whether the next TOC entry exceeds the page boundary. If so, insert a new TOC page and continue from there.
* Track the start page index of each source document before merging so you can later build accurate [PDF Link Annotations](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/annotations/links) that use a [GoToAction](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/annotations/links) pointing to the correct [RadFixedPage](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/radfixedpage).
* When new TOC pages are inserted at the beginning of the [RadFixedDocument](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/radfixeddocument), adjust the target page index by the number of TOC pages added.

The following example shows the complete approach:

**Example 1: Merge PDF Files and Create a TOC**

```csharp
static void Main(string[] args)
{
    string sourceDirectory = @"..\..\..\PDF files";
    string outputFile = @"..\..\..\MergedOutput.pdf";

    MergePdfFiles(sourceDirectory, outputFile);
}

static void MergePdfFiles(string sourceDirectory, string outputFile)
{
    string[] pdfFiles = Directory.GetFiles(sourceDirectory, "*.pdf", SearchOption.TopDirectoryOnly);

    if (pdfFiles.Length == 0)
    {
        return;
    }

    RadFixedDocument mergedDocument = new RadFixedDocument();
    PdfFormatProvider formatProvider = new PdfFormatProvider();

    var documentStartPages = new System.Collections.Generic.List<System.Tuple<string, int>>();

    foreach (string pdfFile in pdfFiles.OrderBy(f => f))
    {
        int startPageIndex = mergedDocument.Pages.Count;
        string fileName = Path.GetFileNameWithoutExtension(pdfFile);

        RadFixedDocument sourceDocument;
        using (FileStream fileStream = File.OpenRead(pdfFile))
        {
            sourceDocument = formatProvider.Import(fileStream);
        }

        mergedDocument.Merge(sourceDocument);

        documentStartPages.Add(System.Tuple.Create(fileName, startPageIndex));
    }

    CreateTOC(mergedDocument, documentStartPages);

    using (FileStream outputStream = File.Create(outputFile))
    {
        formatProvider.Export(mergedDocument, outputStream);
    }
}

static void CreateTOC(RadFixedDocument document, System.Collections.Generic.List<System.Tuple<string, int>> documentStartPages)
{
    RadFixedPage currentTocPage = new RadFixedPage();
    document.Pages.Insert(0, currentTocPage);

    FixedContentEditor editor = new FixedContentEditor(currentTocPage);

    int factor = 20;
    int offsetX = 70;
    int currentY = 20;
    int tocPageIndex = 0;

    foreach (var docInfo in documentStartPages)
    {
        Block block = new Block();
        block.GraphicProperties.FillColor = new RgbColor(255, 5, 99, 193);
        block.InsertText($"{docInfo.Item1} - Page {docInfo.Item2 + 1}");
        Size blockSize = block.Measure();

        if (currentY + blockSize.Height > currentTocPage.Size.Height - 20)
        {
            tocPageIndex++;
            currentTocPage = new RadFixedPage();
            document.Pages.Insert(tocPageIndex, currentTocPage);
            editor = new FixedContentEditor(currentTocPage);
            currentY = 20;
        }

        editor.Position.Translate(offsetX, currentY);
        editor.DrawBlock(block);

        int adjustedPageIndex = docInfo.Item2 + tocPageIndex + 1;
        RadFixedPage targetPage = document.Pages[adjustedPageIndex];

        Location location = new Location
        {
            Left = 0,
            Top = 0,
            Zoom = 0,
            Page = targetPage
        };

        GoToAction goToAction = new GoToAction();
        goToAction.Destination = location;

        Link link = currentTocPage.Annotations.AddLink(goToAction);
        link.Rect = new Rect(offsetX, currentY, blockSize.Width, blockSize.Height);

        currentY += factor;
    }
}
```

## Notes

* The `documentStartPages` list records the zero-based start page index of each source document **before** the merge. This ensures correct navigation targets even after the TOC pages are prepended.
* The `adjustedPageIndex` calculation (`docInfo.Item2 + tocPageIndex + 1`) compensates for the TOC pages inserted before the merged content.
* Each TOC entry is drawn as a [Block](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/editing/block) and wrapped in a [PDF Link Annotation](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/annotations/links) whose rectangle matches the measured block bounds.

## See Also

* [Merge PDF Documents](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/features/merge-pdf-documents)
* [RadFixedDocument](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/radfixeddocument)
* [FixedContentEditor](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/editing/fixedcontenteditor)
* [Block](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/editing/block)
* [Link Annotations](https://www.telerik.com/document-processing-libraries/documentation/libraries/radpdfprocessing/model/annotations/links)
