简体   繁体   中英

Determine if Popup is in foreground of Excel

I'm writing a VSTO add-in for Excel and I have noticed that if I lock the sheet and password protect it (so only my add-in can write to it but the user can view it), if the user tries to edit the sheet they get the "This sheet is locked" popup. If while that prompt is still pending user input, the add-in tries to write to the sheet, Excel crashes. The act of writing to the sheet involves unprotecting it, writing the data, then locking it again. The Add-in captures data from an external source via the serial port so data could be written at any time.

To recreate: 1. Lock sheet with add-in. 2. User attempts to edit sheet contents 3. User is prompted that they cannot edit the contents of the sheet because it is locked. 4. Data comes in the serial port and the add-in attempts to unlock, write data, and lock the sheet before the user has a chance to ack the prompt that was thrown. 5. Excel bytes the dust.

Any suggestions? I was toying with the idea of maintaining a hidden "master" sheet and the visible sheet and just using an excel formula or named range to reference the hidden sheet. However this would then be open to editing and potential data corruption by a user. The data must be as un-editable as possible.

Update: I would be satisfied with catching the COMException so it doesn't kill excel, however the general "catch (Exception ex)" doesn't seem to help.

In VBA you can protect the sheet with UserInterFaceOnly:=True. This means the code can still write to the sheet. From this link it looks like this is true with a VSTO addin as well.

You may put check to ensure sheet is in interactive mode or active cell is not null, if check fails exit function that perform write operation

 private bool IsExcelInteractive()
    {
        try
        {
            Globals.ThisAddIn.Application.Interactive = Globals.ThisAddIn.Application.Interactive;
            return true;
        }
        catch
        {
            return false;
        }
    }

The issue was apparently

catch(Exception)

does not function as a general catch all when it comes to a COMException. Adding the line

using System.Runtime.InteropServices;

and then adding

catch(COMException)

to my try...catch blocks allows me to handle the errors better. Mix that with some code to retry the failed action a few times after using

SendKeys.SendWait("{ESC}");

seems to make things better. However, blindly sending the escape key to the forefront program can cause some issues however I cannot sit in an endless loop waiting for a user who may or may not be paying attention to clear up the issue on the screen. It seems to cause the serial port to stop buffering data and just dropping it if it's not handled fast enough.

您可以在功能区中添加一个按钮,然后单击它来执行此任务,而不是在单击单元格时执行此操作,这样就可以摆脱弹出窗口

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM