Word is quite flexible when it comes to Table of
Contents (TOC) as it allows you to base its generation to either styles or
table entry fields (Insert à Field à TC).
The first is the option that is most commonly used, as
documents tend to be logically spit into distinct parts which have their own
heading. Applying a specific style to those headings means that you can use all
instances of this style to generate the TOC. This method stops working when the
way the document is structured is not consistent with the way you want to TOC
to be generated or when you want the TOC to include parts of the document that
do not have a specific style applied to them.
This is where table entry fields come in. They can be
placed anywhere in the document and they can contain any text that you like.
They can even be associated with an outline level (i.e. which level in the
hierarchy they belong to). In other words, it is like planting hidden headings
within the document.
However, there are two main issues with table entry
fields
- When
“Show all formatting marks” are turned on the user can see them, which can
be annoying to a power user that uses this option but is not interested in
the table entry fields, and can also edit them either by mistake or on
purpose. One way or the other, a lot of responsibility is placed on the
hands of the user for keeping the table of entry fields intact.
- They
are inline with text. If you place a table entry field between two words,
selecting the two words and deleting them will also delete the table entry
field. Clearly this can be an issue as it restricts the users’ ability to
edit the document freely.
If you are in a situation where basing the TOC on
styles or table entry fields is not an option, your only true alternative is
the generating your own. By keeping track of the parts of the document that are
of interest (e.g. using Smart Documents and XML tags to annotate the content of
the document) you can generate a TOC of contents that looks and functions the
same as well the TOC generated by Word, but this time you are not restricted to
using styles or table entry fields.
Manually creating a TOC requires being able to do or
having access to the following
- Titles
that will be the entries of the TOC
- Creating
hyperlinks so that users can CTRL+CLICK on a TOC entry and be taken to the
part of the document the entry corresponds to
- The
page number that a part of the document starts at
- Being
able to align the page numbers differently than the titles and have some
sort of spacing between them (e.g. white space, dots, etc.)
Titles that will be entries of the
TOC
This one depends on the source of information that
your TOC will be based upon, but should be quite easy. In the case of using
Smart Documents and XML tags, you can have an XML attribute in each XML node
that needs to be part of the TOC that has the value that will appear in the
TOC. When the TOC is being generated, XPath can be used to retrieve all of the
required attributes very efficiently.
Creating hyperlinks so that users
can CTRL+CLICK on a TOC entry and be taken to the part of the document the
entry corresponds to
This is not as straight forward as it sounds; it might
not be technically very challenging, but it is not straight forward. First of
all you need a bookmark to base the hyperlink on. Bookmarks can easily be added
to a document using the following line of code
Globals.ThisDocument.Bookmarks.Add("BookmarkName", ref
range);
However, bookmarks are visible within the document and
since power users might also use them, the situation is not much different to
using table entry fields. By prefixing the name of the bookmark with “_” the
bookmark is added as “hidden”, meaning that it won’t be visible within the
document and unless the user explicitly wants hidden bookmarks to be displayed
they won’t even appear in the “Bookmarks” window (Insert à Bookmark).
Having the bookmark is half the battle; the rest is
creating a hyperlink based on the bookmark. First you add the hyperlink to the
document using the following code
object bookmarkRange = Globals.ThisDocument.Range(ref start, ref end);
object bookmarkSubAddress =
SubsectionManager.GetBookmarkName("_BookmarkName");
object bookmarkScreenTip = "Mouse over text";
Globals.ThisDocument.Hyperlinks.Add(bookmarkRange,
ref missing,
ref bookmarkSubAddress, ref
bookmarkScreenTip, ref missing, ref missing);
Then you need to style the TOC entry accordingly. You
will probably have a style that you would like to apply to the range of the
bookmark, but it is not as easy as that. Adding a hyperlink to the document
will automatically apply the built-in “Hyperlink” style to the specified range.
Applying your own style after adding the hyperlink will not override the
hyperlink settings for font and its properties (i.e. blue colour, underline,
etc.). The way around this is to create a style that is based on the built-in
“Hyperlink” style but has the font properties you want the TOC entry to have.
If it is still necessary you can apply your own style on top of the custom
“Hyperlink” based style without issues, applying more formatting to the TOC
entry.
object styleName = "Style
TOC1 Hyperlink";
((Range)bookmarkRange).set_Style(ref
styleName);
styleName = "Style TOC1";
((Range)bookmarkRange).set_Style(ref
styleName);
The page number that a part of the
document starts at
This might not be immediately obvious, but it is
actually pretty simple. The object “Range” has a method called
“get_Information()” that can take a number of parameters, one of which being
the page number the specific range ends at. Since for the TOC entry the page
number that a range starts are is required, a new range that starts and ends at
the beginning of the original range can be used to get this information as
shown below
object start = ((Range)bookmarkRange).Start;
Word.Range range = Globals.ThisDocument.Range(ref
start, ref start);
range.get_Information(WdInformation.wdActiveEndAdjustedPageNumber);
When using page numbers that have been adjusted (e.g.
the count starts from 2, the count actually starts from page 4 of the document,
etc.) make sure you use WdInformation.wdActiveEndAdjustedPageNumber instead of WdInformation.wdActiveEndPageNumber.
Being able to align the page numbers
differently than the titles and have some sort of spacing between them (e.g.
white space, dots, etc.)
This part is probably the easiest one as it can
be achieved as part of the style that is applied to the TOC entry. Each
“paragraph” type style has a set of properties called “Tabs” which can be used
to set the alignment that the text on the right of a “tab” will have, it’s
position on the page and the spacing between the text on the right and the left
of a “tab”.