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

时间:2015-04-13 00:55:25

标签: excel vba

我需要帮助加速我的直接,8变量,嵌套循环宏。每个循环仍然需要大约1秒钟,并且有几十个循环完成所以需要3到4天才能完成!从我在这里的阅读和实验中我已经做了尽可能多的精简,但现在已经碰壁了。

我的宏基本上有3个细分。 1)为每个循环上的变量赋值,2)将这些值插入到我的excel模型中以执行计算,以及3)每次将每次迭代的结果粘贴到新行上。我为每个片段定时,每个片段所需的时间分别为(约)0.4s,0.4s和0.2s。

我主要与段1混淆,因为只需要为每个循环上的变量赋值0.4s。我接受了这一段2)的缓慢是因为我的excel电子表格大小为5,000行(可能是我的糟糕excel编程)和3)已经重组(感谢你们在这个论坛上!)和比以前快很多。

以下是代码:

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

非常感谢你的帮助。

3 个答案:

答案 0 :(得分:2)

设置属性或调用方法时,每个都是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

字符串Concatination

并且不要一次加入一个字符串。使用字符串连接小字符串然后连接现在更大的字符串。您可以使用类似字符串构建器的MID 语句(非mid函数)。

阅读属性

不要重读不会发生变化的属性,尤其是在进程外或后期绑定时。把它们放入一个变量中。与对象查找(也是函数调用,或者如果是后期绑定至少两个)相比,读取变量很快,然后是函数调用。

<强>变量

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

Const x = 5
msgbox x

相同
msgbox 5

直接在代码中插入文字。字符串和对象变量具有管理器,增加了开销。避免无缘无故地创建变量。这是一个无意义和慢变量的例子。

x = "This is a string"
msgbox x

相比
const x = "This is a string"
msgbox x

msgbox "This is a string"

对象类型

这里有两个概念 - 进程内外或早期或晚期绑定。

exefiles连接到进程外。所有调用都通过RPC(网络协议)进行编组。 Dllfiles正在进行中,函数调用是直接跳转的。

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

后期绑定设置为x = createobject("objecttype")。每个函数调用都是这样的。 &#34;你好对象你有打印命令&#34;。 &#34;是&#34;,它回复,&#34;命令编号3&#34;。 &#34;嗨,对象可以请你做第3和第34号命令。 &#34;当然,结果是&#34;。

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

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

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

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

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

如果对象引用使用声明为特定类的变量的对象变量,则它们是早期绑定的。如果对象引用使用声明为通用Object类的变量的对象变量,则它们是后期绑定的。使用早期绑定变量的对象引用通常比使用后期绑定变量的对象引用运行得快。

Excel特定

请参阅Microsoft人员的此链接。这是excel特定而不是VBA。 Autocalc和其他计算选项/屏幕更新等。

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

答案 1 :(得分:1)

请记住,每次移动/为工作表上的单元格指定值时,Excel都会停止并重新计算整个工作表。 @ Joe的链接在您移动数据时关闭此自动计算将为您提供一些速度提升。但...

如果您在VBA例程中执行所有计算而不是将它们复制到工作表并依赖公式来执行计算,那么您的循环将会极大地加速。此外,使用基于内存的数组来保存结果可以最大程度地减少您的例程对此副本的减速程度。 (Chip Pearson有very good explanation of this.

所以我的建议:

  1. 使用循环变量(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数组块复制到工作表上的Range。
  5. 你应该从这些技术中获得很大的速度提升。

答案 2 :(得分:0)

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

详细解释here