# Tables of Contents

> Generate tables of contents with ServerTextControl: structure levels in paragraph styles, TableOfContents settings, updates after a merge, TOC styles and links.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Document Processing > Tables of Contents
- **4715 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/tables-of-contents/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/tables-of-contents/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/tables-of-contents/llms-full.txt

---

Long contracts, reports and manuals open with a list of their headings, the page each one starts on and a link to it. TX Text Control generates such a table of contents from the structure levels of the paragraphs. In code, you mark the headings, insert a table of contents, update it after a merge has added headings and pages, change the look of its entries and read or remove the tables of contents of documents you load.

The dialog and the JavaScript API that users work with in the browser are described in [Tables of Contents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/tables-of-contents/llms-full.txt) in the Document Editor section. Paragraph styles, which carry the structure levels, are introduced in [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/#use-paragraph-styles).

### How Tables of Contents Work

A table of contents lists the paragraphs whose structure level lies in a range you choose:

- **Structure levels.** [ParagraphFormat.StructureLevel](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/paragraphformat/structurelevel-property/llms-full.txt) is a number from 0 to 10. 0, the default, is body text; 1 is a top-level heading, 2 a heading below it and so on. A level can be set for a single paragraph, but it's usually part of a paragraph style, so that every heading with the style belongs to the level.
- **Generation.** When a table of contents is inserted, TX Text Control searches the document for the paragraphs in the level range and writes their text, with or without page numbers, at the input position.
- **Styles of the entries.** For the title and each level, a paragraph style is generated: `TOC_Title`, `TOC_Level1`, `TOC_Level2` and so on. Changing these styles changes the look of the entries.
- **Links.** Each entry can be a link to its heading: a `DocumentLink` that points to a `DocumentTarget` generated at the heading.
- **Several tables.** A document can contain several tables of contents, for example one per chapter, but they can't be nested.
- **Formats.** Tables of contents are imported from and exported to DOCX, RTF and DOC, with DOC only on the Classic engine, and kept in the TX Text Control format. In PDF documents, the entries are links, and the logical structure of the PDF marks the table of contents.

### Insert a Table of Contents

The following program writes a short agreement, defines two heading styles with structure levels, applies them and inserts a table of contents below the title. It saves the result as PDF and DOCX:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "Service Agreement\r\n" +
              "\r\n" +
              "Scope\r\n" +
              "The provider delivers the software.\r\n" +
              "Support Services\r\n" +
              "Support is available on business days.\r\n" +
              "Payment Terms\r\n" +
              "Invoices are payable within 30 days.";

    // Heading styles that carry the structure levels
    ParagraphStyle heading = new ParagraphStyle("Contract Heading");
    heading.FontSize = 320; // 16 pt
    heading.Bold = true;
    heading.ParagraphFormat.StructureLevel = 1;
    heading.ParagraphFormat.PageBreakBefore = true;
    heading.ParagraphFormat.KeepWithNext = true;
    tx.ParagraphStyles.Add(heading);

    ParagraphStyle subheading = new ParagraphStyle("Contract Subheading", "Contract Heading");
    subheading.FontSize = 280; // 14 pt
    subheading.ParagraphFormat.StructureLevel = 2;
    subheading.ParagraphFormat.PageBreakBefore = false;
    tx.ParagraphStyles.Add(subheading);

    tx.Paragraphs[3].FormattingStyle = "Contract Heading";
    tx.Paragraphs[5].FormattingStyle = "Contract Subheading";
    tx.Paragraphs[7].FormattingStyle = "Contract Heading";

    // The input position in the empty second paragraph (Paragraph.Start is one-based)
    tx.Select(tx.Paragraphs[2].Start - 1, 0);

    TableOfContents contents = new TableOfContents(1, 2)
    {
        Title = "Contents",
        Name = "contents",
        ID = 1,
        HasPageNumbers = true,
        HasRightAlignedPageNumbers = true,
        HasLinks = true
    };

    TableOfContentsCollection.AddResult result = tx.TablesOfContents.Add(contents);

    if (result != TableOfContentsCollection.AddResult.Successful)
    {
        Console.WriteLine($"No table of contents was inserted: {result}");
        return;
    }

    Console.WriteLine(contents.Text);

    tx.Save("agreement.pdf", StreamType.AdobePDF);
    tx.Save("agreement.docx", StreamType.WordprocessingML);
}
```

The code works as follows:

- `PageBreakBefore` starts each top-level heading on a new page, so the entries get different page numbers. The subheading style is based on the heading style and turns the page break off again.
- The [TableOfContents constructor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/constructor/llms-full.txt) takes the lowest and the highest structure level to include, each from 1 to 10.
- [Title](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/title-property/llms-full.txt) is the heading of the table of contents; an empty string means none. [Name](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/name-property/llms-full.txt) and the one-based [ID](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/id-property/llms-full.txt) identify it for your code.
- [HasPageNumbers](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/haspagenumbers-property/llms-full.txt) adds the page numbers. [HasRightAlignedPageNumbers](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/hasrightalignedpagenumbers-property/llms-full.txt) aligns them at the right border with a tab of the type `TabType.RightBorderTab`. [HasLinks](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/haslinks-property/llms-full.txt) turns every entry into a link to its heading.
- [TableOfContentsCollection.Add](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontentscollection/add-method/llms-full.txt) returns an [AddResult](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontentscollection/addresult-enumeration/llms-full.txt): `ContentNotFound` when no paragraph has a level in the range, `Error` at a position where no table of contents can be inserted, such as inside a field or another table of contents, and otherwise `Successful`.
- [Text](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/text-property/llms-full.txt) returns the generated text of the table of contents.

On the first page of *agreement.pdf*, below the title, the table of contents lists the two headings of level 1 and, indented, the subheading of level 2, each with a dotted leader and its page number at the right border:

![The table of contents in agreement.pdf: the title "Contents" and the entries Scope on page 2, the indented Support Services on page 2 and Payment Terms on page 3.](https://docs.textcontrol.com/assets/img/tx-text-control-dotnet-server/toc-page-numbers.729f34cd.webp)

### Update a Table of Contents After Changes

A table of contents doesn't follow later changes to the document by itself. After you add or remove headings, or after a merge has repeated blocks with headings and added pages, call [Update](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/update-method/llms-full.txt). The following program merges JSON data into a template that contains a table of contents and updates it before saving the PDF:

```csharp
using TXTextControl;
using TXTextControl.DocumentServer;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/report-template.tx", StreamType.InternalUnicodeFormat);

    using (MailMerge mailMerge = new MailMerge())
    {
        mailMerge.TextComponent = tx;
        mailMerge.MergeJsonData(File.ReadAllText("Documents/data.json"));
    }

    // Merged blocks added headings and pages: regenerate the entries and page numbers
    foreach (TableOfContents toc in tx.TablesOfContents)
    {
        TableOfContentsCollection.AddResult result = toc.Update();
        Console.WriteLine($"Table of contents {toc.Number}: {result}");
    }

    tx.Save("report.pdf", StreamType.AdobePDF);
}
```

`Update` regenerates the entries and page numbers and returns the same `AddResult` values as `Add`. The template is a document whose merge block contains a heading paragraph with a structure level, as in the blog article [Combining MailMerge and Table of Contents](https://www.textcontrol.com/blog/2022/03/22/combining-mailmerge-and-table-of-contents/). Merge blocks and the JSON data that fills them are described in [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/blocks/llms-full.txt).

### Change, Read and Remove Tables of Contents

The following program changes the style of the top-level entries, lists the tables of contents of a document with the links they generated and removes the table of contents named "contents":

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("agreement.docx", StreamType.WordprocessingML);

    // The style generated for the entries of level 1
    ParagraphStyle level1 = tx.ParagraphStyles.GetItem("TOC_Level1");

    if (level1 != null)
    {
        level1.Bold = true;
        level1.ParagraphFormat.TopDistance = 120;
        level1.Apply();
    }

    foreach (TableOfContents toc in tx.TablesOfContents)
    {
        toc.Update();
        Console.WriteLine($"{toc.Number} \"{toc.Name}\": levels {toc.MinimumStructureLevel} to {toc.MaximumStructureLevel}, " +
                          $"{toc.Length} characters from position {toc.Start}");
    }

    // The links of the entries
    foreach (DocumentLink link in tx.DocumentLinks)
    {
        if (link.AutoGenerationType == AutoGenerationType.TableOfContents)
        {
            Console.WriteLine($"Entry \"{link.Text}\" links to {link.DocumentTarget?.TargetName}");
        }
    }

    // Remove the table of contents with its text and the targets of its links
    TableOfContents contents = tx.TablesOfContents.GetItem("contents");

    if (contents != null)
    {
        tx.TablesOfContents.Remove(contents);
    }

    tx.Save("agreement-without-contents.docx", StreamType.WordprocessingML);
}
```

The code works as follows:

- `ParagraphStyles.GetItem` returns the generated style by its name, and [Apply](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/formattingstyle/apply-method/llms-full.txt) applies the changed style to the document.
- [Number](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/number-property/llms-full.txt) counts the tables of contents in the text flow from 1. [Start](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/start-property/llms-full.txt) is the one-based position of the first character and [Length](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontents/length-property/llms-full.txt) the number of characters.
- [DocumentLink.AutoGenerationType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/documentlink/autogenerationtype-property/llms-full.txt) is `TableOfContents` for the links that a table of contents generated and `None` for all others. [DocumentTarget.AutoGenerationType](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/documenttarget/autogenerationtype-property/llms-full.txt) does the same for targets, whose generated names begin with `TOC_`.
- [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontentscollection/getitem-method/llms-full.txt) takes a name or an ID and returns `null` if none matches. [Remove](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/tableofcontentscollection/remove-method/llms-full.txt) deletes the table of contents with all its text and all document targets its links point to.

### Tables of Contents in Other Text Parts

Headers, footers and text frames have their own collection, [IFormattedText.TablesOfContents](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/iformattedtext/tablesofcontents-property/llms-full.txt). To update every table of contents of a document, loop through [ServerTextControl.TextParts](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/textparts-property/llms-full.txt). The following program also lists the paragraphs that have a structure level, which shows which headings a table of contents of a loaded document can include:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/sample.docx", StreamType.WordprocessingML);

    foreach (Paragraph paragraph in tx.Paragraphs)
    {
        if (paragraph.Format.StructureLevel > 0)
        {
            Console.WriteLine($"Level {paragraph.Format.StructureLevel} ({paragraph.FormattingStyle}): {paragraph.Text}");
        }
    }

    foreach (IFormattedText textPart in tx.TextParts)
    {
        foreach (TableOfContents toc in textPart.TablesOfContents)
        {
            toc.Update();
        }
    }

    tx.Save("sample-updated.docx", StreamType.WordprocessingML);
}
```

To save a document without the table of contents data, set `SaveSettings.OmittedContent` to `OmittedContent.TablesOfContents`: the text and formatting of the entries are saved, but not the table of contents itself. [TableOfContentsCreated](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/tableofcontentscreated-event/llms-full.txt) and [TableOfContentsDeleted](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/tableofcontentsdeleted-event/llms-full.txt) occur when a table of contents is created or deleted, as [Events](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/events/llms-full.txt) describes.

### Next Steps

- [Paragraphs](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/paragraphs/#use-paragraph-styles): define the heading styles.
- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/blocks/llms-full.txt): repeat sections with headings for each record of your data.
- [Fields](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/fields/#add-hypertext-links-and-bookmarks): add links and bookmarks of your own.
- [Tables of Contents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/tables-of-contents/llms-full.txt) in the Document Editor: let users insert and update tables of contents.

---

## Nearby

- **Previous:** [Footnotes](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/footnotes/llms-full.txt)
- **Next:** [Fields](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/fields/llms-full.txt)
