Joe W
Joe W

Reputation: 1890

Why does Microsoft Word fire the DocumentOpen event for an already opened document

I have a Microsoft Word Add-in using VSTO and interop. My code is having issues if the DocumentOpen event is fired for an already open document. I've been able to consistently replicate this by opening a document doc1, opening another document doc2, and then trying to open doc1 again.

Doc1 is already obviously open, but the DocumentOpen event is fired again for doc1. Is this an intended design and if so, is there a simple way I can tell if the event is being fired for an already opened document?

private void ThisAddIn_Startup(object sender, System.EventArgs a)
{
  try
  {
    this.Application.DocumentOpen += 
      new MSWord.ApplicationEvents4_DocumentOpenEventHandler(Application_DocumentOpen);

  }
}

private void Application_DocumentOpen(MSWord.Document document)
{
  HandleOpenedDocument(document);
}

Upvotes: 3

Views: 5106

Answers (1)

Lasse Christiansen
Lasse Christiansen

Reputation: 10325

As far as I can tell by reading the documentation and doing some empirical studies, it looks like the DocumentOpen event is fired if:

  • you open doc1, then doc2, and then doc1 again

However, if you:

  • open doc1 and then doc1 again, the event is only fired the first time doc1 is opened.

So the rule might be something like: "if you open the same document over and over the event is only fired once, however, when you open a different document than the one that was recently opened, the event is fired for the newly opened document no matter if that document is already open in a running instance of Word."

I have been looking for more details on this in the documentation, but without any luck. However, if you really want to know what is going on, I suggest you ask your question at the MSDN forum where some of the MVPs might be able to help.

Then you ask:

is there a simple way I can tell if the event is being fired for an already opened document?

And yes, I think :)

Basically you can keep a set of open documents in your application and use the DocumentOpen and DocumentBeforeClose events to maintain the set. Knowing which documents are currently open it gets simple to determine if a document is already open when the event is fired - simply do a lookup in the set and you are good to go.

To illustrate, I have constructed a sample implementation of how this can be done using Word Interop - as far as I know, this should map almost 1 to 1 to VSTO. I have provided a couple of comments in the code, so it should be fairly easy to follow what is going on.

using Microsoft.Office.Interop.Word;
using Application = Microsoft.Office.Interop.Word.Application;

namespace WordDocStats
{
    internal class Program
    {
        private static readonly HashSet<Document> OpenDocuments = new HashSet<Document>();

        private static void Main()
        {
            var wordApplication = new Application() { Visible = true };

            // Listen for documents open
            wordApplication.DocumentOpen += WordApplicationDocumentOpen;

            // Listen for documents close
            wordApplication.DocumentBeforeClose += WordApplicationDocumentBeforeClose;

            Console.ReadLine();
            wordApplication.Quit();
        }

        static void WordApplicationDocumentBeforeClose(Document doc, ref bool cancel)
        {
            OpenDocuments.Remove(doc);
            Console.WriteLine(doc.Name + " closed!");
        }

        static void WordApplicationDocumentOpen(Document doc)
        {
            // If this returns true, the doc is not in the set of open documents, hence the doc is not already open
            if(OpenDocuments.Add(doc))
            {
                OpenDocuments.Add(doc);
                Console.WriteLine(doc.Name + " opened...");
            }
            // Otherwise, the doc is already in the set of open documents, hence we know the document is already open
            else
            {
                Console.WriteLine(doc.Name + " is already open!");
            }
        }
    }
}

Hope this helps! :)

Upvotes: 5

Related Questions