应用程序。根据工作簿计算

我正在用超过200 000个公式(一些非常复杂的数组公式)来pipe理一个工作簿,这意味着我不能让Excel每次点击某处时自动计算所有的单元格(计算所有内容需要大约8个小时)。

而不是这样,计算设置为手动,并且在打开Calculation.xlsm时执行以下VBA代码:

With Application .CalculateBeforeSave = False .Calculation = xlCalculationManual End With 

我需要时使用自定义button来计算200k单元的某些部分。

我发现Excel确实logging了每个工作簿中的设置,这意味着如果打开Calculation.xlsm,Excel会记住计算设置为手动。 如果我打开我的Values.xlsx,Excel确实记得计算设置为自动。 这是之前我试图将Calculation.xlsm 中的值复制到Values.xlsx

现在,因为我在Calculation.xlsm中使用VBA将值复制到Values.xlsx,Excel也将Application.Calculation设置应用于该工作簿,这意味着如果使用Excel的新实例打开它,计算将会仍然被设置为手动。

如果我在Calculation.xlsm工作簿中closures带有VBA的Application.Calculation = xlCalculationAutomatic之前添加Application.Calculation = xlCalculationAutomatic ,它将起作用,但Excel也将开始计算我的Calculation.xlsm工作簿中的200k个单元格,不想要。

所以我的问题是关于如何基于特定的工作簿而不是Application对象实际设置Excel的计算。 这是基于这样一个事实,即Excel根据打开哪个工作簿来跟踪该设置(您可以只进行testing并创build两个不同的.xlsx文件,一个启用计算,另一个禁用计算,Excel将会记住这些设置)。

我知道我可以在closures它之前使用Worksheets.Range.Calculate方法来计算我的Values.xlsx工作簿,但是如果在此之后在Excel的新实例中打开它,计算仍然会被设置为手动。


编辑3:20 pm :不知道我是否足够清楚,英语不是我的母语。 简而言之,我将Calculation.xlsm与VBA和“ Calculation设置为手动。 我有没有VBA和计算设置为自动Values.xlsx 。 如果在Calculation.xlsm 使用以下VBA代码打开Values.xlsx ,Excel将自动将我的Values.xlsx工作簿转换为手动计算。

Calculation.xlsm代码:

 Private Sub Workbook_Open() With Application .CalculateBeforeSave = False .Calculation = xlCalculationManual End With End Sub Sub someFunction() Set WB = Application.Workbooks.Open("Values.xlsx") Set WBws = WB.Sheets("mySheet") DoEvents wb.Save WB.Close End Sub 

执行someFunction()后,将Values.xlsx计算设置为手动。 那就是问题所在。 我希望它保持自动(我不能将VBA添加到该文件,它必须全部从上面的Calculation.xlsm完成)。


编辑3:40下午 :我可以只有我的大工作簿与Application.Calculation设置为手动,把我需要的剪贴板中的所有数据(我只需要值,而不是公式),closures它(将VBA仍然继续即使我closures从其执行的工作簿?),将Application.Calculation设置为自动(因为没有打开的工作簿),然后打开目标工作簿粘贴值(将Excel仍将数据保留在剪贴板中另一个工作簿已closures?),然后保存并closures该工作簿,将计算设置为手动(未打开工作簿),然后重新打开执行代码的原始工作簿?

一种方法是创build一个新的Excel实例。 虽然这可能比较慢,但在不closures函数内部的书籍/应用程序的情况下,可能更难以处理,但对于例如简单的情况,可能最容易实现:

 Sub someFunction() Dim newExcel as Excel.Application Set newExcel = CreateObject("Excel.Application") Set WB = newExcel.Workbooks.Open("Values.xlsx") Set WBws = WB.Sheets("mySheet") DoEvents wb.Save WB.Close newExcel.Quit Set newExcel = Nothing End Sub 

Application.Calculation属性是相对于该应用程序的实例,而不是其他实例。

或者 ,您可以使用应用程序级别的事件处理程序。 我怀疑这可能会更快,但我没有testing速度。

从这个非常相似的问题稍微修改(这也是有条件地禁用应用程序级属性)。

如果:

我只是担心,如果我closures从中启动它的工作簿,代码仍然会被执行

只需使用正常的Workbook_BeforeClose事件处理程序来恢复所需的Application.Calculation属性(对于整个应用程序/所有其他打开的工作簿)。

答案的其余部分:

创build一个应用程序级别的事件处理程序,创build一个名为cEventClass的类模块,并将其中的代码:

 Public WithEvents appevent As Application Dim ret Private Sub appevent_WorkbookActivate(ByVal wb As Workbook) Call ToggleCalculation(wb, ret) End Sub 

在名为mod_Caclulate的标准模块中使用以下mod_Caclulate

 Option Explicit Public XLEvents As New cEventClass Sub SetEventHandler() If XLEvents.appevent Is Nothing Then Set XLEvents.appevent = Application End If End Sub Sub ToggleCalculation(wb As Workbook, Optional ret) If wb.Name = ThisWorkbook.Name Then ret = xlCalculationManual Else ret = xlCalculationAutomatic End If Application.Calculation = ret End Sub 

把它放在Workbook_Open事件处理程序中,你总是要手动计算:

 Option Explicit Private Sub Workbook_Open() 'Create the event handler when the workbook opens Call mod_Caclulate.SetEventHandler Call mod_Caclulate.ToggleCalculation(Me) End Sub 

这将仅在打开特定工作簿时创build事件处理程序,并且只要将视图切换到其他工作簿,处理程序就会切换“ Calculation属性。

注意:如果“结束”运行时或在debugging时执行任何会导致状态丢失的事情,则将丢失事件处理程序。 这总是可以通过调用Workbook_Open过程来恢复,所以在ThisWorkbook代码模块中也可以添加一个额外的保护措施:

 Private Sub Workbook_SheetActivate(ByVal Sh As Object) ' Additional safeguard in case state loss has killed the event handler: ' use some workbook-level events to re-instantiate the event handler Call Workbook_Open End Sub