C# 正在调用应用程序。计算正在编辑的公式
我正在处理一个外接程序,该外接程序使用以下命令定期请求重新计算:C# 正在调用应用程序。计算正在编辑的公式,c#,excel,excel-interop,excel-dna,C#,Excel,Excel Interop,Excel Dna,我正在处理一个外接程序,该外接程序使用以下命令定期请求重新计算: ((Excel.Application)xlApp.Calculate() 如果用户当时正在编辑公式,Excel在我执行此操作时会中断用户公式 我预计该操作会由于用户活动而失败,但在奇怪地中断用户键入的任何公式之前,它确实会失败 例如,如果用户正在键入一个单元 =和(1 + 2 + < /代码>),一旦运行上述代码行,它们的输入被中断,Excel抱怨它们的公式不完整或类似。 请注意,这甚至与用户点击“回车”时的行为不同,这将
((Excel.Application)xlApp.Calculate()
如果用户当时正在编辑公式,Excel在我执行此操作时会中断用户公式
我预计该操作会由于用户活动而失败,但在奇怪地中断用户键入的任何公式之前,它确实会失败
例如,如果用户正在键入一个单元<代码> =和(1 + 2 + < /代码>),一旦运行上述代码行,它们的输入被中断,Excel抱怨它们的公式不完整或类似。
请注意,这甚至与用户点击“回车”时的行为不同,这将导致如下对话框: Excel正在做一些更奇怪的事情,试图将用户完全踢出公式输入,而没有细节 更奇怪的是,如果用户的公式在语法上是有效的,Excel不仅会让他们放弃编辑公式,还会用结果替换公式的内容我已经证实,这个问题正在我的许多用户身上发生,他们都使用现代版本的Excel 我尝试在excel拥有的主应用程序上调用
Calculate()
,也尝试在后台进程中调用,但两者的行为相同。我尝试了不同的计算方法(如CalculateFull()
),但都是一样的。我还尝试了其他互操作操作,如xlApp.StatusBar=“Test”
并且它们不会像计算
那样中断用户的操作
我能做些什么来防止像这样打断用户?我可以发誓这不是旧版本Excel中的行为
如果有区别的话,我使用Excel Dna库作为外接程序的基础,但我纯粹是使用Microsoft.Office.Interop.Excel.Application
更新一些更奇怪的内容: 我使用所描述的方法来检查是否可以设置
应用程序,取得了轻微的成功。Interactive
设置为false
,然后返回到true
-如果没有,用户正在编辑单元格。这允许我在公式编辑器中跳过计算
,但奇怪的是,这并不能阻止Excel踢用户没有其他输入
例如,如果用户是:
- 编辑图纸名称
- 将命名范围名称指定给单元格
- 在“字体”功能区框中键入新字体名称
- 等等
app.Calculate()
时,用户会被踢出所有这些操作,而检测他们是否正在编辑公式的常用方法不会检测用户何时正在执行这些操作--
更新re:应用程序。交互式
事实证明,设置Application.Interactive=True
会导致更多的用户中断问题,例如从对话框中窃取焦点,以及中断鼠标拖动操作(如调整大小或移动窗口)。如果您的目标是不打扰用户,则不建议将其作为解决方案。编辑
使用应用程序。交互式导致的问题多于解决的问题。不建议使用此解决方案。
这仍然是一项正在进行的工作,但到目前为止,我不得不求助于各种黑客手段来检测用户是否正在Excel中积极地做一些事情,如果是这样的话,我只需停止自己调用“计算” 主要的检查是:
- Excel拥有的窗口当前是否在前台
- 如果不是,则某些用户正在使用其他程序,调用Calculate不会中断这些程序
- 如果是,它是工作簿主窗口(
)吗?Excel.Application.Hwnd
- 如果没有,则用户处于Excel对话框、VBA编辑器等中。不要中断
- 如果是这样,我们需要更深入地挖掘
- 用户的鼠标当前是否已按下?
- 如果是这样,他们肯定很忙(拖动、单击、调整大小等),不要打断
- 用户的光标是否位于某个可编辑控件中?(重命名工作表、从下拉列表中选择字体、在命名范围框中键入等)。
- 如果是这样的话,不要打断。(还没有弄清楚如何进行测试)
- 用户是否正在编辑单元格?(可以专门使用
)进行测试)Excel.Application.Interactive
- 如果是这样,不要打断
2年后-我很高兴一些人开始使用它。事实上,我最终对它进行了一些重大改进,以便能够尽可能多地确定“为什么”Excel很忙。因此,我将介绍两种解决方案 首先,简单、独立(但有限)的解决方案:
/// <summary>A variety of checks to see whether Excel is busy. This is required because
/// in recent versions of Excel, Recalculate can interrupt user activity.</summary>
private static bool IsExcelBusy(Application xlApp)
{
try
{
// The user is editing if Interactive is true and cannot be set to false
// NOTE: Toggling App.Interactive can interrupt certain user activity
// (e.g. renaming a sheet) so use this check sparingly.
if (xlApp.Interactive)
{
xlApp.Interactive = false;
xlApp.Interactive = true;
}
// Otherwise, assume Excel is not busy.
return false;
}
catch (AccessViolationException)
{
return true;
}
catch (COMException)
{
return true;
}
}
///检查Excel是否忙的各种检查。这是必需的,因为
///在最新版本的Excel中,重新计算可能会中断用户活动。
专用静态bool IsExcelBusy(应用程序xlApp)
{
尝试
{
//如果Interactive为true且不能设置为false,则用户正在编辑
//注意:切换应用程序。交互可能会中断某些用户活动
//(例如,重命名工作表)因此请谨慎使用此检查。
如果(xlApp.Interactive)
{
xlApp.Interactive=false;
xlApp.Interactive=true;
}
//否则,假设Excel不忙。
返回false;
}
捕获(AccessViolationException)
{
雷图