暂停VBA并重新运行它会导致执行速度加快

时间:2017-06-07 21:45:32

标签: excel vba performance excel-vba

我们有一个宏用于某些分析,因为我们希望能够查看该过程,因为这里的原因超出了范围,我们被迫使用Activate和{{ 1}}在宏中。我和我的同事都意识到使用这种方法的缺点。同时,已经测试了显式编码和避免选择和激活不是主要原因。

在其中一个 子模块 中,我发布了下面的(伪)代码,我们基本上从工作表中获取数据并将其复制到另一个。

问题

问题是这个过程太慢但是当我暂停宏( Esc )时,点击调试,逐步执行( F8 )一个或两个步骤{ {1}}然后再次运行( F5 )它运行得更快。

这不是围绕我的for循环或特定工作表的特定步骤发生的,因此与我的数据及其结构无关。

问题:可能的原因是什么?暂停/步骤运行是否会导致内存清除或任何其他可能使其运行得更快的情况?我如何解决这个问题(让它快速运行而不需要暂停等等。)?

重要提示

如上所述,使用Selectfor-loop并不是减慢进程速度的主要原因。我很抱歉发布此内容,但需要告诉您我知道如何使用显式选项,设置范围,设置值而不是复制等。我已经更改了代码以避免选择并查看是否可以解决问题事实并非如此。它一直运行缓慢,直到暂停,踩踏并再次运行。如果你仔细看看问题并描述问题背后的原因,我将不胜感激。或者至少让我知道为什么这个,我的意思是这个特定的问题将在暂停和再次运行后解决,正在发生以及为什么它与Select有关。

这是整个程序运行的更大主模块的一部分,但这是导致问题的部分。我在主模块中使用了一些优化技术。

Activate

P.S。:我还想知道Select/Activate除了其他应用程序属性之外是否会对我有显着的好处。

P.P.S。请不要提出Sub Copy_ModelInputs(RootDir, FileName, TranID, ModOutDir, Angle, x, y, Method, TypeN) 'For each 150 storms, step through model event tabs and copy into runup tabs FileName = RootDir & "NWM\" & FileName FileName_output = ModOutDir & TranID & "_Outputs.xlsm" Workbooks.Open (FileName) FileName = ActiveWorkbook.Name Workbooks.Open (FileName_output) Filename2 = ActiveWorkbook.Name 'copy the angle into the doc sheet Windows(FileName).Activate Sheets("doc").Select Range("c12").Select ActiveCell.value = Angle 'File Transect ID Range("c6").Select ActiveCell.value = TranID ActiveCell.Offset(1, 0).Select ActiveCell.value = FileName_output Range("I4").Select ActiveCell.value = Now Range("d8").Select ActiveCell.value = x ActiveCell.Offset(0, 2).Select ActiveCell.value = y 'copy model output to input into excel spreadsheets For i = 1 To 150 'input SWELs Windows(Filename2).Activate Sheets("Event" & i).Select Range("B2:B300").Select 'Range(Selection, Selection.End(xlDown)).Select Selection.Copy Windows(FileName).Activate Sheets("Event" & i).Select Range("B7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False 'input H Windows(Filename2).Activate Range("C2:C300").Select 'Range(Selection, Selection.End(xlDown)).Select Selection.Copy 'Open runup template spreadsheet, copy H0 Windows(FileName).Activate Range("D7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False 'input T Windows(Filename2).Activate Range("D2:D300").Select 'Range(Selection, Selection.End(xlDown)).Select Selection.Copy 'Open template Windows(FileName).Activate Range("G7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False If TypeN = 1 Or TypeN = 3 Then 'input deep Windows(Filename2).Activate Range("E2:E300").Select 'Range(Selection, Selection.End(xlDown)).Select Selection.Copy 'Open template Windows(FileName).Activate Range("H7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False End If 'input local Windows(Filename2).Activate 'If Method = 2 Then If TypeN = 2 Then Range("G2:G300").Select Selection.Copy 'Open template Windows(FileName).Activate Range("I7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False 'input model Windows(Filename2).Activate Range("F2:F300").Select Selection.Copy 'Open template Windows(FileName).Activate Range("H7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False 'input length Windows(Filename2).Activate Range("J2:J300").Select Selection.Copy 'Open template Windows(FileName).Activate Range("J7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False 'input data Windows(Filename2).Activate Range("I2:I300").Select Selection.Copy 'Open template Windows(FileName).Activate Range("K7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False End If 'input sheet Windows(Filename2).Activate If TypeN = 3 Then Range("H2:H300").Select Selection.Copy 'Open template Windows(FileName).Activate Range("S7").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False End If Windows(Filename2).Activate Application.StatusBar = "Model Output copied Event " & i Next i ActiveWorkbook.Save ActiveWindow.Close ActiveWorkbook.Save ActiveWindow.Close Sheets("Summary").Select End Sub Application.Cursor = xlWaitSelect Activate参数。它已在上面的行和评论中多次报道过。

2 个答案:

答案 0 :(得分:1)

在问题上花了相当多的时间后,我想报告这个问题;

正如@Slai建议的那样,我试图通过在每个进程之间打印时间来找到代码的瓶颈。事实证明,for循环的每一步之间都存在滞后,然后在Debug/Continue之后消失。

同样Application属性在Debug/Continue之前和之后都没有变化。

关于从立即窗口运行宏的@YowE3K提议实际解决了这个问题。不知何故,似乎激活VBE就是解决方案

我还尝试将我的主工作簿保存为* .xlsb 来解决问题。但是,它会在开始时导致文件加载速度变慢,但总开销时间成本并不大。

我对即时窗口的了解是它的范围不同。如果没有运行,它假定全局(Public)范围。否则,它将在应用程序范围内。如果有人可以添加并详细解释激活VBE与从命令按钮运行宏的方式不同,我将不胜感激。

作为参考,我想在答案中包括不禁用Application.ScreenUpdating会严重影响执行时间。

答案 1 :(得分:1)

我在 Microsoft 365(64 位 Windows 10 专业版、i5 第 9 代处理器、16GB RAM。Excel 文件大小为 4MB,大量使用 VBA。64 位 Excel)时遇到了类似问题。

代码子长度 - 大约 770 行,它调用了几个函数并分支到几个子。

使用 Office 2010(在同一台机器上的 32 位 Excel - 就此而言,在我以前的规格相当低的机器上)时,软件工作/工作正常的问题。

在 MS365 机器上。在运行时,代码会在代码中的随机位置停顿 30 到 300 秒或更长时间,但在调试模式下则不会。

我尝试了所有建议的技巧,例如在代码中的不同位置插入 DoEvent 和添加一两秒的等待。甚至卸载了 MS365 并重新安装了 32 位。

长话短说,我将代码分解成更小的部分,并从原始代码块中调用它们,如下面的示例所示...

Sub xyz()
.....
.....
Call SetDoCalcPages
Call SetDoCalcPages1(r, ACellAddr, errStr, NowStr, errAddr)
Call SetDoCalcPages2(temWatch, fYoung, temYoung, doneonce, fK4, ACellAddr, goQT)
.....
.....
End Sub

大约 70 行代码被转移到上面提到的三个子程序中。

我不能说为什么,但这解决了问题。在运行时,计算速度很快。

有一件事是肯定的。代码激活工作表和单元格并设置颜色和字体 - 许多论坛上的建议都不赞成所有这些。我可以确认这些与症状没有任何关系 - 在运行时执行宏代码时出现随机长停顿。