Excel WorkbookActivate event not fired

Add-in Express™ Support Service
That's what is more important than anything else

Excel WorkbookActivate event not fired
 
Maxim T


Guest


Hi Team,


We've found an unexpected behavior regarding AddInExpress event model. Here are what we have:
- Mainly we using https://www.add-in-express.com/docs/net-custom-task-panes.php approach in conjunction with https://www.add-in-express.com/creating-addins-blog/2012/02/27/how-an-office-add-in-intercepts-clicking-a-built-in-control/#commandbar
- So we using ADXKeyboardShortcut for "ctrl+S" shortcut. Inside ADXKeyboardShortcut.Action event handler we doing:
ADXAddinModule.SendMessage(Const.SEND_SAVE, IntPtr.Zero, IntPtr.Zero).
- Exists an event handler for ADXAddinModule.OnSendMessage event. It catches Const.SEND_SAVE message and doing next:
var excel = ((Microsoft.Office.Interop.Excel._Application)this.HostApplication);
excel.ActiveWorkbook.Save();
- Exists an event handler for ADXExcelAppEvents.WorkbookActivate (ProtectedViewWindowActivate, and other) event to associate current ribbon form state with active workbook.

That's it. Very simple.
But next unexpected behavior can be reproduced:
1. Open two files in Excel 2013.
2. Make ribbon form different for file 1 and file 2 by entering some values in controls.
3. Start debugging. Put break point to ADXExcelAppEvents.WorkbookActivate event handler. Or use some logger if you want.
4. Active file 2 window by selecting some cell. Start dragging file 1 window that should be not active yet. Notice that active cell still present in file 2 window whereas file 1 window header already received focus.
5. During dragging press "ctrl+s". Under the hood: file 1 saved
At this step:
a) user32.dll GetFocus method returns pointer to file 2 window.
b) In reality we not only saving ActiveWorkbook. We accessing other properties like ActiveWorkbook.FullName. Example in ADXKeyboardShortcut.Action or ADXAddinModule.OnSendMessage event handler:
var excel = ((Microsoft.Office.Interop.Excel._Application)this.HostApplication);
var test = excel.ActiveWorkbook.FullName; // file 2 path
excel.ScreenUpdating = true; // it will trigger internal update mechanics according to the https://social.msdn.microsoft.com/Forums/office/en-US/7ec7ee04-9408-4205-a16e-741e624a8ab7/excel-automation-application-steals-focus?forum=exceldev#20be7c96-6646-48c1-ab04-d6f47dc7fc0f
var test2 = excel.ActiveWorkbook.FullName; // file 1 path (!)

As you can see by accessing some properties we may trigger internal update mechanics leading to changing of ActiveWorkbook value. But OK, we can live with it in case we will be able to synchronize ribbon form correspondingly.

6. Continue dragging and press "ctrl+s" again. Under the hood:
a) file 2 saved. So ActiveWorkbook now contain file 2 reference.
b) observe that we still seeing file 1 form state. It is because none of *Activate events fired. We are processing form state relying on them.
In addition we writing data from ribbon controls associated with file 1 to file 2 properties. That is actually a huge problem.

7. And finally stop dragging. Actual result: none of *Activate and *Deactivate events are fired but file 2 Excel window is active in fact.

It is also valid for 2013 Word and, I guess, for Power Point.

I cannot see any more or less stable workaround for it. I'd really like to use "*BeforeSave" event for Word, Excel and PowerPoint to achieve our needs. But we cannot because exists https://social.msdn.microsoft.com/Forums/office/en-US/eba95124-3ae4-4188-97ea-e44c10c95a97/word-2013-fires-beforesave-event-to-addin-during-document-close-even-though-dont-save-was?forum=worddev that doesn't allow to always identify if "Save" event produced by user action. We need to support 2010 office as well.

Could you please suggest something?
Thanks.
Posted 08 Dec, 2016 04:43:00 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Maxim,

All the Office-related events that you receive are generated by Office. Whether any given event is generated or not is solely determined by the corresponding Office application and its object model, not by Add-in Express.

You have to deal with how the Excel object model defines the active workbook. If you don't like how the ActiveWorkbook property behaves, you would need to invent your own definition (say, using Windows API) and use it instead of calling ActiveWorkbook.

What I see is this: a workbook becomes active after the user releases the left mouse button.

Turn your add-in off, create two new workbooks, and try to press Ctrl+S while dragging an Excel window as you describe: note that Excel doesn't let you save a workbook in this scenario. Consider blocking Ctrl+S while the left mouse button is down.

Maxim T writes:
I'd really like to use "*BeforeSave" event for Word, Excel and PowerPoint to achieve our needs. But we cannot because exists well known issue with Word AutoSave feature that doesn't allow to always identify if "Save" event produced by user action. We need to support 2010 office as well.


Such a way does exist. Intercept clicking all built-in controls (and key combinations) that cause saving the document. In the corresponding event handlers set a flag that you check (and clear) in the DocumentBeforeSave event: if you find the flag not set in this event, then the save is caused by Word, not by the user.

Additionally, there's a way which exists since Word 2007 SP2: see https://support.microsoft.com/en-us/kb/2193786.


Andrei Smolin
Add-in Express Team Leader
Posted 08 Dec, 2016 07:26:09 Top