Excel VSTO如何在激发WorkbookBeforeClose事件后检查对话框中的取消按钮是否已触发?

问题描述 投票:0回答:1

我目前正在开发Excel VSTO插件,这是WorkbookBeforeClose的代码

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

在此代码中,如果没有打开的工作簿,则禁用功能区。但是,如果我在尝试关闭Excel之后从对话框中按“取消”按钮,则功能区还是会被禁用。但是,由于WorkbookBeforeClose事件传递了一个Cancel参数,因此当我按下按钮时,我不知道如何设置该参数,如何检查提示您已触发按钮的对话框。

到目前为止,我已经看到的所有情况都在WorkbookBeforeClose处理程序的主体中实现了一个对话框,但是我不想实现自定义对话框,我想使用默认提供的对话框。

谢谢!

c# excel vsto
1个回答
0
投票

截至我的VBA经验

但我不想实施自定义对话框,我想使用默认提供的对话框。

不可能,因为该对话框仅在before_close事件之后出现。唯一(据我所知)管理这些内容的方法-创建自己的SaveChanges对话框,顺便说一句,这是非常简单的,并非每个用户都会注意到差异。而且,它将执行与默认提示相同的工作。您还应注意的另一件事-可能至少有一个看不见的工作簿。即使您看到这样的屏幕:enter image description herethis.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事件中再次启用它。

[Note我只是从VBA转到VSTO-因此,任何评论都将受到高度赞赏。

© www.soinside.com 2019 - 2024. All rights reserved.