Excel VSTO, как проверить, сработала ли кнопка «Отмена» в диалоговом окне после запуска события WorkbookBeforeClose? - PullRequest
0 голосов
/ 25 января 2020

В настоящее время я разрабатываю надстройку Excel VSTO, и вот код для WorkbookBeforeClose

private void App_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel)
    {
        bool isEnabled = false;
        setRibbonControlState(ref isEnabled);
    }

В этом коде я отключаю ленту, если рабочая книга не осталась открытой. Но если я нажму кнопку «Отмена» в диалоговом окне после попытки закрыть Excel, лента все равно отключится. Но поскольку событие WorkbookBeforeClose передало параметр Cancel, я не знаю, как установить этот параметр при нажатии кнопки, как проверить диалоговое окно, запрашиваемое для кнопки, которая была активирована.

Все случаи I До сих пор видел, как реализован диалог в теле обработчика WorkbookBeforeClose, но я не хочу реализовывать пользовательский диалог, я хотел бы использовать тот, который предоставляется по умолчанию.

Спасибо!

1 Ответ

0 голосов
/ 27 января 2020

Начиная с моего опыта VBA это

, но я не хочу реализовывать пользовательский диалог, я хотел бы использовать предоставленный по умолчанию.

невозможно, потому что это диалоговое окно появляется сразу после события before_close.
Единственный (известный мне) способ управления этим материалом - это создать собственный диалог SaveChanges , что, кстати, , очень просто и не каждый пользователь заметит разницу. Более того, он будет выполнять ту же работу, что и приглашение по умолчанию.
Еще одна вещь, на которую следует обратить внимание - это то, что может быть хотя бы одна невидимая книга. Даже если вы видите такой экран:
enter image description here есть вероятность, что this.Application.Workbooks.Count покажет вам 1 вместо 0. Это связано с тем, что у пользователя есть собственный Personal.xlsb Книга, которая невидима, но, тем не менее, загружена с приложением Excel.Application. Так что, если вы хотите правильно отключить ленту - вы должны учитывать это.

Вот мой пример этого решения:

public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            this.Application.WorkbookBeforeClose += ApplicationOnWorkbookBeforeClose;
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        // Catch the before close event
        private void ApplicationOnWorkbookBeforeClose(Excel.Workbook wb, ref bool cancel)
        {

            if (!wb.Saved)
            {
                switch (MessageBox.Show(text:$"Do you want to save changes you made to '{this.Application.ActiveWorkbook.Name}'?", 
                    caption:"Microsoft Excel",buttons:MessageBoxButtons.YesNoCancel, icon:MessageBoxIcon.Exclamation))
                {
                    case DialogResult.Cancel: // case want to cancel - break the closing event
                        {
                            cancel = true;
                            return;
                        }
                    case DialogResult.Yes: // case user want to save wb - save wb
                        {
                            wb.Save();
                            break;
                        }
                    case DialogResult.No: // case user don't want to save wb - mark wb as saved to avoid the application messagebox to appear
                        {
                            wb.Saved = true;
                            break;
                        }
                }
            }

            if (IsAnyWorkbookOpen())
            {
                // replace this with your code
                MessageBox.Show("Some books will still be open, don't turn off the ribbon");
                return;
            }
            // replace this with your code
            MessageBox.Show("All books will be closed");
        }

        private bool IsAnyWorkbookOpen()
        {
            // check that remaining amount of open workbooks without the one being closed is greater that 2
            if (this.Application.Workbooks.Count - 1 > 2)
            {
                return true;
            }
            // IF the count of workbooks is 2 one of them maybe a PERSONAL.xlsb
            else if (this.Application.Workbooks.Count == 2)
            {
                foreach (Excel.Workbook wb in this.Application.Workbooks)
                {
                    if (!wb.Name.Equals(this.Application.ActiveWorkbook.Name))
                    {
                        // In case when one of two open workbooks is Personal macro book you may assume that 
                        // there will be no open workbooks for user to work directly
                        if (wb.Name.Equals("Personal.xlsb".ToUpper()))
                        {
                            return false;
                        }
                    }
                }
                // In case when NONE of two open workbooks is a Personal macro book
                // there will be at least one open workbook for user to work directly
                return true;
            }
            else
            {
                return true;
            }
        }


        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }

И последнее - если вы отключите ленту, но приложение все еще будет работать - вам придется снова включить его на workbook_activate event.

Примечание Я просто перехожу с VBA на VSTO - поэтому любые комментарии будут высоко оценены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...