【发布时间】:2017-12-16 01:59:58
【问题描述】:
我有许多单元格(我们称之为源单元格),它们被另一个单元格(我们称之为目标单元格)通过其公式引用。我更改了源单元格中的值,我想在目标单元格中的公式重新计算后得到结果值。
我暂时将计算设置为XlCalculation.xlCalculationManual,并使用Application.Calculate 强制重新计算。
问题在于,当在循环内执行时,有时公式计算得不够快,代码会选择较旧的值。所以我想要的是等待强制重新计算结束。
我尝试了Application.CalculationState 方法,但它始终是xlPending,这使程序陷入无限循环。 excel文件有一些循环引用,设置了计算迭代,我可以在Excel状态栏中不断看到“计算”警告(即使我手动重新计算)。
我还尝试将 Application.AfterCalculate 事件与 Autoreset 事件结合使用,但我再次无限等待(我怀疑发出事件的信号和等待事件都发生在同一个线程上,所以当首先执行等待时,程序挂起):
public static AutoResetEvent AutoEvent;
public static void StartMonitoring()
{
AutoEvent?.Close();
AutoEvent = new AutoResetEvent(false);
Globals.ThisAddIn.Application.AfterCalculate += Application_AfterCalculate;
}
public static void StopMonitoring()
{
Globals.ThisAddIn.Application.AfterCalculate -= Application_AfterCalculate;
AutoEvent?.Close();
AutoEvent = null;
}
public static void WaitForCalculations()
{
AutoEvent.WaitOne();
StopMonitoring();
}
private static void Application_AfterCalculate()
{
AutoEvent.Set();
}
...
StartMonitoring();
Globals.ThisAddIn.Application.Calculate()
WaitForCalculations();
有更好的想法吗?我是否希望找到给定 excel 的解决方案,或者我应该解决循环引用?
【问题讨论】:
-
带线的东西给了我一个想法。它们确实在同一个线程上运行。我会尝试在不同的线程上启动整个过程!
-
就我个人而言,我会摆脱循环引用,因为它们会导致各种问题,并非所有问题都可以轻松避免。另一种解决方案可能是单步循环计算(例如:将迭代设置为 2:重新计算直到迭代计数 = 1)
-
@CharlesWilliams 我知道,但实际上不可能解决循环引用。我现在尝试 AfterCalculate 方法,我已经将整个更改源代码放在不同的线程中查看目标代码,看起来给我一致的结果而不会挂起。奇怪的是,集合总是在等待之前......继续调查。
-
也许您可以在将计算重置为自动之前尝试添加
DoEvents?另外,在您手动触发计算后,CalculationState 是否不返回正在计算?在这种情况下,也许您可以等待状态变为待定状态? -
@NetMage 我曾想过,但似乎由于循环引用和迭代模式,状态始终为 xlPending。
标签: c# excel excel-interop vba