Deleting orphaned list templates in a document.
From time to time, we come across support cases where customers need to clean up the list templates in a document. While working with a document, there are situations when you will want to know how many list tempates are currently in use and when you check that value, it is a much larger number than what you expect. Before discussing how to get the correct number, I want to mention that I am assuming you have at least some type of understanding about list templates and the scenarios that will put a document into a state where it contains un-used list templates. There are a few different articles on the internet that discuss list numbering and list templates. A regular search for these terms should get you some of the background information related to this particular information.
Note: This particular blog post is related to the Open Xml (.docx) file format and will not address the problem with binary (.doc) files.
Having said that, we can now start discussing what needs to happen if you want to remove these un-used or orphaned list templates. This is a manual process and I am also making further assumptions that you have some understanding of opening a Word document and modifying the underlying xml files. I will use the following document for this example, which at first contains two list templates.
To achieve an orphaned list template, I will delete everything in List #2 so only the first list remains and then save the document. It now looks like the following:
If I query the object model for the number of list templates (ActiveDocument.ListTemplates.Count), I will get a value of 2 instead of 1. To get the actual count of list templates currently in use, we first need to rename the file to ".zip" and have a look at its contents. After zipping my document, I can navigate to the "word" folder and this is what I find:
The two files of importance are "document.xml" and "numbering.xml". We will not make any changes to "document.xml"; we just need to look through it to find out what list templates are currently in use. As you can see in the following screenshot, this document has only one "numId" in use with a value of 1. It does appear three times, one for each list item but I only need to know if the style is used at least once. You also need to keep in mind that if you are using list numbering in other parts of the document (like headers, footers, etc...), you will need to repeat this check for each of those xml files. The process will be the same in those files, so you still are just looking for "numId" values.
Now that I know what "numId" values are used in the document, the next thing I will do is look through the file "numbering.xml" so I can see what orphaned list templates are still listed. Here is what mine looks like:
I collapsed the "abstractNum" tags to make it easier to show the relationship between the "numId" and "abstractNumId". As you can see in the screenshot, the document is still listing both list templates in the document. Since my search through "document.xml" only showed the numId = 1, any other numId can be deleted along with its related abstractNum tag.
After deleting the "num" tag with a numId = 2 and the "abstractNum" tag with an abstractNumId = 0, I can save the "numbering.xml" file and place it back into my Word document. You should now have a document that has the correct number of list templates.
One thing to keep in mind is that, while this method does work it could be very time consuming on larger documents. There might be other sites/blogs that have information about using VBA or some other approach to automate this type of clean up in a Word document. There are even some approaches to manually modifying the document in Word to achieve the same results. The goal of this post was to try and provide another option for users to choose from regarding this particular issue.
Lastly, I spent the weekend writing an automated version of this blog using the Open Xml SDK to see if that works and it does, so it would be possible to get this working on a larger scale programmatically.