c# - Excel VSTO如何在触发WorkbookBeforeClose事件后检查是否已从对话框中触发了取消按钮?
问题描述
我目前正在开发 Excel VSTO 插件,这是 WorkbookBeforeClose 的代码
private void App_WorkbookBeforeClose(Excel.Workbook Wb, ref bool Cancel)
{
bool isEnabled = false;
setRibbonControlState(ref isEnabled);
}
在此代码中,如果没有打开任何工作簿,我将禁用功能区。但是,如果我在尝试关闭 Excel 后按下对话框中的取消按钮,则功能区无论如何都会被禁用。但是由于 WorkbookBeforeClose 事件传递了一个 Cancel 参数,我不知道当我按下按钮时如何设置该参数,如何检查提示已触发按钮的对话框。
到目前为止,我看到的所有案例都在 WorkbookBeforeClose 处理程序的主体中实现了一个对话框,但我不想实现自定义对话框,我想使用默认提供的对话框。
谢谢!
解决方案
根据我的 VBA 经验
但我不想实现自定义对话框,我想使用默认提供的对话框。
是不可能的,因为该对话框出现在before_close
事件之后。
管理这些东西的唯一(我知道的)方法是创建自己的SaveChanges对话框,顺便说一句,这非常简单,并不是每个用户都会注意到其中的区别。而且,它会做与默认提示相同的工作。
您应该注意的另一件事 - 可能至少有一个不可见的工作簿。即使您看到这样的屏幕:
也有可能this.Application.Workbooks.Count
会显示 1,而不是 0。这是因为用户可能拥有自己的 Personal.xlsb 工作簿,该工作簿是不可见的,但仍然加载了 Excel。应用。因此,如果您想正确禁用功能区 - 您也应该考虑这一点。
这是我的这个解决方案的例子:
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
事件中再次启用它。
请注意,我只是从 VBA 转移到 VSTO - 所以任何评论都非常感谢。
推荐阅读
- java - Android Retrofit API 使用
- python - Python,从文件中读取 -> 将文件内容添加到列表 -> 将列表与用户输入进行比较
- go - 为什么我会从此 API 调用中收到意外的 EOF?
- javascript - 验证电话号码的字符串操作
- python - 使用 Kafka 和 Python 向 Elasticsearch 发送数据时抛出 RequestError
- c++ - 适用于 Windows 控制台应用程序的传感器 API 的 SetEventSink()
- java - 将另一个api的返回数据集成到服务方法
- c - C:函数,将字符串作为字符数组返回
- python - 将 OpenCV C++ Mat 暴露给 Python
- java - 使用 JDBC 连接到 Hive 2.3.0