Table of contents takes formatting from TC field

I’m merging multiple Word documents together and adding a table of contents at the beginning to link to each merged document.

I don’t control the documents, so for the table of contents to work correctly I’m not using the headers and instead I’m manually inserting TC fields at the start of each merged document to identify the places I want to show up in the ToC.

This all works, except that the ToC is getting the formatting from the merged document instead of using the TOC1 style, which is contrary to what the documentation says:

The formatting of entries in the TOC do not use the original styles of the marked entries, instead each level is formatted using an equivalent TOC style

Here is a document with formatting at the beginning - this causes my ToC to have a bold and yellow highlighted entry:

ComplyVision_General Brochure.docx[826_978].docx (7.7 KB)

Here is my code:

var mergedDoc = new Document();
var mergedDocBuilder = new DocumentBuilder(mergedDoc);

mergedDocBuilder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Title;
mergedDocBuilder.Writeln(title);
mergedDocBuilder.InsertBreak(BreakType.PageBreak);

// https://support.microsoft.com/en-us/office/field-codes-toc-table-of-contents-field-1f538bc4-60e6-4854-9f64-67754d78d05c
mergedDocBuilder.InsertTableOfContents(@"\h \z \f p");

var policiesWithDocuments = policies
    .Where(p => p.Document != null)
    .ToList();

foreach (var policy in policiesWithDocuments)
{
    using var vs = await _documentService.DownloadPolicyDocumentAsStreamAsync(policy.Document!.Id, false);

    var policyDoc = new Document(vs.Stream);

    policyDoc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;
    policyDoc.FirstSection.HeadersFooters.LinkToPrevious(false);

    var builder = new DocumentBuilder(policyDoc);
    builder.InsertField($@"TC ""{policy.Name}"" \f p");

    foreach (var srcSection in policyDoc.Sections)
    {
        var dstSection = mergedDoc.ImportNode(srcSection, true, ImportFormatMode.KeepSourceFormatting);

        mergedDoc.AppendChild(dstSection);
    }
}

mergedDoc.UpdateFields();
mergedDoc.UpdatePageLayout();

var ms = new MemoryStream();
mergedDoc.Save(ms, SaveFormat.Pdf);

@jmunro This is an expected behavior. MS Word also inherits highlight color form the TC field. You can test this using the following simple code:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.InsertTableOfContents(@"\h \z \f p");

builder.InsertBreak(BreakType.PageBreak);
builder.Font.HighlightColor = Color.Yellow;
builder.InsertField($@"TC ""Test"" \f p");

doc.UpdateFields();
doc.UpdatePageLayout();

doc.Save(@"C:\Temp\out.docx", SaveFormat.Docx);
doc.Save(@"C:\Temp\out.pdf", SaveFormat.Pdf);

Even if you update field manually in MS Word highlight color in TOC will be preserved.

In your case you should clear font formatting before inserting TC field:

builder.Font.ClearFormatting();
builder.InsertField($@"TC ""{policy.Name}"" \f p");

Thank you! That clears the highlight, but the size is still different

@jmunro It looks like MS Word always uses TC field formatting for entries in the TOC, so does Aspose.Words. So in your case you should manually apply the required formatting to TC fields.

1 Like

Can I apply StyleIdentifier.Toc1 to it or do I need to set the individual builder.Font properties?

@jmunro,

You can use the inner properties, because Font is a ReadOnly property:

builder.Font.Size = target.Styles[StyleIdentifier.Toc1].Font.Size;
1 Like

@jmunro Toc1 is paragraph style, but in your case you need a character style. You can create a character style that replicates formatting of TOC1 style:

Style charToc1 = doc.Styles.Add(StyleType.Character, "charToc1");
charToc1.Font.Size = doc.Styles[StyleIdentifier.Toc1].Font.Size;
charToc1.Font.Name = doc.Styles[StyleIdentifier.Toc1].Font.Name;
// etc...
// ...

builder.Font.Style = charToc1;
builder.InsertField($@"TC ""Test"" \f p \l 1");
1 Like