I'm working on an add-in that periodically requests a recalculation using the following:
((Excel.Application) xlApp).Calculate()
If the user happens to be editing a formula at the time, Excel breaks the users formula when I do this.
I expect the action to fail due to user activity, which it does, but not before oddly interrupting whatever formula the user is typing.
For example, if the user is in the middle of typing into a cell =SUM(1+2+
, as soon as I run the above line of code, their input is interrupted and Excel complains that their formula is incomplete or similar.
Note that this is not even the same behaviour as if the user were to hit "Enter", which would result in a dialog like this:
Excel is doing something weirder, and trying to kick the user out of their formula input entirely without the niceties.
Even weirder - if the user's formula is syntactically valid, Excel not only kicks them out of editing the formula, but replaces the contents of the formula with the result!
I've confirmed that the issue is happening to a variety of my users, all using modern versions of Excel.
I've tried both invoking Calculate()
on the main excel-owned application, and in a background process, but both behave identically. I've tried different calculation methods (like CalculateFull()
) but it's the same. I've also tried other interop actions like xlApp.StatusBar = "Test"
and they don't interrupt the user's actions the way Calculate
does.
Is there anything I can do to prevent interrupting the user like this? I could have sworn this wasn't the behavior in older versions of Excel.
If it makes a difference, I am using the Excel-Dna library as the basis for my add-in, but I'm purely using Microsoft.Office.Interop.Excel.Application
for this piece.
Update with some more weirdness:
I had mild success using the method described here to check if I could set Application.Interactive
to false
then back to true
- if not, the user is editing a cell. That allows me to skip Calculate
in cases where they are in the formula editor, but oddly, doesn't prevent Excel from kicking the user out of other inputs.
For example, if the user is:
- Editing a sheet name
- Assigning a named range name to a cell
- Typing a new font name into the "Font" ribbon box
- etc...
--The user gets kicked out of all these actions when app.Calculate()
is called, and usual methods for detecting if they are editing a formula don't detect when the user is doing any of those things.--
Update re: Application.Interactive
It turns out settingApplication.Interactive = True
causes even more user-interruption issues, such as stealing focus out of dialogs, and interrupting mouse-drag operations (like resizing or moving windows). Not recommended as a solution if your goal is to not annoy users.
EDIT
Using
Application.Interactive
caused more problems than it solved. This solution is not recommended.This is still a work in progress, but so far I've had to resort to a variety of hacks to detect if the user is actively doing something in Excel, and simply stop myself from calling "Calculate" if so.
The main checks are:
Excel.Application.Hwnd
)?Excel.Application.Interactive
)There's still things to work around, but this already helps a lot.
Here's the code - hopefully the comments make the logical progression clear:
Based on how difficult this has been, I feel as though I'm trying to do things with Excel that it isn't meant for. Excel was definitely meant to be automated, and definitely meant to be used by end users. Maybe not just both at the same time?