为什么激活特定工作表会影响我的宏的运行时间

问题描述 投票:2回答:2

为简洁/正确而编辑:滚动至TL / DR的末尾

我运行了一个相当长的宏,它从Workspace / Sharepoint打开一堆文件,将其复制到我的Excel工作表中,将数据加载到数组中,比较数组项,将数据写入工作表等。它使用PowerPivot和Power Query读取/在几本工作簿的几张纸上写东西。

在寻找代码优化选项期间,我发现使用以下行激活工作表可以使我的代码运行速度提高3倍。我想弄清楚为什么以及如何避免将来的这种放缓。

ThisWorkbook.Sheets("Dashboard").Activate

我还将“仪表板”更改为另一个新添加的,完全为空的工作表(sheets(15)),并且对运行时间没有影响,这意味着运行时间不会快3倍。我认为,在活动表上工作会产生一些效果。但是不,激活新的,空的和未使用的表并不能使代码更快。我使用以下宏增强功能:

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

我不在代码中的其他任何地方使用.activate。 (我具体是cntrl + f)。 .activate就在一个长的For-Loop之前,后者会调用其他3个子。在下图中,您可以看到循环的运行时间。

See the image for some run times in seconds

图中的开始是指分配一些变量等所用的时间。工具,序列号等是循环期间运行的子程序。这些数字是循环中所有步骤的总和,该循环通常具有大约300ish的步骤,可能需要从0s到0.3s。

以下是代码的一部分。我将发布For-Loop和“ check_others”子程序以及它调用的子程序。这是最短的子程序,但是如您在上图中所见,即使该子程序也已生效,所以发生的事情似乎并不只影响一个子程序。为了便于阅读,我还删除了定时循环的代码。

'Go from first row of the Prisma report to the last row. (Reference WITHIN the pivot table. e.g: 1 is absolut row 6)
RowCount = ThisWorkbook.Sheets("Prisma").PivotTables("OperationData").DataBodyRange.Rows.Count
PrismaArr = ThisWorkbook.Sheets("Prisma").Range("H6:U" & RowCount + 5)

'It is unclear why and how but without this line, the code takes 3x longer to execute.
ThisWorkbook.Sheets("Dashboard").Activate

For Prismarow = 1 To RowCount

    'Set some of the most used variables and progres bar. (Indicator, Comment, Instruction)
    progress 13 + (Prismarow / RowCount) * 82, "Analizing"
    IndicatorSkipFurtherAnalyses = 0
    CommentToBeAnalysed = PrismaArr(Prismarow, 5)
    InspectionInstruction = PrismaArr(Prismarow, 6)


'#7     G - Check Tools
        Call Check_Tools(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction)

'#8     H - Check serial numbers
        If Not IndicatorSkipFurtherAnalyses Like "1" Then _
        Call Check_Serial_Numbers(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction)

'#9     I - Check for others (everything else)
        If Not IndicatorSkipFurtherAnalyses Like "1" Then _
        Call Check_Others(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction)

SkipThisEntry:
Next

调用Check_Others(PrismaArr,Prismarow,CommentToAnalyded,InspectionInstruction):

Sub Check_Others(ByVal PrismaArr, ByVal Prismarow As Long, ByVal CommentToBeAnalysed As String, ByVal InspectionInstruction As String)

'Check if the entry was already deleted, ignore it otherwise
If Not PrismaArr(Prismarow, 7) Like "E D" Then


    'Check that all entries on the PDF which are not tools or serial numbers are empty
    If PrismaArr(Prismarow, 13) Like "2" And PrismaArr(Prismarow, 10) Like "FALSCH" And PrismaArr(Prismarow, 11) Like "FALSCH" Then
        If Not CommentToBeAnalysed Like "" Then
        Call Fill_Out_Others_Analysis(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction, 5)
        End If
    End If

    'Check if there should have been a serial number here
    If PrismaArr(Prismarow, 10) Like "WAHR" And CommentToBeAnalysed Like "" Then
        Call Fill_Out_Others_Analysis(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction, 19)
    End If

    'Check if there should have been a tool number here
    If PrismaArr(Prismarow, 11) Like "WAHR" And CommentToBeAnalysed Like "" Then
        Call Fill_Out_Others_Analysis(PrismaArr, Prismarow, CommentToBeAnalysed, InspectionInstruction, 18)
    End If

End If
End Sub

调用Fill_Out_Others_Analysis(PrismaArr,Prismarow,CommentToBeAnalysed,InspectionInstruction,5):

Sub Fill_Out_Others_Analysis(ByVal PrismaArr, _
    ByVal Prismarow As Long, _
    ByVal CommentToBeAnalysed As String, _
    ByVal InspectionInstruction As String, _
    ByVal Error_Code As String)

'Write the given information into the analysis sheet
    With ThisWorkbook.Sheets("Analysis").ListObjects("Analysis_Others").ListRows.Add
        .Range.ClearFormats
        .Range(1, 1) = PrismaArr(Prismarow, 1)
        .Range(1, 2) = Prismarow + 5 & " (" & PrismaArr(Prismarow, 2) & ")"
        .Range(1, 3) = CommentToBeAnalysed
        .Range(1, 4) = InspectionInstruction
        .Range(1, 6) = "----"
        .Range(1, 7) = "----"
        .Range(1, 8) = "----"
        .Range(1, 9) = "----"
        .Range(1, 10) = "----"
        .Range(1, 11) = "----"

        'Assign errors, including coloring and statistical error assignment
        Call AssignError(Error_Code, .Range)
    End With

End Sub

此时,它称为“ AssignError”,该时间太长了,无法真正发布。但是,即使我注释掉该Call,也仍然可以通过使用.activate来加速宏。

另外,如果我启动宏,然后在打开和关闭excel工作表以收集数据时也可以类似地加快宏的速度,但是在For-Loop启动之前,请单击excel。我只需单击Windows按钮并保持开始菜单为打开状态,而我看到进度条的填充速度比平时快3倍。实际上,这甚至具有更好的性能,即使我额外使用.activate约20%(16s-> 13s),也可以加快程序运行速度。这并不令我感到惊讶。但是对于.activate行为,我只是没有任何解释。

有人可以理解吗?

TL / DR:是否有人知道宏中间的worksheet.activate如何将执行速度提高3倍。添加worksheet.activate使我的代码以其他方式所需的时间完成运行的1/3。

谢谢丹尼斯

excel vba
2个回答
1
投票

但是,我也有很多想法。


0
投票

您有电话要计算吗?我想知道您是否只是在进行一些计算或其他操作,而ThisWorkbook.Sheets(“ Dashboard”)。Activate可能会中断它,从而使宏更快地完成。

© www.soinside.com 2019 - 2024. All rights reserved.