VBA计算方法会降低性能和阻塞效果

时间:2017-08-17 21:04:22

标签: vba performance excel-vba calculation excel

代码在具有35个表格的模型中基于UserForm复选框选择计算五个单独的DataTable,其中约30个是相互依赖的。过去花了不到9分钟计算的五个表(启用计时器 - 我知道这个可能会减慢速度),直到我介绍了我认为简单的添加,即DataTables使用的两个变量之一的索引/匹配,我在开头添加(除了几个提示)代码。 通过从下拉列表(DT表格上的单元格和数据验证列表)中选择的值的索引/匹配来定位另一个工作表上的相关单元格,然后链接到驱动该表格的两个单元格之一。第二个变量总是在同一个地方(还有另一个工作表),代码在开始时激活(链接到DT工作表),最后硬编码。

这个简单的添加似乎引起了比我预期更多的问题,将计算时间延长到将近15分钟并迫使我改变计算方法。

添加索引/匹配我定义了许多新变量(全部显式)并尽可能多地组合到预定义的名称中,但最终得到了先前功能计算的错误结果,其中似乎是其中一个DT变量(静态的,没有索引/匹配来找到它)现在被忽略了,我最终得到了一个完全相同结果的表。我以前在每张桌子上使用过这个:

For Each s In Worksheets
s.Calculate
Next s

现在我用Application.Calculate替换它,它会产生所需的结果,但需要更长的时间。

这个改变的问题,我相信以前优化了计算时间(现在似乎是唯一破坏结果的东西),是Application.Calculate,如果我理解正确的话,不仅已经使计算更长,但现在也将触发计算任何其他打开的工作簿,进一步延长时间。

代码:

Option Explicit
Public closetime, OpenTime, t

Sub Sensitivities()

Dim i As Long
Dim s As Worksheet, Sens As Worksheet, BuildInput As Worksheet, GlobInput As Worksheet

Dim Combo1 As Range, Combo2 As Range, IRRs As Range, SalesPrice As Range, Multiples As Range, Combo1Dt As Range, Combo2Dt As Range
Dim IRRsDt As Range, SalesPriceDt As Range, MultiplesDt As Range, BaseYield As Range, BaseExit As Range, VarYield As Range, VarExit As Range

Dim GlobalExit As Range, PropList As Range, AllYieldsBase As Range, AllYieldsTemp As Range

Dim NIY As Integer, PropName As Integer
Dim VarYieldVal As String, PropsVal As String
Dim BuildInputData As Range, BuildInputPropNames As Range, BuildInputCategories As Range
Dim Target As Range

Set Sens = Worksheets("Sensitivities")
Set BuildInput = Worksheets("Building Input")
Set GlobInput = Worksheets("Global Input")

Set BaseYield = Sens.Range("AF2")
Set BaseExit = Sens.Range("AF4")
Set VarYield = Sens.Range("AD2")
Set VarExit = Sens.Range("AD4")
Set AllYieldsBase = BuildInput.Range("F24:DA24")
Set AllYieldsTemp = BuildInput.Range("F26:DA26")
Set GlobalExit = GlobInput.Range("H7")

Set PropList = Sheets("List Reference").Range("B4:B103")
VarYieldVal = Sens.Range("AE2").Value
PropsVal = Sens.Range("AD3").Value
Set BuildInputData = BuildInput.Range("E1:DA75")
Set BuildInputPropNames = BuildInput.Range("E3:DA3")
Set BuildInputCategories = BuildInput.Range("E1:E75")


Set Combo1 = Sens.Range("AD7:AS16")
Set Combo2 = Sens.Range("AD18:AM27")
Set IRRs = Sens.Range("AD30:AM39")
Set SalesPrice = Sens.Range("AD42:AM51")
Set Multiples = Sens.Range("AP30:AY39")

Set Combo1Dt = Sens.Range("AE8:AS16")
Set Combo2Dt = Sens.Range("AE19:AM27")
Set IRRsDt = Sens.Range("AE31:AM39")
Set SalesPriceDt = Sens.Range("AE43:AM51")
Set MultiplesDt = Sens.Range("AQ31:AY39")

    UserForm1.Hide

    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
        .EnableCancelKey = xlDisabled
        .EnableEvents = False
    End With


    ActiveSheet.EnableFormatConditionsCalculation = False

    'MsgBox "Calculation time is likely to be extended significantly if you have " & vbNewLine & "other Workbooks open. To avoid that, close other Workbooks first."


    Dim mbResult As Integer
    mbResult = MsgBox("This will overwrite the sensitivities results currently shown. Would you like to save a copy of the model before proceeding?", _
     vbYesNoCancel)

    Select Case mbResult
        Case vbYes

            With ActiveWorkbook
                If Not .Saved Then .SaveAs Application.GetSaveAsFilename()
            End With
        Case vbNo

        Case vbCancel

            Exit Sub

    End Select


    If UserForm1.CheckBox1.Value = True And UserForm1.CheckBox2.Value = True And UserForm1.CheckBox3.Value = True And UserForm1.CheckBox4.Value = True And UserForm1.CheckBox5.Value = True Then

    MsgBox "You have selected all five tables - this will take up to 15 minutes to calculate."


    End If

    Application.Cursor = xlWait
    Application.DisplayStatusBar = True
    Application.StatusBar = "Calculating Sensitivities..."

OpenTime = Time
i = 1

    For Each s In Worksheets
    s.Unprotect Password:="Whatever"
    Next

    Sens.Range("BB4:BB103") = PropList.Value
    AllYieldsTemp.Value = AllYieldsBase.Value

        GlobalExit.FormulaR1C1 = "=Sensitivities!R4C30"

        With Application.WorksheetFunction
            NIY = .Match(VarYieldVal, BuildInputCategories, 0)
            PropName = .Match(PropsVal, BuildInputPropNames, 0)
        Set Target = .Index(BuildInputData, NIY, PropName)

        Target.FormulaR1C1 = "=Sensitivities!R2C30"
        End With
            Set PropList = Nothing
            Set BuildInputData = Nothing
            Set BuildInputPropNames = Nothing
            Set BuildInputCategories = Nothing

        Sens.Select

        Application.Calculate

        If UserForm1.CheckBox1.Value = True Then
                Combo1.Table ColumnInput:=VarExit
            'For Each s In Worksheets
            's.Calculate
            'Next s
            Application.Calculate
                Combo1Dt = Combo1Dt.Value
        End If
            Set Combo1 = Nothing
            Set Combo1Dt = Nothing

        If UserForm1.CheckBox2.Value = True Then
            GlobalExit.FormulaR1C1 = "=Sensitivities!R4C32"
            Combo2.Table ColumnInput:=VarYield
            'For Each s In ActiveWorkbook.Sheets
            's.Calculate
            'Next s
            Application.Calculate
            Range("N34:W42").Value = Range("N21:W29").Value
            GlobalExit.FormulaR1C1 = "=Sensitivities!R4C30"

            For Each s In ActiveWorkbook.Sheets
            s.Calculate
            Next s
            Combo2Dt = Combo2Dt.Value
        End If
            Set Combo2 = Nothing
            Set Combo2Dt = Nothing

        If UserForm1.CheckBox3.Value = True Then
            IRRs.Table RowInput:=VarExit, ColumnInput:=VarYield
            'For Each s In ActiveWorkbook.Sheets
            's.Calculate
            'Next s
            Application.Calculate
            IRRsDt = IRRsDt.Value
        End If
            Set IRRs = Nothing
            Set IRRsDt = Nothing

        If UserForm1.CheckBox4.Value = True Then
            SalesPrice.Table RowInput:=VarExit, ColumnInput:=VarYield
            'For Each s In ActiveWorkbook.Sheets
            's.Calculate
            'Next s
            Application.Calculate
            SalesPriceDt = SalesPriceDt.Value
        End If
            Set SalesPrice = Nothing
            Set SalesPriceDt = Nothing

        If UserForm1.CheckBox5.Value = True Then
            Multiples.Table RowInput:=VarExit, ColumnInput:=VarYield
            'For Each s In ActiveWorkbook.Sheets
            's.Calculate
            'Next s
            Application.Calculate
            MultiplesDt = MultiplesDt.Value
        End If
            Set Multiples = Nothing
            Set MultiplesDt = Nothing

        AllYieldsBase.Value = AllYieldsTemp.Value
        AllYieldsTemp.ClearContents

        GlobalExit.Value = BaseExit.Value

            Set AllYieldsBase = Nothing
            Set AllYieldsTemp = Nothing
            Set GlobalExit = Nothing
            Set BaseExit = Nothing


        Sens.Activate

        For Each s In ActiveWorkbook.Sheets
        s.Protect Password:="Whatever", UserInterfaceOnly:=True, DrawingObjects:=False, Contents:=True, Scenarios:=False, _
        AllowFormattingCells:=False, AllowFormattingColumns:=True, AllowFormattingRows:=True, _
        AllowInsertingColumns:=False, AllowInsertingRows:=False, AllowInsertingHyperlinks:=False, _
        AllowDeletingColumns:=False, AllowDeletingRows:=False, AllowSorting:=True, AllowFiltering:=True, _
        AllowUsingPivotTables:=True
        s.EnableOutlining = True
        Next

    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True

    End With

    ActiveSheet.Range("Q2").Select
    ActiveSheet.EnableFormatConditionsCalculation = True
    Application.Cursor = xlDefault
    Application.StatusBar = False

closetime = Time
    t = Format(closetime - OpenTime, "hh:mm:ss")

        MsgBox "Opened at " & Format(OpenTime, "hh:mm:ss") _
        & "    Closed at " & Format(closetime, "hh:mm:ss") & vbCr & vbNewLine & _
        "The calculation took " & t, vbOKOnly, "Calculation Timer"

End Sub

任何想法......?

0 个答案:

没有答案