【问题标题】:Wait for calculations to end in excel with circular references使用循环引用等待计算以 excel 结束
【发布时间】: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


【解决方案1】:

如果所有其他选项都失败 您可以尝试将公式设置为手动并使用 vb 代码分别在每个单元格中执行公式:

  Application.Calculation = xlManual

  Range("NAMED_RANGE_1").Formula = "=10 + NAMED_RANGE_2"
  Range("NAMED_RANGE_2").Formula = "=10 + NAMED_RANGE_1"

(更容易将单元格命名为 Ranges 1st) 如果您想禁止循环引用警告,您始终可以从其中一个单元格中删除公式:

  Selection.Copy
  Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False

【讨论】:

  • 我不明白你在提议什么。我确实设置了手动计算。 excel 非常复杂,有一堆循环引用可能包含在我尝试计算的公式中,也可能不包含。
  • 通过重新输入公式,您正在强制计算公式。您可以按照您想要的任何顺序执行此操作。或者,您可以创建一个函数,将 "=" 替换为 "=" ,这也将强制公式进行计算。
  • EX: Sheets("Sheet1").Range("A1").Cells.Replace What:="=", Replacement:="="
猜你喜欢
  • 2021-11-20
  • 2022-01-16
  • 2021-03-02
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多