在VBA中加速嵌套循环macros所需的指针

我需要帮助加快我的直接,8variables,嵌套循环macros。 每个循环仍然需要〜1秒,并有几十万循环完成,所以需要3至4天才能完成! 我在阅读和实验的过程中尽可能地简化了工作,但现在已经遇到了困难。

我的macros观基本上有3个部分。 1)为每个循环上的variables赋值,2)将这些值插入到我的excel模型中进行计算,3)每次迭代将结果粘贴到一个新行上。 我已经定时了每个细分市场,每个细分市场所需的时间分别是(大约)0.4s,0.4s和0.2s。

我大部分与段1)混淆,因为它需要0.4s只是为每个循环的variables赋值。 我接受第2段的缓慢是由于我的Excel电子表格的大小超过了5000行(可能是我的糟糕的Excel编程),3)已经被重新devise(感谢你们在这个论坛上的介绍!比以前快得多。

代码如下:

Sub VariableIteration2() Dim a As Double Dim b As Double Dim c As Double Dim d As Double Dim w As Double Dim x As Double Dim y As Double Dim z As Double Dim Row As Long Dim Results As Variant Dim T1S As Double Dim T1E As Double Dim T2S As Double Dim T2E As Double Dim T3S As Double Dim T3E As Double Dim T4S As Double Dim T4E As Double Dim V1S As Double Dim V1E As Double Dim V2S As Double Dim V2E As Double Dim V3S As Double Dim V3E As Double Dim V4S As Double Dim V4E As Double Dim ST1 As Double Dim ST2 As Double Dim ST3 As Double Dim ST4 As Double Dim SV1 As Double Dim SV2 As Double Dim SV3 As Double Dim SV4 As Double Dim Startime As Single Row = 18 T1S = Range("S3").Value T1E = Range("S4").Value T2S = Range("t3").Value T2E = Range("t4").Value T3S = Range("u3").Value T3E = Range("u4").Value T4S = Range("v3").Value T4E = Range("v4").Value V1S = Range("s6").Value V1E = Range("s7").Value V2S = Range("t6").Value V2E = Range("t7").Value V3S = Range("u6").Value V3E = Range("u7").Value V4S = Range("v6").Value V4E = Range("v7").Value ST1 = Range("s5").Value ST2 = Range("t5").Value ST3 = Range("u5").Value ST4 = Range("v5").Value SV1 = Range("s8").Value SV2 = Range("t8").Value SV3 = Range("u8").Value SV4 = Range("v8").Value 'SEGMENT_1_ASSIGNING_VALUES Startime = Timer For a = V1S To V1E Step SV1 For w = T1S To T1E Step ST1 For b = V2S To V2E Step SV2 For x = T2S To T2E Step ST2 For c = V3S To V3E Step SV3 For y = T3S To T3E Step ST3 For d = V4S To V4E Step SV4 For z = T4S To T4E Step ST4 Range("dy20") = Timer - Startime 'SEGMENT_2_PASTE_VARIABLES_INTO_CALCULATIONS Startime = Timer Range("s19").Value = w Range("s20").Value = a Range("t19").Value = x Range("t20").Value = b Range("u19").Value = y Range("u20").Value = c Range("v19").Value = z Range("v20").Value = d Range("s23:v24").Value = Range("s19:v20").Value Range("dy21") = Timer - Startime 'SEGMENT_3_RECORD_RESULTS Startime = Timer Row = Row + 1 Results = Range("g15:ax15") Range(Cells(Row, 131), Cells(Row, 131 + UBound(Results, 2) - 1)) = Results Range("dy22") = Timer - Startime Next z Next d Next y Next c Next x Next b Next w Next a End Sub 

非常感谢您的帮助。

请记住,每次移动/为工作表上的单元格赋值时,Excel都会停止并重新计算整个工作表。 @乔的链接关掉这个自动计算,而你移动你的数据会给你一些速度提升。 但…

如果您在VBA例程中执行所有计算,而不是将其复制到工作表,并依靠公式来执行计算,则循环速度将会大大加快。 此外,使用基于内存的数组来保存结果可以最大限度地减less你的例程减慢这个副本。 (Chip Pearson对此有非常好的解释。 )

所以我的build议是:

  1. 使用循环variables(w,a,x,…)在VBA例程中执行计算,即将公式移动到您的代码中。
  2. 将结果存储在内存数组Dim results(1 to 44) as Double
  3. 将结果数组直接复制到结果范围的下一个区域(g15:ax15)。
  4. 或者更好的办法是,将这个结果数组附加到另​​一个内存数组Dim allResults(1 to 1000, 1 to 44) as Double – (提示:你不能在一个语句中这样做,你必须循环才能从结果数组放到allResults数组中的下一个槽中)。 然后将块allResults数组复制到您的工作表上的一个范围。

你应该从这些技术中获得巨大的速度提升。

设置属性或调用方法时,每个函数都是CPU中的函数调用。 这意味着堆栈设置开销。 函数调用比内联代码慢。 出于同样的原因,在VBA中使用循环而不是函数。

首先不要一遍又一遍地指定所有这些属性。 除非你改变它们,否则它们不会改变。

 With Selection.Find .ClearFormatting .Replacement.ClearFormatting .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchByte = False .MatchAllWordForms = False .MatchSoundsLike = False .MatchWildcards = False .MatchFuzzy = False For loop to go through each word pair .Text = SrcText .Replacement.Text = DestText .Find.Execute Replace:=wdReplaceAll Next End With 

最小化点

所以如果你对性能感兴趣,最小化点(每个点都是查找),特别是在循环中。

有两种方法。 一个是设置对象到最低的对象,如果你要访问不止一次。

例如(较慢)

 set xlapp = CreateObject("Excel.Application") msgbox xlapp.worksheets(0).name 

(更快,因为每次使用对象时都省略一个点)

 set xlapp = CreateObject("Excel.Application") set wsheet = xlapp.worksheets(0) msgbox wsheet.name 

第二种方式是与。 一次只能有一个活动。

这跳过了100个查找。

 with wsheet For x = 1 to 100 msgbox .name Next end with 

stringConcatination

一次不要join一个string。 用string连接小string然后连接现在较大的string。 你可以使用MID 语句 (不是mid函数),就像string生成器一样。

读取属性

不要重新读取不会改变的属性,特别是在过程或迟到时。 把它们变成一个variables。 与对象查找(这也是一个函数调用,或者至less两个,如果是延迟的)相比,读取variables是快速的,然后是函数调用。

variables

常量和文字在编译后几乎相同。

 Const x = 5 msgbox x 

是相同的

 msgbox 5 

文字直接插入代码中。 string和对象variables有pipe理器,导致开销。 避免无缘无故地创buildvariables。 这是一个毫无意义和缓慢的variables的例子。

 x = "This is a string" msgbox x 

相比

 const x = "This is a string" msgbox x 

要么

 msgbox "This is a string" 

对象types

这里有两个概念 – 过程中和早期或晚期的约束。

exefiles连接到进程外。 所有的调用都通过RPC(一个networking协议)进行编组。 Dllfiles正在处理,函数调用直接跳转。

早期绑定set x = objecttype 。 编写程序时会查找函数。 在执行时,程序被硬编码以跳转到存储在该函数的vtable中的地址。

后期绑定设置为x = createobject("objecttype") 。 每个函数调用都是这样的。 “你好对象,你有一个打印命令”。 “是”,它回复“3号命令”。 “嗨对象,你可以请指挥3号”。 “当然,这是结果”。

从Visual Basic概念(帮助的一部分)

通过优化Visual Basicparsing对象引用的方式,可以使Visual Basic应用程序运行得更快。 Visual Basic处理对象引用的速度可能会受到以下影响:

ActiveX组件是否被实现为进程内服务器或进程外服务器。

对象引用是早期绑定还是后期绑定。 一般情况下,如果某个组件是作为可执行文件(.exe文件)的一部分实现的,则它是一个进程外服务器,并在其自己的进程中运行。 如果已经作为dynamic链接库实现,则它是一个进程内服务器,并且与客户端应用程序在相同的进程中运行。

使用进程内服务器的应用程序通常比使用进程外服务器的应用程序运行得更快,因为应用程序不必跨越进程边界来使用对象的属性,方法和事件。 有关进程内和进程外服务器的详细信息,请参阅“进程内和进程外服务器”。

如果对象引用使用作为特定类的variables声明的对象variables,则它们是早期绑定的。 如果对象引用使用作为generics对象类的variables声明的对象variables,则对象引用是迟到的。 使用早期绑定variables的对象引用通常比使用后期绑定variables的对象引用运行得更快。

Excel的具体

查看来自Microsoft人员的链接。 这是特定的而不是VBA。 Autocalc和其他计算选项/屏幕更新等

http://blogs.office.com/2009/03/12/excel-vba-performance-coding-best-practices/

屏幕更新和自动计算可以降低性能。

这在这里详细解释。