MS word - How to Read Table of contents programmatically
Reading Table of contents and populating treeview.
Reading Table of Contents
Problem Scenario
- Reading TOC programmatically. There are hardly any sites containing information related to reading TOC.
- How to populate Treeview with TOC (Table of contents).
Solution
Step 1: drop treeview and button in your form. Set treeview Name property to "tvwTOC" and button to
"button1". Set button's onClick handler to ".button_click".
Step 2: Add a reference to the Microsoft Word Object Library. To do this, follow these steps:
On the Project menu, click Add Reference.
On the COM tab, locate the Microsoft Word Object Library and click Select.
Step 3: Copy following code in your .cs file.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Word = Microsoft.Office.Interop.Word;
using System.IO;
using System.Collections.Generic;
namespace WordStructureProcessing
{
public partial class Form3 : Form
{
private Word.Application wordApp = null;
private Word.Document docSource = null;
Object oMissing = Type.Missing;
List
const int c_iNrTolerableDeleteErrors = 5; // used to prevent user getting stuck on a large number of error messages
private Object oReplaceAll;
public Form3()
{
InitializeComponent();
}
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
System.Windows.Forms.Application.Run(new Form3());
}
private void LoadTOC(OpenFileDialog openFile)
{
int paragraphCount = -1;
string strDelimiters = string.Empty;
char[] a_charDelimiter = null;
string strTOC = string.Empty;
string[] paragraphs = null;
wordApp = new Word.Application();
wordApp.Visible = true;
Object filename = openFile.FileName;
wordApp.Documents.Open(ref filename, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing);
docSource = wordApp.ActiveDocument;
Word.Range oRangeTOC = docSource.TablesOfContents[1].Range;
// Removing unwanted characters.
// Creating string array that contains all TOC heading.
strDelimiters = "\r";
a_charDelimiter = strDelimiters.ToCharArray();
strTOC = oRangeTOC.Text;
strTOC = strTOC.TrimEnd(a_charDelimiter);
paragraphs = strTOC.Split(a_charDelimiter);
// Create tree node along with hierarchy level.
// "TOC 1" - First level
// "TOC 2" - Second level
for (int i = 0; i < paragraphs.Length; i++)
{
TOCNode tNode = new TOCNode();
tNode.Text = GetHeaderText(paragraphs[i]);
string tocLevel = ((Word.Style)oRangeTOC.Paragraphs[i + 1].Range.get_Style()).NameLocal;
switch (tocLevel)
{
case "TOC 1":
tNode.HeadingStyle = 1;
break;
case "TOC 2":
tNode.HeadingStyle = 2;
break;
case "TOC 3":
tNode.HeadingStyle = 3;
break;
case "TOC 4":
tNode.HeadingStyle = 4;
break;
case "TOC 5":
tNode.HeadingStyle = 5;
break;
case "TOC 6":
tNode.HeadingStyle = 6;
break;
case "TOC 7":
tNode.HeadingStyle = 7;
break;
case "TOC 8":
tNode.HeadingStyle = 8;
break;
case "TOC 9":
tNode.HeadingStyle = 9;
break;
default:
break;
}
tocNodes.Add(tNode);
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Title = "Select Source File";
openFile.Filter = "Word Document (*.doc)|*.doc";
openFile.FilterIndex = 2;
openFile.RestoreDirectory = true;
if (openFile.ShowDialog() == DialogResult.OK)
{
LoadTOC(openFile);
}
PopulateTree(tocNodes);
}
private void PopulateTree(List
{
Int16 previousNodeLevel = -1;
TreeNodeCollection nodeCollection = null;
TreeNode tNode = null;
tvwTOC.Nodes.Clear();
tvwTOC.BeginUpdate();
for (int i = 0; i < tocNodes.Count; i++)
{
if (tvwTOC.Nodes.Count == 0 || tocNodes[i].HeadingStyle == 1)
{
nodeCollection = tvwTOC.Nodes;
}
else
{
// Currently it is supporting up to 9 level.
// Starting from the root node, its keep checking the
// HeadingStyle that is equivalent to node level. once correct node is found
// it passes node collection in which current node to be added.
nodeCollection = tvwTOC.Nodes;
for (int j = 1; j <= 9; j++)
{
if (tocNodes[i].HeadingStyle == j)
{
break;
}
nodeCollection = nodeCollection[nodeCollection.Count - 1].Nodes;
}
}
previousNodeLevel = tocNodes[i].HeadingStyle;
tNode = CreateTreeNode(tocNodes[i],nodeCollection);
}
tvwTOC.EndUpdate();
}
private TreeNode CreateTreeNode(TOCNode tocNode,TreeNodeCollection nodeCollection)
{
TreeNode tNode = nodeCollection.Add(tocNode.Text);
return (tNode);
}
private string GetHeaderText(string tocText)
{
string strDelimiters = "\r";
char[] a_charDelimiter = strDelimiters.ToCharArray();
tocText = tocText.TrimEnd(a_charDelimiter);
return (tocText.Replace("\t", " - "));
}
}
}
Add class file and paste following code
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace WordTOCProcessing
{
public class TOCNode: TreeNode
{
private Int16 _headingStyle = -1;
private string _nodeText = string.Empty;
private TOCNode _parentNode = null;
public string NodeText
{
get
{
return (_nodeText);
}
set
{
_nodeText = value;
}
}
public TOCNode ParentNode
{
get { return _parentNode; }
set { _parentNode = value; }
}
public Int16 HeadingStyle
{
get { return _headingStyle; }
set { _headingStyle = value; }
}
}
}
creating object for list is creating a issue since it is not a collection.
tocNodes.Add(tNode);
kindly check and revert back