只需在Active Workbook上进行Excel计算,寻找解决方法

当您打开多个Excel文件,并且您的VBA / VSTO代码调用Calculatefunction,或打开自动计算时,Excel将痛苦地重新计算所有打开的工作簿 ,而不仅仅是活动的工作簿。

在这里输入图像说明 这是一个众所周知且报道良好的问题,这个问题已经存在了好几年了,但是微软似乎对解决这个问题并不感兴趣。

保存前只计算活动工作簿

Microsoft Excel心愿单:工作簿级别计算

可笑的是,在VBA和VSTO中,微软赋予我们以下能力:

  • 重新计算一个特定的Worksheeet
  • 重新计算所有打开的工作簿

…但是没有办法重新计算一个特定的工作簿。

在我工作的金融公司,这是一个很大的问题。 我们的精算师有大,庞大的Excel文件,充满公式,当他们点击一个工作簿上的计算,或者我们在保存文件之前执行计算,然后他们必须等待几分钟,所有其他打开的Excel文件得到计算。

有两种方法可以解决这个问题。

你可以像这样运行一些VBA:

 Application.Calculation = xlManual For Each sh In ActiveWorkbook.Worksheets sh.Calculate Next sh 

但是这不能保证工作。 您的“工作表1”可能包含指向“工作表2”中的单元格的公式,但“工作表2”中的其他单元格可能依赖于“工作表1”。 因此,计算每个工作表一次可能不足以对您的工作簿执行完整的计算。

或者,您可以在单独的实例中打开每个Excel文件(通过在打开Excel图标时按住ALT键)。 但是,如下所述,您将失去完整的Excel切换function:

不能完全切割Excel实例之间的粘贴

所以,我的问题是…有没有人find解决这个问题的方法

只想重新计算Active Excel工作簿中的单元格。

我想知道是否可以添加一些VBA或VSTO,在启动Active Workbook上的计算之前将所有非活动工作簿设置为“只读”,从而防止其他工作簿被重新计算。 但这是不可能的。 只能读取“ Workbook.ReadOnly ”,而不能以编程方式设置。

或者可能添加一个处理程序到Worksheet_Calculate事件,它检查正在运行的VBA代码是否属于活动工作簿,如果没有,它会中止尝试计算…? 但是这个事件实际上是 Worksheet被计算出来之后被踢开的,所以已经太迟了。

我们公司不能成为唯一遭受这个问题的人…

任何build议(除了升级到莲花1-2-3)?

此方法使用另一个Excel实例来避免多个工作簿计算。 从这个SO问题中抽取了几行使用新实例的代码, 这个问题涉及到类似的主题,可能会引起您的兴趣。

您必须在特定情况下testing速度,因为closures/打开时间可能不会超出避免的计算!

macros观步骤

  • 将计算设置为手动
  • 保存并退出所需的工作簿
  • 在Excel的新实例中打开它
  • 重新计算
  • 在Excel的原始实例中保存,closures并重新打开。

运行这个脚本的关键点

  • macros不能重新计算工作簿中,因为它在过程中被closures(两次)。 它应该放在其他“实用”工作簿中。

代码 – 请参阅注释的详细信息

 Sub CalculateWorkbook(WB As Workbook) ' Store path of given workbook for opening and closing Dim filepath As String filepath = WB.FullName ' Turn off calculation before saving Dim currentCalcBeforeSave As Boolean currentCalcBeforeSave = Application.CalculateBeforeSave Application.CalculateBeforeSave = False ' Store current calculation mode / screen update and then set it to manual Dim currentCalcMode As Integer, currentScreenUpdate As Integer currentCalcMode = Application.Calculation currentScreenUpdate = Application.ScreenUpdating Application.Calculation = xlCalculationManual Application.ScreenUpdating = False ' Close and save the given workbook WB.Close savechanges:=True ' Open a new INSTANCE of Excel - meaning seperate calculation calls Dim newExcel As Excel.Application Set newExcel = CreateObject("Excel.Application") ' Could make it visible so that any problems don't leave it hidden in the background ' newExcel.Visible = False ' Set the calculation mode to manual in the new instance sothat the workbook isn't calculated on opening. ' This can't be done without an existing workbook object. Dim tempWB As Workbook Set tempWB = newExcel.Workbooks.Add newExcel.Calculation = xlCalculationManual newExcel.CalculateBeforeSave = False ' Open the workbook in the new instance of Excel Dim newWB As Workbook Set newWB = newExcel.Workbooks.Open(filepath) ' Calculate workbook once newExcel.Calculate ' Close and save the workbook, tempworkbook and quit new instance newWB.Close savechanges:=True tempWB.Close savechanges:=False newExcel.Quit ' Re-open in the active instance of Excel Application.Workbooks.Open filepath ' Reset the application parameters Application.CalculateBeforeSave = currentCalcBeforeSave Application.ScreenUpdating = currentScreenUpdate Application.Calculation = currentCalcMode End Sub 

通过传递你想重新计算的工作簿对象来调用上面的子(这可以通过button来完成)。

这已经在一个非常简单的示例工作簿上进行了testing,并且这个概念起作用。 但是,请首先在工作簿的副本上进行testing,因为它没有经过完全稳健性testing,并且没有error handling。

在我的FastExcel产品中使用的方法包括将WorkSheet.EnableCalculation设置为false,对于所有非活动工作簿中的所有工作表,对于活动工作簿中的所有工作表,将其设置为True。

这种方法有效,但有一个缺点,就是在更改活动工作簿时,需要对下一个计算进行全面的计算:这是一个折衷。

通过下载FastExcel的试用版,您可以在您的情况下尝试下载FastExcel V3 build 231.655.789.380的15天全function试用版

然后使用“FastExcel计算选项”并在“当前计算模式”设置中选中“活动工作簿”checkbox;

免责声明:我拥有,开发和销售FastExcel产品。 包含活动工作簿计算代码的FastExcel组件是FastExcel V3 Calc