Reputation: 1890
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
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:
However, if you:
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