Optimizing VBA 

This page lists some suggestions and strategies for optimizing your Visual Basic For Applications (VBA) code, so that it will run faster.   There are few absolute rules for optimizing VBA;  you'll see the best increases in performance by streamlining the basic logic.


        

Accessing Cells In A Range


You do not need to use the .Cells method to access specific cells in a range.  For example, you can use

Range("MyRange")(1,2)   rather than
Range("MyRange").Cells(1,2)


See Alan Beban's explanation of this method for more details.

Related to this is the shortcut method of refering to cells.  VBA will allow you reference cells with [A1] rather than Range("A1"). While the [A1] syntax is easier to type, it is slower to execute than the Range("A1") syntax.

 

Calculation Mode


Normally, Excel will recalculate a cell or a range of cells when that cell's or range's precedents have changed.  This may  cause your workbook to recalculate too often, which will slow down performance.  You can prevent Excel from recalculating the workbook by using the statement:

Application.Calculation = xlCalculationManual

At the end of your code, you can set the calculation mode back to automatic with the statement:

Application.Calculation = xlCalculationAutomatic

Remember, though, that when the calculation mode is xlCalculationManual, Excel doesn't update values in cells.  If your macro relies on an updated cell value, you must force a Calculate event, with the .Calculate method, which may be applied to either a specific range (Range("MyRange").Calculate) or to the entire workbook (Calculate).

 

Collection Indexes


An individual item of a collection object may be accessed by either its name or by its index into the collection.  For example, if you have three worksheets ("Sheet1", "Sheet2", and "Sheet3")  in a workbook ("MyWorkbook"), you can reference "Sheet2" with either

Worksheets("Sheet2")  or
Worksheets(2)

In general, the index number method (Worksheets(2)) is considerably faster than the index name method (Worksheets("Sheet2")).

However, the number and order of items in a collection may change, so it is usually safer and easier to refer to items in a collection by their name, rather than their index number.

Constants


Whenever you can, declare values as constants, rather than variables.   Since their values never change, they are evaluated only once when your code is compiled, rather than each time they are used at run time.

 

Early Binding


This is closely tied with Specific Object Type Declaration.  If you're going to work with another application, such as Word, declare your OLE object directly, rather than as an Object type variable.  By doing so, a great deal of overhead is done at compile time ("Early Binding") rather than at run time ("Late Binding").   For example, use

Dim WordObj As Word.Application        rather than
Dim WordObj As Object

Also see Using Variables (Properly) In VBA.

FOR EACH Loops


When looping through a collection it is usually faster than the FOR EACH statement rather than using the index.  For example, the first code loop is faster than the second:

Dim WS as Worksheet
For Each WS In Worksheets
    MsgBox WS.Name
Next WS

Dim i as Integer
For i = 1 To Worksheets.Count
    MsgBox Worksheets(i).Name
Next i

 

Range Objects Not Selection Object


Generally, it is not necessary to select a range before working with it.  For example, it is more efficient to use

Range("A1").Font.Bold = True


Rather than

Range("A1").Select
Selection.Font.Bold = True

 

Screen Updating


You can turn off screen updating so that Excel does not update the screen image as your code executes.  This can greatly speed up your code.

Application.ScreenUpdating = FALSE

Be sure to restore the setting to True at the end of your macro.  Older version of Excel would automatically restore the setting; Excel97 does not.

 

Simple Objects Rather Than Compound Objects


If you've got to make repeated references to an object, such a range, declare an object of that type, set it to the target object, and then use your object to refer to the target.   For example,

Dim MyCell As Range
Set MyCell = Workbooks("Book2").Worksheets("Sheet3").Range("C3")
'....
MyCell.Value = 123


By referring directly to MyCell , VBA can access the object directly, rather than resolving the complete path to the object each time.  This method is useful only when you are accessing an object several times during code execution.

 

Specific Object Type Declaration


If possible avoid using the Object or Variant data types.  These data types require considerable overhead to determine their types.  Instead, use explicit data types, such as

Dim MySheet As Worksheet
  rather than
Dim MySheet As Object 
Or
Dim NumRows As Long rather than
Dim NumRows As Variant

This is especially true with index variables in For Next loops, since a Variant type has to be re-evaluated each iteration of the loop.

Also see Using Variables (Properly) In VBA.

 

WITH Statements


If you are using several statement in a row that apply to the same object, use a WITH statement, rather than fully qualifying the object each time.  For example,

With Worksheets("Sheet1").Range("A1")
    .Font.Bold = True
    .Value = 123
End With



Worksheet Functions


You can use Excel's standard worksheet functions in your VBA code, rather than writing the functions in VBA.  Since these are fully executable instructions in native code, rather than interpreted VBA code, they run much faster.  For example, use

MySum = Application.WorksheetFunction.Sum(Range("A1:A100"))   

rather than

For Each C In Range("A1:A100")
    MySum = MySum + C.Value
Next C