Unable to set font family for TOC

We generate a word & PDF document using Aspose.Words in C#.

This word document have multiple headings and of font family Georgia. When we add TOC to the document, TOC is by default inheriting the font family of actual Headers though we set Helvetica as font family for the current paragraph.

To solve this issue we tried writing following code:

// Calling code
ApplyStyles(builder, paragraphStyle, StyleIdentifier.Toc1);
ApplyStyles(builder, paragraphStyle, StyleIdentifier.Toc2);
ApplyStyles(builder, paragraphStyle, StyleIdentifier.Toc3);

builder.InsertTableOfContents("\\o \"2-2\" \\h \\z \\u");
private static void ApplyStyles(DocumentBuilder builder, Styles paragraphStyle, StyleIdentifier styleIdentifyer)
{
    var style = builder.Document.Styles[styleIdentifyer];
    style.Font.Name = paragraphStyle.FontFamily; // Setting this as Helvetica
    style.Font.Size = paragraphStyle.FontSize;

    var paragraphFormat = style.ParagraphFormat;

    paragraphFormat.SpaceBefore = paragraphStyle.SpaceBefore;

    paragraphFormat.LineSpacing = paragraphStyle.LineHeight;
    paragraphFormat.LineSpacingRule = LineSpacingRule.Exactly;

    var pageSetup = builder.PageSetup;
    var margins = 25;
    var tabStopPosition = pageSetup.PageWidth - (pageSetup.LeftMargin + pageSetup.RightMargin) - margins;
    paragraphFormat.LeftIndent += margins;
    paragraphFormat.TabStops.Add(new TabStop(tabStopPosition, TabAlignment.Right, TabLeader.Dots));
}

Though we set the font family as Helvetica, it is not getting applied for TOC. Hence we have written following workaround to apply the font family:

document.UpdateFields();
SetTOCFontStyles(builder);
private void SetTOCFontStyles(Document document)
{
    var tocFields = document.Range.Fields.OfType<FieldToc>();
    foreach (var tocEntry in tocFields)
    {
        var fontName = tocEntry.Start.Font.Name;
        var runs = tocEntry.Start.ParentParagraph.ParentNode.GetChildNodes(NodeType.Run, true);

        foreach (Run title in runs)
        {
            if (!title.ParentParagraph.ParagraphFormat.IsHeading)
            {
                title.Font.Name = fontName;
            }
        }
    }
}

This code is applying the font family as expected when the document is exported as word document. But while same document is exported in PDF format, changes are not being applied for font family. But all other styles are reflecting properly.

Can you provide any suggestions on how can we fix this issue?

@shridhartl

To address the issue of setting the font family for the Table of Contents (TOC) in your Word document generated using Aspose.Words, it seems that while you are successfully applying the font family in the Word format, the changes are not reflected when exporting to PDF. Here are some suggestions to help you resolve this:

  1. Ensure TOC Styles are Defined: Make sure that the styles for the TOC levels (e.g., TOC1, TOC2, TOC3) are properly defined before you insert the TOC. You can modify the styles directly in the document’s style collection.

  2. Update Fields Before Exporting: You are already calling document.UpdateFields();, which is essential. This ensures that the TOC is updated with the latest styles before exporting to PDF. Make sure this call is made right before the export.

  3. Check PDF Export Settings: Sometimes, specific settings during the PDF export can affect how styles are applied. Ensure that you are using the correct options for PDF export that allow for style retention.

  4. Use DocumentBuilder for Direct Formatting: Instead of relying solely on the TOC styles, you can directly format the runs in the TOC after it has been inserted. This can be done by iterating through the TOC entries and applying the desired font settings directly to the Run objects.

Here’s a modified version of your SetTOCFontStyles method that ensures the font is applied correctly:

private void SetTOCFontStyles(Document document)
{
    var tocFields = document.Range.Fields.OfType<FieldToc>();
    foreach (var tocEntry in tocFields)
    {
        var runs = tocEntry.Start.ParentParagraph.Runs;
        foreach (Run run in runs)
        {
            run.Font.Name = "Helvetica"; // Set your desired font here
            run.Font.Size = 12; // Set your desired font size here
        }
    }
}
  1. Test with Different PDF Formats: If you are targeting specific PDF standards (like PDF/A), ensure that the font you are using is embeddable and compliant with those standards. Sometimes, certain fonts may not render correctly in specific PDF formats.

  2. Review Documentation: For further details on customizing TOC styles and exporting to PDF, you may want to refer to the Aspose documentation on modifying TOC styles and the nuances of PDF export.

By following these steps, you should be able to achieve the desired font styling for your TOC in both Word and PDF formats. If the issue persists, consider reaching out to Aspose support for more tailored assistance.

Sources:
[1]: Change Toc Style In Word Document - Aspose
[2]: DocumentBuilder.InsertTableOfContents | Aspose.Words for .NET

@shridhartl By default, upon saving to PDF, Aspose.Words updates fields in the document. So all changes made to Run nodes inside TOC are reset. You can disable updating fields in PdfSaveOptions to avoid this:

Document doc = new Document(@"C:\Temp\in.docx");

// Do somethog with the document.
// ...............

PdfSaveOptions opt = new PdfSaveOptions();
opt.UpdateFields = false;
doc.Save(@"C:\Temp\out.pdf", opt);

Thank you @Professionalize.Discourse for your quick reply. However almost all the suggestions are already part of my sample code provided and those are not actually solving my issue.

Reply for your suggestions:

  1. Already I am defining the TOC styles for TOC. You can look at it in my original post.
  2. Like you already mentioned, I am already calling the Update fields right before exporting. I already tried moving it around a bit and tried.
  3. Already this document is having other fonts with Helvetica, so I am not really sure if this could be relevant for our issue. Any way I will give it a try once.
  4. This is what I have been already doing and you can see the source code. I debugged it and ensured it is getting assigned as expected. Moreover as I told it is working fine with Word document.

Thank you @alexey.noskov for your quick reply. I have already applied this “UpdateFields = false” in my actual code and hence this is not solving the issue.

Are there any other suggestions to try? or do you need any other details from me to further think though this?

@shridhartl Could you please attach your input, output and expected output documents here for our reference? We will test the scenario on our side and provide you more information.

Hi @alexey.noskov, Thank you for your response. I have managed to reproduce the issue in a separate standalone project.

I have attached the source code and output document as well. In word document font family of TOC is coming as expected. But in PDF, it is not working as expected. Same object when exported as Word it is working fine, but when exported as PDF it is having issue with font family.

Look at the font family of subtitle text in TOC which is coming as Verdana in Word Document, but coming as Georgia in PDF.

My header will contain two runs with two different family, but in TOC, I am expecting it to use different font I set which is working as expected with a workaround I added. But it is not working fine for PDF.

Program.zip (62.0 KB)

@shridhartl Thank you for additional information. The problem is that both MS Word and Aspose.Words applies the explicitly applied font of the heading paragraph in the TOC item. To avoid this, you can apply the fonts using styles. For example see the following simplified code:

// Create a new Word document
Document doc = new Document();
var builder = new DocumentBuilder(doc);

// Apply formatting of TOC 
ApplyStyles(builder, StyleIdentifier.Toc1);
ApplyStyles(builder, StyleIdentifier.Toc2);
ApplyStyles(builder, StyleIdentifier.Toc3);

// Configure Normal style.
doc.Styles[StyleIdentifier.Normal].Font.Name = PrimaryFont;
// Setup font of heading 2.
doc.Styles[StyleIdentifier.Heading2].Font.Name = PrimaryFont;
doc.Styles[StyleIdentifier.Heading2].Font.Size = 12;
// Add sub heading style
Style subHeading = doc.Styles.Add(StyleType.Character, "subHeading");
subHeading.Font.Name = SecondaryFont;
subHeading.Font.Size = 12d;

// Add the second pagedocument
builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Heading2;
builder.Font.Name = PrimaryFont;
builder.Writeln("Table of Contents");

// Add the table of contents
builder.ParagraphFormat.ClearFormatting();
builder.Font.ClearFormatting();
builder.Writeln();
builder.InsertTableOfContents($"\\o \"2-2\" \\h \\z \\u");
builder.Writeln();
builder.InsertBreak(BreakType.PageBreak);

for (int i = 2; i <= 3; i++)
{
    builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Heading2;
    builder.Write($"TOC Header {i} in {PrimaryFont}");

    // Following font I set as SecondaryFont in header, but want to set TOCFont for TOC Entry
    builder.Font.Style = subHeading;
    builder.Writeln($" | TOC Sub Header {i} in {SecondaryFont} expected in {TOCFont}");

    builder.ParagraphFormat.ClearFormatting();
    builder.Font.ClearFormatting();
    builder.Writeln("Single line text");
    builder.InsertBreak(BreakType.PageBreak);
}

doc.UpdateFields();
            
doc.Save(@"C:\Temp\out.pdf");
doc.Save(@"C:\Temp\out.docx");
private static void ApplyStyles(DocumentBuilder builder, StyleIdentifier styleIdentifyer)
{
    var style = builder.Document.Styles[styleIdentifyer];
    style.Font.Name = TOCFont;
    style.Font.Size = 14d;
}

out.docx (8.3 KB)
out.pdf (55.6 KB)