How to change tab leader of Table Of Contents in Word document?
Syncfusion® Essential® DocIO is a .NET Word library used to create, read, and edit Word documents programmatically without Microsoft Word or Interop dependencies. Using this library, you can add and modify the table of contents in a Word document using C# and VB.NET.
We can achieve this requirement by following these steps:
- Create a Word document.
- Append a table of contents in the Word document.
- Update the table of contents in the Word document.
- Find the table of contents in the Word document by iterating through the document elements.
- Insert a bookmark from the start to the end of the table of contents.
- Access the table of contents using the BookmarkNavigator.
- Iterate through the bookmark content and change the tab leader for TOC paragraphs.
- Save the Word document.
Steps to change the Tab leader for TOC paragraphs:
- Create a new C# console application project.
- Install the Syncfusion.DocIO.WinForms NuGet package as a reference to your .NET Framework applications from NuGet.org.
- Include the following namespace:
C#
using Syncfusion.DocIO.DLS;
VB
Imports Syncfusion.DocIO.DLS
- The following code example shows how to change the tab leader for TOC paragraphs in the Word document.
C#
// Create a new Word document.
WordDocument document = new WordDocument();
// Add a section into the Word document.
IWSection section = document.AddSection();
string paraText = "AdventureWorks Cycles, the fictitious company on which the AdventureWorks sample databases are based, is a large, multinational manufacturing company.";
// Add a paragraph into the created section.
IWParagraph paragraph = section.AddParagraph();
// Append the TOC field with LowerHeadingLevel and UpperHeadingLevel to determine the TOC entries.
paragraph.AppendTOC(1, 3);
// Add a section into the Word document.
section = document.AddSection();
// Add a paragraph into the created section.
paragraph = section.AddParagraph();
// Add text for the headings.
paragraph.AppendText("First Chapter");
// Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading1);
// Add text into the paragraph.
section.AddParagraph().AppendText(paraText);
// Add a section into the Word document.
section = document.AddSection();
// Add a paragraph into the created section.
paragraph = section.AddParagraph();
// Add text for the headings.
paragraph.AppendText("Second Chapter");
// Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading2);
// Add text into the paragraph.
section.AddParagraph().AppendText(paraText);
// Add a section into the Word document.
section = document.AddSection();
// Add a paragraph into the created section.
paragraph = section.AddParagraph();
// Add text into the headings.
paragraph.AppendText("Third Chapter");
// Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading3);
// Add text into the paragraph.
section.AddParagraph().AppendText(paraText);
// Update the table of contents.
document.UpdateTableOfContents();
// Find the TOC from the Word document.
TableOfContent toc = FindTableOfContent(document);// Change tab leader for the table of contents in the Word document.
if (toc != null)
ChangeTabLeaderForTableOfContents(toc, TabLeader.Hyphenated);// Save and close the Word document.
document.Save("Result.docx");
document.Close();
VB
'Create a new Word document.
Dim document As WordDocument = New WordDocument()
'Add a section into the Word document.
Dim section As IWSection = document.AddSection()
Dim paraText As String = "AdventureWorks Cycles, the fictitious company on which the AdventureWorks sample databases are based, is a large, multinational manufacturing company."
'Add a paragraph into the created section.
Dim paragraph As IWParagraph = section.AddParagraph()
'Append the TOC field with LowerHeadingLevel and UpperHeadingLevel to determine the TOC entries.
paragraph.AppendTOC(1, 3)
'Add a section into the Word document.
section = document.AddSection()
'Add a paragraph into the created section.
paragraph = section.AddParagraph()
'Add text for the headings.
paragraph.AppendText("First Chapter")
'Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading1)
'Add text into the paragraph.
section.AddParagraph().AppendText(paraText)
'Add a section into the Word document.
section = document.AddSection()
'Add a paragraph into the created section.
paragraph = section.AddParagraph()
'Add text for the headings.
paragraph.AppendText("Second Chapter")
'Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading2)
'Add text into the paragraph.
section.AddParagraph().AppendText(paraText)
'Add a section into the Word document.
section = document.AddSection()
'Add a paragraph into the created section.
paragraph = section.AddParagraph()
'Add text into the headings.
paragraph.AppendText("Third Chapter")
'Set a built-in heading style.
paragraph.ApplyStyle(BuiltinStyle.Heading3)
'Add text into the paragraph.
section.AddParagraph().AppendText(paraText)
'Update the table of contents.
document.UpdateTableOfContents()
'Find the TOC from the Word document.
Dim toc As TableOfContent = Program.FindTableOfContent(document)
'Change tab leader for the table of contents in the Word document.
If toc IsNot Nothing Then ChangeTabLeaderForTableOfContents(toc, TabLeader.Hyphenated)
'Save and close the Word document.
document.Save("Result.docx")
document.Close()
- The following code example provides supporting methods for the above code.
5.1 Find the table of contents from the Word document by iterating through the document elements.
C#
/// <summary> /// Finds the table of contents from a Word document by iterating its elements. /// </summary> private static TableOfContent FindTableOfContent(WordDocument document) { foreach (var item in document.Visit()) { if (item is TableOfContent) return item as TableOfContent; } return null; }
VB
'''<summary> ''' Finds the table of contents from a Word document by iterating its elements. ''' </summary> Private Shared Function FindTableOfContent(ByVal document As WordDocument) As TableOfContent For Each item In document.Visit() If TypeOf item Is TableOfContent Then Return TryCast(item, TableOfContent) Next Return Nothing End Function
5.2 Insert a bookmark that covers the TOC of the Word document. Then, access the bookmark content using the BookmarkNavigator and change the tab leader for the TOC paragraphs.
C#
/// <summary>
/// Change tab leader for the table of contents in the Word document.
/// </summary>
private static void ChangeTabLeaderForTableOfContents(TableOfContent toc, TabLeader tabLeader)
{
// Insert the bookmark start before the TOC instance.
BookmarkStart bkmkStart = new BookmarkStart(toc.Document, "tableOfContent");
toc.OwnerParagraph.Items.Insert(toc.OwnerParagraph.Items.IndexOf(toc), bkmkStart);Entity lastItem = FindLastTOCItem(toc);
// Insert the bookmark end next to the TOC last item.
BookmarkEnd bkmkEnd = new BookmarkEnd(toc.Document, "tableOfContent");
WParagraph paragraph = lastItem.Owner as WParagraph;
paragraph.Items.Insert(paragraph.Items.IndexOf(lastItem) + 1, bkmkEnd);// Create the bookmark navigator instance to access the bookmark.
BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(toc.Document);
// Move the virtual cursor to the location before the end of the bookmark "tableOfContent."
bookmarkNavigator.MoveToBookmark("tableOfContent");
// Get the bookmark content.
TextBodyPart part = bookmarkNavigator.GetBookmarkContent();// Iterate through the items from the bookmark to change the spacing in the table of contents.
for (int i = 0; i < part.BodyItems.Count; i++)
{
paragraph = part.BodyItems[i] as WParagraph;
// Set the tab leader as none.
if (paragraph.ParagraphFormat.Tabs.Count != 0)
paragraph.ParagraphFormat.Tabs[0].TabLeader = tabLeader;
}// Remove the bookmark which we added to get the paragraphs in the table of contents.
Bookmark bookmark = toc.Document.Bookmarks.FindByName("tableOfContent");
toc.Document.Bookmarks.Remove(bookmark);}
/// <summary>
/// Finds the last TOC item.
/// </summary>
private static Entity FindLastTOCItem(TableOfContent toc)
{
int tocIndex = toc.OwnerParagraph.Items.IndexOf(toc);
// TOC may contain nested fields and each field has its owner field end mark.
// To identify the TOC Field end mark (WFieldMark instance), use the stack.
Stack<Entity> fieldStack = new Stack<Entity>();
fieldStack.Push(toc);// Find whether the TOC end item exists in the same paragraph.
for (int i = tocIndex + 1; i < toc.OwnerParagraph.Items.Count; i++)
{
Entity item = toc.OwnerParagraph.Items[i];if (item is WField)
fieldStack.Push(item);
else if (item is WFieldMark && (item as WFieldMark).Type == FieldMarkType.FieldEnd)
{
if (fieldStack.Count == 1)
{
fieldStack.Clear();
return item;
}
else
fieldStack.Pop();
}}
return FindLastItemInTextBody(toc, fieldStack);
}
/// <summary>
/// Finds the last TOC item from consecutive text body items.
/// </summary>
private static Entity FindLastItemInTextBody(TableOfContent toc, Stack<Entity> fieldStack)
{
WTextBody tBody = toc.OwnerParagraph.OwnerTextBody;for (int i = tBody.ChildEntities.IndexOf(toc.OwnerParagraph) + 1; i < tBody.ChildEntities.Count; i++)
{
WParagraph paragraph = tBody.ChildEntities[i] as WParagraph;foreach (Entity item in paragraph.Items)
{
if (item is WField)
fieldStack.Push(item);
else if (item is WFieldMark && (item as WFieldMark).Type == FieldMarkType.FieldEnd)
{
if (fieldStack.Count == 1)
{
fieldStack.Clear();
return item;
}
else
fieldStack.Pop();
}
}
}
return null;
}
VB
''' <summary>
''' Change tab leader for the table of contents in the Word document.
''' </summary>
Private Shared Sub ChangeTabLeaderForTableOfContents(ByVal toc As TableOfContent, ByVal tabLeader As TabLeader)
'Insert the bookmark start before the TOC instance.
Dim bkmkStart As BookmarkStart = New BookmarkStart(toc.Document, "tableOfContent")
toc.OwnerParagraph.Items.Insert(toc.OwnerParagraph.Items.IndexOf(toc), bkmkStart)
Dim lastItem As Entity = SurroundingClass.FindLastTOCItem(toc)'Insert the bookmark end next to the TOC last item.
Dim bkmkEnd As BookmarkEnd = New BookmarkEnd(toc.Document, "tableOfContent")
Dim paragraph As WParagraph = TryCast(lastItem.Owner, WParagraph)
paragraph.Items.Insert(paragraph.Items.IndexOf(lastItem) + 1, bkmkEnd)'Create the bookmark navigator instance to access the bookmark.
Dim bookmarkNavigator As BookmarksNavigator = New BookmarksNavigator(toc.Document)
'Move the virtual cursor to the location before the end of the bookmark "tableOfContent."
bookmarkNavigator.MoveToBookmark("tableOfContent")
'Get the bookmark content.
Dim part As TextBodyPart = bookmarkNavigator.GetBookmarkContent()'Iterate through the items from the bookmark to change the spacing in the table of contents.
For i As Integer = 0 To part.BodyItems.Count - 1
paragraph = TryCast(part.BodyItems(i), WParagraph)
'Set the tab leader as none.
If paragraph.ParagraphFormat.Tabs.Count <> 0 Then paragraph.ParagraphFormat.Tabs(0).TabLeader = tabLeader
Next'Remove the bookmark which we added to get the paragraphs in the table of contents.
Dim bookmark As Bookmark = toc.Document.Bookmarks.FindByName("tableOfContent")
toc.Document.Bookmarks.Remove(bookmark)
End Sub''' <summary>
''' Finds the last TOC item.
''' </summary>
Private Shared Function FindLastTOCItem(ByVal toc As TableOfContent) As Entity
Dim tocIndex As Integer = toc.OwnerParagraph.Items.IndexOf(toc)
'TOC may contain nested fields and each field has its owner field end mark.
'To identify the TOC Field end mark (WFieldMark instance), use the stack.
Dim fieldStack As Stack(Of Entity) = New Stack(Of Entity)()
fieldStack.Push(toc)'Find whether the TOC end item exists in the same paragraph.
For i As Integer = tocIndex + 1 To toc.OwnerParagraph.Items.Count - 1
Dim item As Entity = toc.OwnerParagraph.Items(i)If TypeOf item Is WField Then
fieldStack.Push(item)
ElseIf TypeOf item Is WFieldMark AndAlso TryCast(item, WFieldMark).Type Is FieldMarkType.FieldEnd ThenIf fieldStack.Count = 1 Then
fieldStack.Clear()
Return item
Else
fieldStack.Pop()
End If
End If
NextReturn SurroundingClass.FindLastItemInTextBody(toc, fieldStack)
End Function''' <summary>
''' Finds the last TOC item from consecutive text body items.
''' </summary>
Private Shared Function FindLastItemInTextBody(ByVal toc As TableOfContent, ByVal fieldStack As Stack(Of Entity)) As Entity
Dim tBody As WTextBody = toc.OwnerParagraph.OwnerTextBodyFor i As Integer = tBody.ChildEntities.IndexOf(toc.OwnerParagraph) + 1 To tBody.ChildEntities.Count - 1
Dim paragraph As WParagraph = TryCast(tBody.ChildEntities(i), WParagraph)For Each item As Entity In paragraph.Items
If TypeOf item Is WField Then
fieldStack.Push(item)
ElseIf TypeOf item Is WFieldMark AndAlso TryCast(item, WFieldMark).Type Is FieldMarkType.FieldEnd ThenIf fieldStack.Count = 1 Then
fieldStack.Clear()
Return item
Else
fieldStack.Pop()
End If
End If
Next
NextReturn Nothing
End Function
- The following code example provides a helper class to find the table of contents in the Word document.
C#
/// <summary> /// DocIO extension class. /// </summary> public static class DocIOExtensions { public static IEnumerable<IEntity> Visit(this ICompositeEntity entity) { var entities = new Stack<IEntity>(new IEntity[] { entity }); while (entities.Count > 0) { var e = entities.Pop(); yield return e; if (e is ICompositeEntity) { foreach (IEntity childEntity in ((ICompositeEntity)e).ChildEntities) { entities.Push(childEntity); } } } } }
VB
''' <summary> ''' DocIO extension class. ''' </summary> Public Module DocIOExtensions <Extension()> Public Iterator Function Visit(ByVal entity As ICompositeEntity) As IEnumerable(Of IEntity) Dim entities = New Stack(Of IEntity)(New IEntity() {entity}) While entities.Count > 0 Dim e = entities.Pop() Yield e If TypeOf e Is ICompositeEntity Then For Each childEntity As IEntity In CType(e, ICompositeEntity).ChildEntities entities.Push(childEntity) Next End If End While End Function End Module
A complete working example of how to change the tab leader for a table of contents in a Word document using C# can be downloaded from the change tab leader of TOC.zip.
By executing the program, you can get a Word document as follows.
You can refer to our documentation to know more about working with the table of contents in a Word document using the Syncfusion® .NET Word library (Essential® DocIO).
Take a moment to peruse the documentation. You can find basic Word document processing options along with features like mail merge, merge and split documents, find and replace text in the Word document, protect the Word documents, and most importantly PDF and image conversions with code examples.
Explore more about a rich set of Syncfusion® Word Framework features.