Ty Anderson

Word add-in development in Visual Studio: Application and base objects

Microsoft Word has tons of objects and is a bit underrated when it comes to building Office solutions. My opinion is this is due to the attention Outlook and Excel receive… and rightfully so. But Word is just as powerful as its siblings, if not more so.

In this article (the first in a series of Word development topics), I’ll cover Microsoft Word application and base objects. And, as is our tradition, I’ll provide relevant code samples for Word 2013 – 2000 you can copy and paste into your solutions. You have my permission (otherwise it would be stealing).

Word’s base objects

Microsoft Word base objects

  • Application – The Word application itself. The mother ship… without her we don’t have Word.
  • Document – A Word document… I know, almost needs no explanation.
  • Selection – The currently selected content in a document. This one is tricky because it can also be the insertion point.

As you can see in the diagram to the right (which I lifted straight off MSDN), everything else resides beneath these three guys.

Today, we will focus on these three and save all the other hangers-on for another day.

Accessing base objects with code

Learning to work with the base objects is the 20% that empowers you to do 80% of what’s needed to make things happen. I’m going to do this in alphabetical order today. Let’s get to the code samples.

The Application object

This sample shows how to change some Word application-level settings. Add-in Express provides the WordApp within our AddinModule for easy access to the Word application.

Public Sub SetMyWordApplicationPreferences() 
    WordApp.DisplayRecentFiles = True
    WordApp.RecentFiles.Maximum = 1
    WordApp.DisplayScreenTips = False
    WordApp.DisplayScrollBars = True
    WordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone
    WordApp.WindowState = Word.WdWindowState.wdWindowStateMaximize
    WordApp.ActiveWindow.View.ReadingLayout = False
End Sub

This routine clears Word just a little bit of distractions and prepares the serious writer for some serious writing. It reduces the recent files list to a single file, turns off screen tips and alerts. It also maximizes the Word window and turns off the reading layout. Ahh… now I’m ready to… ready to do some serious writing.

The Document object

Microsoft Word exists for users to author documents. It stands to reason, therefore, that the majority of the samples today are document focused.

Enumerate documents

Word has a documents collection that provides access to all open documents. Using the documents collection, you can do what you want with them (assuming the API supports it that is).

Public Sub EnumerateDocumentsAndCloseWithoutSaving()
    Dim docs As Word.Documents = Nothing
    docs = WordApp.Documents
 
    For i As Integer = docs.Count To 1 Step -1
        docs(i).Close(Word.WdSaveOptions.wdDoNotSaveChanges)
    Next
 
    Marshal.ReleaseComObject(docs)
 
End Sub

Here, I wanted to close all the documents and not save them.

Create a new Word document

To create a new word document, you need to add a new document to the Documents collection.

Public Sub CreateNewDocument(docName As String)
    Dim newDoc As Word.Document = Nothing
    newDoc = WordApp.Documents.Add()
    newDoc.SaveAs2(docName)
 
    Marshal.ReleaseComObject(newDoc)
End Sub

In the above sample, I go the extra trouble of saving the document using the passed docName.

Create a new document from a template

To create new document based on a template, you do the same thing as we just did except you provide the path to the document template.

Public Sub CreateNewDocumentFromTemplate(templatePath As String)
    Dim newDoc As Word.Document = Nothing
    newDoc = WordApp.Documents.Add(templatePath)
 
    Marshal.ReleaseComObject(newDoc)
End Sub

It’s easy but your users will believe it to be magic. And it is.

Open an existing document

To open a document you can call the Open method of the Documents collection and specify the path to the file you want to open.

Public Sub OpenDocument(docPath As String)
    Dim doc As Word.Document = Nothing
    doc = WordApp.Documents.Open(docPath)
     'or
    'doc = WordApp.Documents.Add(docPath)
 
    Marshal.ReleaseComObject(doc)
End Sub

You can also just add it to the documents collection.

The Selection object

There is always a selection in Word. Either there is selected content or there is an insertion point (meaning, no content is selected and we are ready to add content. This object provides quick access to the content that is the current focus of the user’s attention.

Private Sub ChangeSelectionFontAndCountWords()
    Dim selection As Word.Selection = Nothing
 
    selection = WordApp.Selection
    selection.Font.Name = "Arial"
    selection.Font.Size = 16
    MessageBox.Show( _
        selection.Words.Count, "Selection Word Count", _
        MessageBoxButtons.OK, MessageBoxIcon.Information)
 
    Marshal.ReleaseComObject(selection)
End Sub

This method changes the font and size of the text in the Selection object. It then displays the Word count in a message box.

Useful events

Working with the base objects and bending them to your will is one thing. Responding to events when they try to sneak away is another. When you combine the two, well, you are close to building some useful solutions.

NewDocument event

Don’t let the name of this event fool you. This event is a Word application event that executes when Microsoft Word creates a new document. It is the place for any setup logic you want to execute against a new document.

Private Sub adxWordEvents_NewDocument(sender As Object, hostObj As Object) _
    Handles adxWordEvents.NewDocument
 
    Dim doc As Word.Document = Nothing
    doc = TryCast(hostObj, Word.Document)
    doc.BuiltInDocumentProperties("Author") = "Me"
End Sub

This hostObj is the newly created document. By casting to a Document, I then access the built-in properties and set the Author property.

DocumentOpen event

I really like to see the Navigation Pane when I work with documents. If it is not visible, I immediately click the View tab and enable it. But that’s silly. Why not have some code to do it for me?

Private Sub adxWordEvents_DocumentOpen(sender As Object, hostObj As Object) _
    Handles adxWordEvents.DocumentOpen
 
    WordApp.ActiveWindow.DocumentMap = True
End Sub

This DocumentOpen event executes anytime Word opens a document. Thus, it is the event to respond to and automatically display the navigation pane (aka the DocumentMap)

DocumentBeforePrint event

Does anyone besides accountants and lawyers print documents these days? Heck, anytime I think about printing a document I receive, I feel guilty because lots of people have email signatures that include the phrase “Think before you print.” The DocumentBeforePrint is a good event for doing some last minute checking with the user as it executes right before sending the document to the printer.

Private Sub adxWordEvents_DocumentBeforePrint(sender As Object, _
    e As ADXHostBeforeActionEventArgs) _
    Handles adxWordEvents.DocumentBeforePrint
 
    'At least think about being green before printing
    If MessageBox.Show( _
        "Do you really want to print the document and contribute to the killing of a few _
         trees?", "Think Before You Print", MessageBoxButtons.YesNo) = DialogResult.No Then
        e.Cancel = True
    End If
End Sub

If the user clicks No, the method sets Cancel=True to cancel the print job. Otherwise, the print continues and a few trees are killed. Oh well, they’ll grow back I suppose. Another good use of this event is to automatically route print jobs to different printers depending on the logic of your choosing.

DocumentBeforeClose event

This event executes right before Word closes the document. It’s a good event for cleaning up the document.

Private Sub adxWordEvents_DocumentBeforeClose(sender As Object, _
    e As ADXHostBeforeActionEventArgs) Handles adxWordEvents.DocumentBeforeClose
 
    Dim doc As Word.Document = Nothing
    doc = TryCast(e.HostObject, Word.Document)
 
    If doc.Comments.Count > 1 Then
        If MessageBox.Show( _
            "This documents contains comments, do you really want to close it?", _
            "Respond to Comments?", MessageBoxButtons.YesNo) = DialogResult.No Then
            e.Cancel = True
        End If
    End If
End Sub

In this example, I reference the HostObject of the passed ADXHostBeforeActionEventArgs object. I do it because HostObject is the document that’s closing. After I recast it as a Document, I check for comments and alert the user to them and give them a chance to reconsider.

Application.Quit event

The Quit event is the place for doing some clean-up.

Private Sub adxWordEvents_Quit(sender As Object, e As EventArgs) _
    Handles adxWordEvents.Quit
 
    'Clear the recent docs list
    While WordApp.RecentFiles.Count > 0
        WordApp.RecentFiles.Item(1).Delete()
    End While
 End Sub

Continuing my theme of removing distractions, this sample removes all recent files. The NSA can’t track this! Notice that I do not up the count in the loop and always access WordApp.RecentFiles.Item(1). The reason is that each Delete action lowers the count in the RecentFiles collection. Thus, by calling Item(1) each time, I can safely delete each item.

***

Okay, there you go… that’s Word Application and Base Objects 101. This is enough information and samples to get you started. But, it’s also enough to make you thirst for more. You will not thirst for long as we have a whole series of Beginning Word Development topics set for this month.

Available downloads:

This sample Outlook add-in was developed using Add-in Express for Office and .net:

VB.NET sample Word add-in

You may also be interested in:

Word add-in development in Visual Studio for beginners:

4 Comments

  • bob says:

    Thanks very much Ty and yes Word is just a capable and more so in my book as i think eventually, we will be able to use Word documents as web front ends as well, but currenly i am managing my software documentation for thousands of modules using Word and can instantly access code 10 levels deep using a customized Word VBA system and with Open XML the sky is the limit! So thanks Ty as i’m really looking forward to any examples you can provide as i’m only seeing VBA solutions as of late and actually i’m currently searching for a way to publish my VBA code to Sharepoint so others can use it!

  • Ty Anderson says:

    Thanks Bob…I think you are onto something regarding Word docs as web pages. I was thinking the other day that, to my children, the concept of a “document” will most likely be as foreign as cassette tape. What you are doing with Word sounds very interesting. We’ll have more code samples soon.

  • Amitabh says:

    These examples are very useful. Is the code available in C#?

  • Dmitry Kostochko (Add-in Express Team) says:

    Hello Amitabh,

    We don’t have a C# version of this sample. Could you please let me know exactly what portion of the VB.NET code you cannot translate into C#? I will try to help with this.

Post a comment

Have any questions? Ask us right now!