VBA-Docs - Excel-Tips-For-Optimizing-Performance-Obstructions - MD at Main MicrosoftDocs - VBA-Docs GitHub
VBA-Docs - Excel-Tips-For-Optimizing-Performance-Obstructions - MD at Main MicrosoftDocs - VBA-Docs GitHub
Follow these tips for optimizing many frequently occurring performance obstructions in Excel.
Excel calculates circular references sheet-by-sheet without considering dependencies. Therefore, you
usually get slow calculation if your circular references span more than one worksheet. Try to move the
circular calculations onto a single worksheet or optimize the worksheet calculation sequence to avoid
unnecessary calculations.
Before the iterative calculations start, Excel must recalculate the workbook to identify all the circular
references and their dependents. This process is equal to two or three iterations of the calculation.
After the circular references and their dependents are identified, each iteration requires Excel to
calculate not only all the cells in the circular reference, but also any cells that depend on the cells in
the circular reference chain, together with volatile cells and their dependents. If you have a complex
calculation that depends on cells in the circular reference, it can be faster to isolate this into a separate
closed workbook and open it for recalculation after the circular calculation has converged.
It's important to reduce the number of cells in the circular calculation and the calculation time that is
taken by these cells.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 1/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Using fewer larger workbooks is usually, but not always, better than using many smaller workbooks.
Some exceptions to this might be when you have many front-end calculations that are so rarely
recalculated that it makes sense to put them in a separate workbook, or when you have insufficient
RAM.
Try to use simple direct cell references that work on closed workbooks. By doing this, you can avoid
recalculating all your linked workbooks when you recalculate any workbook. Also, you can see the
values Excel has read from the closed workbook, which is frequently important for debugging and
auditing the workbook.
If you cannot avoid using linked workbooks, try to have them all open instead of closed, and open the
workbooks that are linked to before you open the workbooks that are linked from.
You can check the visible used range on a worksheet by using Ctrl+End. Where this is excessive, you
should consider deleting all the rows and columns below and to the right of your real last used cell,
and then saving the workbook. Create a backup copy first. If you have formulas with ranges that
extend into or refer to the deleted area, these ranges will be reduced in size or changed to #N/A.
You can do this by using a large range in your formulas that extends well beyond your current data
boundaries. However, this can cause inefficient calculation under certain circumstances, and it is
difficult to maintain because deleting rows and columns can decrease the range without you noticing.
Starting in Excel 2007, you can use structured table references, which automatically expand and
contract as the size of the referenced table increases or decreases.
Fewer performance disadvantages exist than the alternatives of whole column referencing and
dynamic ranges.
Formulas that are embedded in the table also expand and contract with the data.
Many Excel built-in functions (SUM, SUMIF) calculate whole column references efficiently because
they automatically recognize the last used row in the column. However, array calculation functions
like SUMPRODUCT either cannot handle whole column references or calculate all the cells in the
column.
User-defined functions don't automatically recognize the last-used row in the column and,
therefore, frequently calculate whole column references inefficiently. However, it is easy to
program user-defined functions so that they recognize the last-used row.
It's difficult to use whole column references when you have multiple tables of data on a single
worksheet.
In Excel 2007 and later versions, array formulas can handle whole-column references, but this
forces calculation for all the cells in the column, including empty cells. This can be slow to
calculate, especially for 1 million rows.
=OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),1)
=Sheet1!$A$1:INDEX(Sheet1!$A:$A,COUNTA(Sheet1!$A:$A)+ROW(Sheet1!$A$1) - 1,1)
When you use the dynamic range name in a formula, it automatically expands to include new entries.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 3/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Performance decreases because the COUNTA function inside the dynamic range formula must
examine many rows. You can minimize this performance decrease by storing the COUNTA part of the
formula in a separate cell or defined name, and then referring to the cell or name in the dynamic
range:
Counts!z1=COUNTA(Sheet1!$A:$A)
OffsetDynamicRange=OFFSET(Sheet1!$A$1,0,0,Counts!$Z$1,1)
IndexDynamicRange=Sheet1!$A$1:INDEX(Sheet1!$A:$A,Counts!$Z$1+ROW(Sheet1!$A$1) - 1,1)
You can also use functions such as INDIRECT to construct dynamic ranges, but INDIRECT is volatile
and always calculates single-threaded.
Dynamic ranges work well to limit the number of calculations performed by array formulas.
Using multiple dynamic ranges within a single column requires special-purpose counting
functions.
That said, for earlier Excel versions, Lookups continue to be frequently significant calculation
obstructions. Fortunately, there are many ways of improving lookup calculation time. If you use the
exact match option, the calculation time for the function is proportional to the number of cells
scanned before a match is found. For lookups over large ranges, this time can be significant.
Lookup time using the approximate match options of VLOOKUP, HLOOKUP, and MATCH on sorted
data is fast and is not significantly increased by the length of the range you are looking up.
Characteristics are the same as binary search.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 4/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
The following code example shows the syntax for the MATCH function. For more information, see
the Match method of the WorksheetFunction object.
Matchtype=1 returns the largest match less than or equal to the lookup value when the lookup
array is sorted ascending (approximate match). If the lookup array is not sorted ascending,
MATCH will return an incorrect answer. The default option is approximate match sorted ascending.
Matchtype=0 requests an exact match and assumes that the data is not sorted.
Matchtype=-1 returns the smallest match greater than or equal to the lookup value if the lookup
array is sorted descending (approximate match).
The following code example shows the syntax for the VLOOKUP and HLOOKUP functions. For more
information, see the VLOOKUP and HLOOKUP methods of the WorksheetFunction object.
Range-lookup=TRUE returns the largest match less than or equal to the lookup value
(approximate match). This is the default option. Table array must be sorted ascending.
Avoid performing lookups on unsorted data where possible because it is slow. If your data is sorted,
but you want an exact match, see Use two lookups for sorted data with missing values.
It's easy to convert VLOOKUP to INDEX and MATCH. The following two statements return the same
answer:
VLOOKUP(A1, Data!$A$2:$F$1000,3,False)
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 5/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
INDEX(Data!$A$2:$F$1000,MATCH(A1,$A$1:$A$1000,0),3)
Speed up lookups
Because exact match lookups can be slow, consider the following options for improving performance:
Use one worksheet. It's faster to keep lookups and data on the same sheet.
When you can, SORT the data first (SORT is fast), and use approximate match.
When you must use an exact match lookup, restrict the range of cells to be scanned to a
minimum. Use tables and structured references or dynamic range names rather than referring to a
large number of rows or columns. Sometimes you can pre-calculate a lower-range limit and
upper-range limit for the lookup.
If you can sort your data but still cannot use approximate match because you cannot be sure that the
value you are looking up exists in the lookup range, you can use this formula:
IF(VLOOKUP(lookup_val ,lookup_array,1,True)=lookup_val, _
VLOOKUP(lookup_val, lookup_array, column, True), "notexist")
The first part of the formula works by doing an approximate lookup on the lookup column itself.
VLOOKUP(lookup_val ,lookup_array,1,True)
You can check if the answer from the lookup column is the same as the lookup value (in which case
you have an exact match) by using the following formula:
IF(VLOOKUP(lookup_val ,lookup_array,1,True)=lookup_val,
If this formula returns True, you have found an exact match, so you can do the approximate lookup
again, but this time, return the answer from the column you want.
If the answer from the lookup column did not match the lookup value, you have a missing value, and
the formula returns "notexist".
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 6/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Be aware that if you look up a value smaller than the smallest value in the list, you receive an error. You
can handle this error by using IFERROR, or by adding a small test value to the list.
In earlier versions, a simple but slow way is to use an IF function that contains two lookups.
IF(ISNA(VLOOKUP(lookupval,table,2,FALSE)),0,_
VLOOKUP(lookupval,table,2,FALSE))
You can avoid the double exact lookup if you use exact MATCH once, store the result in a cell, and
then test the result before doing an INDEX.
In A1 =MATCH(lookupvalue,lookuparray,0)
In B1 =IF(ISNA(A1),0,INDEX(tablearray,A1,column))
If you cannot use two cells, use COUNTIF. It's generally faster than an exact match lookup.
IF (COUNTIF(lookuparray,lookupvalue)=0, 0, _
VLOOKUP(lookupval, table, 2 FALSE))
Use MATCH and INDEX for exact match lookups on multiple columns
You can often reuse a stored exact MATCH many times. For example, if you are doing exact lookups on
multiple result columns, you can save time by using one MATCH and many INDEX statements rather
than many VLOOKUP statements.
Add an extra column for the MATCH to store the result ( stored_row ), and for each result column use
the following:
INDEX(Lookup_Range,stored_row,column_number)
Alternatively, you can use VLOOKUP in an array formula. (Array formulas must be entered by using
Ctrl+-Shift+Enter. Excel will add the { and } to show you that this is an array formula).
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 7/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
{VLOOKUP(lookupvalue,{4,2},FALSE)}
{INDEX($A$1:$J$1000,stored_row,0)}
This returns column A to column J from the stored row created by a previous MATCH statement.
It's often more efficient to calculate a subset range for the lookup (for example, by finding the first and
last row for the country, and then looking up the product within that subset range).
If each table that you want to look up (the third dimension) is stored as a set of named structured
tables, range names, or as a table of text strings that represent ranges, you might be able to use
the CHOOSE or INDIRECT functions.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 8/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
INDEX(CHOOSE(TableLookup_Value,TableName1,TableName2,TableName3), _
MATCH(RowLookup_Value,$A$2:$A$1000),MATCH(colLookup_value,$B$1:$Z$1))
The following example uses the INDIRECT function and TableLookup_Value to dynamically create
the sheet name to use for the lookup table. This method has the advantage of being simple and
able to handle a large number of tables. Because INDIRECT is a volatile single-threaded function,
the lookup is single-thread calculated at every calculation even if no data has changed. Using this
method is slow.
You could also use the VLOOKUP function to find the name of the sheet or the text string to use
for the table, and then use the INDIRECT function to convert the resulting text into a range.
INDEX(INDIRECT(VLOOKUP(TableLookup_Value,TableOfTAbles,1)),MATCH(RowLookup_Value,$A$2:$A$
Another technique is to aggregate all your tables into one giant table that has an additional column
that identifies the individual tables. You can then use the techniques for multiple-index lookup shown
in the previous examples.
The key to optimizing the calculation speed of array formulas is to ensure that the number of cells and
expressions that are evaluated in the array formula is as small as possible. Remember that an array
formula is a bit like a volatile formula: if any one of the cells that it references has changed, is volatile,
or has been recalculated, the array formula calculates all the cells in the formula and evaluates all the
virtual cells it needs to do the calculation.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 9/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Take expressions and range references out of the array formulas into separate helper columns and
rows. This makes much better use of the smart recalculation process in Excel.
Do not reference complete rows, or more rows and columns than you need. Array formulas are
forced to calculate all the cell references in the formula even if the cells are empty or unused. With
1 million rows available starting in Excel 2007, an array formula that references a whole column is
extremely slow to calculate.
Starting in Excel 2007, use structured references where you can to keep the number of cells that
are evaluated by the array formula to a minimum.
In versions earlier than Excel 2007, use dynamic range names where possible. Although they are
volatile, it is worthwhile because they minimize the size of the ranges.
Be careful with array formulas that reference both a row and a column: this forces the calculation
of a rectangular range.
In versions earlier than Excel 2007, array formulas are often used to calculate a sum with multiple
conditions. This is relatively easy to do, especially if you use the Conditional Sum Wizard in Excel, but
it is often slow. Usually there are much faster ways of getting the same result. If you have only a few
multiple-condition SUMs, you may be able to use the DSUM function, which is much faster than the
equivalent array formula.
If you must use array formulas, some good methods of speeding them up are as follows:
Use dynamic range names or structured table references to minimize the number of cells.
Split out the multiple conditions into a column of helper formulas that return True or False for
each row, and then reference the helper column in a SUMIF or array formula. This might not
appear to reduce the number of calculations for a single array formula; however, most of the time
it enables the smart recalculation process to recalculate only the formulas in the helper column
that need to be recalculated.
Consider concatenating together all the conditions into a single condition, and then using SUMIF.
If the data can be sorted, count groups of rows and limit the array formulas to looking at the
subset groups.
These functions evaluate each of the conditions from left to right in turn. Therefore, it is more efficient
to put the most restrictive condition first, so that subsequent conditions only need to look at the
smallest number of rows.
SUMPRODUCT(--(Condition1),--(Condition2),RangetoSum)
Note that the size and shape of the ranges or arrays that are used in the conditional expressions and
range to sum must be the same, and they cannot contain entire columns.
You can also directly multiply the terms inside SUMPRODUCT rather than separate them by commas:
SUMPRODUCT((Condition1)*(Condition2)*RangetoSum)
This is usually slightly slower than using the comma syntax, and it gives an error if the range to sum
contains a text value. However, it is slightly more flexible in that the range to sum may have, for
example, multiple columns when the conditions have only one column.
{=SUM($D$2:$D$10301*$E$2:$E$10301)}
=SUMPRODUCT($D$2:$D$10301*$E$2:$E$10301)
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 11/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
=SUMPRODUCT($D$2:$D$10301,$E$2:$E$10301)
These three formulas all produce the same result, but the third formula, which uses the comma syntax
for SUMPRODUCT, takes only about 77 percent of the calculation time that the other two formulas
need.
If you find a calculation obstruction that involves array formulas and range functions, you should look
for the following:
Array formulas and range functions that reference part of a block of cells that are calculated in
another array formula or range function. This situation can frequently occur in time series analysis.
One set of formulas referencing by row, and a second set of formulas referencing the first set by
column.
A large set of single-row array formulas covering a block of columns, with SUM functions at the
foot of each column.
VBA and Automation user-defined functions (UDFs), but XLL-based UDFs can be multi-threaded
PHONETIC
CELL when either the "format" or "address" argument is used
INDIRECT
GETPIVOTDATA
CUBEMEMBER
CUBEVALUE
CUBEMEMBERPROPERTY
CUBESET
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 12/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
CUBERANKEDMEMBER
CUBEKPIMEMBER
CUBESETCOUNT
ADDRESS where the fifth parameter (the sheet_name ) is given
Any database function (DSUM, DAVERAGE, and so on) that refers to a PivotTable
ERROR.TYPE
HYPERLINK
You can often reduce the number of volatile functions by using INDEX instead of OFFSET,
and CHOOSE instead of INDIRECT. However, OFFSET is a fast function and can often be used in
creative ways that give fast calculation.
The performance of VBA user-defined functions is sensitive to how you program and call them.
Ensure that you have put all the references to worksheet cells in the user-defined function input
parameters instead of in the body of the user-defined function, so that you can avoid
adding Application.Volatile unnecessarily.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 13/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
If you must have many formulas that use user-defined functions, ensure that you are in manual
calculation mode, and that the calculation is initiated from VBA. VBA user-defined functions calculate
much more slowly if the calculation is not called from VBA (for example, in automatic mode or when
you press F9 in manual mode). This is particularly true when the Visual Basic Editor (Alt+F11) is open
or has been opened in the current Excel session.
You can trap F9 and redirect it to a VBA calculation subroutine as follows. Add this subroutine to
the Thisworkbook module.
Sub Recalc()
Application.Calculate
MsgBox "hello"
End Sub
User-defined functions in Automation add-ins (Excel 2002 and later versions) don't incur the Visual
Basic Editor overhead because they don't use the integrated editor. Other performance characteristics
of Visual Basic 6 user-defined functions in Automation add-ins are similar to VBA functions.
If your user-defined function processes each cell in a range, declare the input as a range, assign it to a
variant that contains an array, and loop on that. If you want to handle whole column references
efficiently, you must make a subset of the input range, dividing it at its intersection with the used
range, as in this example.
If your user-defined function is using worksheet functions or Excel object model methods to process a
range, it is generally more efficient to keep the range as an object variable than to transfer all the data
from Excel to the user-defined function.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 14/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
If your user-defined function is called early in the calculation chain, it can be passed as uncalculated
arguments. Inside a user-defined function, you can detect uncalculated cells by using the following
test for empty cells that contain a formula:
A time overhead exists for each call to a user-defined function and for each transfer of data from Excel
to VBA. Sometimes one multi-cell array formula user-defined function can help you minimize these
overheads by combining multiple function calls into a single function with a multi-cell input range that
returns a range of answers.
Use wildcard SUMIF, COUNTIF, SUMIFS, COUNTIFS, and other IFS functions
Use the wildcard characters ? (any single character) and * (no character or any number of characters) in
the criteria for alphabetical ranges as part of the SUMIF, COUNTIF, SUMIFS, COUNTIFS, and
other IFS functions.
You can create a formula in column B such as =SUM($A$1:$A2) and drag it down as far as you
need. The beginning cell of the SUM is anchored in A1, but because the finishing cell has a
relative row reference, it automatically increases for each row.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 15/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
You can create a formula such as =$A1 in cell B1 and =$B1+$A2 in cell B2 and drag it down as far
as you need. This calculates the cumulative cell by adding this row's number to the previous
cumulative SUM.
For 1,000 rows, the first method makes Excel do about 500,000 calculations, but the second method
makes Excel do only about 2,000 calculations.
2. Add the counts cumulatively for each block to determine its start row.
3. Use OFFSET with the start row and count to return a subset range to the SUM or SUMIF that
covers only the subset block of rows.
Hidden rows that result from filtering a list. Starting in Excel 2003, you can also
make SUBTOTAL ignore all hidden rows, not just filtered rows.
Other SUBTOTAL functions.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 16/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
The following functionality can usually be turned off while your VBA macro executes:
[!IMPORTANT] Remember to restore this functionality to its original state after your code
executes.
The following example shows the functionality that you can turn off while your VBA macro executes.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 17/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
statusBarState = Application.DisplayStatusBar
calcState = Application.Calculation
eventsState = Application.EnableEvents
' Note: this is a sheet-level setting.
displayPageBreakState = ActiveSheet.DisplayPageBreaks
The following code example shows non-optimized code that loops through cells one at a time to get
and set the values of cells A1:C10000. These cells don't contain formulas.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 18/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
' Write the values back into the Excel grid 30,000 times.
DataRange(Irow,Icol)=MyVar
End If
Next Icol
Next Irow
The following code example shows optimized code that uses an array to get and set the values of cells
A1:C10000 all at the same time. These cells don't contain formulas.
Use .Value2 rather than .Value or .Text when reading data from an Excel range
.Text returns the formatted value of a cell. This is slow, can return ### if the user zooms, and can
lose precision.
.Value returns a VBA currency or VBA date variable if the range was formatted as Date or
Currency. This is slow, can lose precision, and can cause errors when calling worksheet functions.
.Value2 is fast and does not alter the data being retrieved from Excel.
The following code example shows non-optimized code that selects each Shape on the active sheet
and changes the text to "Hello".
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 19/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
For i = 0 To ActiveSheet.Shapes.Count
ActiveSheet.Shapes(i).Select
Selection.Text = "Hello"
Next i
The following code example shows optimized code that references each Shape directly and changes
the text to "Hello".
For i = 0 To ActiveSheet.Shapes.Count
ActiveSheet.Shapes(i).TextEffect.Text = "Hello"
Next i
Declare variables with explicit types to avoid the overhead of determining the data type, possibly
multiple times in a loop, during code execution.
For simple functions that you use frequently in your code, implement the functions yourself in
VBA instead of using the WorksheetFunction object. For more information, see Use faster VBA
user-defined functions.
Use the Range.SpecialCells method to scope down the number of cells with which your code
interacts.
Consider the performance gains if you implemented your functionality by using the C API in the
XLL SDK. For more information, see the Excel 2010 XLL SDK Documentation.
XLS format
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 20/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
The XLS format is the same format as earlier versions. When you use this format, you are
restricted to 256 columns and 65,536 rows. When you save an Excel 2007 or Excel 2010 workbook
in XLS format, Excel runs a compatibility check. File size is almost the same as earlier versions
(some additional information may be stored), and performance is slightly slower than earlier
versions. Any multi-threaded optimization Excel does with respect to cell calculation order is not
saved in the XLS format. Therefore, calculation of a workbook can be slower after saving the
workbook in the XLS format, closing, and re-opening the workbook.
XLSB format
XLSB is the binary format starting in Excel 2007. It's structured as a compressed folder that
contains many binary files. It's much more compact than the XLS format, but the amount of
compression depends on the contents of the workbook. For example, ten workbooks show a size
reduction factor ranging from two to eight with an average reduction factor of four. Starting in
Excel 2007, opening and saving performance is only slightly slower than the XLS format.
XLSX format
XLSX is the XML format starting in Excel 2007, and is the default format starting in Excel 2007. The
XLSX format is a compressed folder that contains many XML files (if you change the file name
extension to .zip, you can open the compressed folder and examine its contents). Typically, the
XLSX format creates larger files than the XLSB format (1.5 times larger on average), but they are
still significantly smaller than the XLS files. You should expect opening and saving times to be
slightly longer than for XLSB files.
If one or more of your workbooks open and close more slowly than is reasonable, it might be caused
by one of the following issues.
Temporary files
Temporary files can accumulate in your \Windows\Temp directory (in Windows 95, Windows 98,
and Windows ME), or your \Documents and Settings\User Name\Local Settings\Temp directory (in
Windows 2000 and Windows XP). Excel creates these files for the workbook and for controls that
are used by open workbooks. Software installation programs also create temporary files. If Excel
stops responding for any reason, you might need to delete these files.
Too many temporary files can cause problems, so you should occasionally clean them out.
However, if you have installed software that requires that you restart your computer, and you
have not yet done so, you should restart before deleting the temporary files.
An easy way to open your temp directory is from the Windows Start menu: Click Start, and then
click Run. In the text box, type %temp%, and then click OK.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 21/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Tracking changes in a shared workbook causes your workbook file-size to increase rapidly.
Be sure that your Windows swap file is located on a disk that has a lot of space and that you
defragment the disk periodically.
A workbook that has its structure protected with a password (Tools menu > Protection > Protect
Workbook > enter the optional password) opens and closes much slower than one that is
protected without the optional password.
Oversized used ranges can cause slow opening and increased file size, especially if they are
caused by hidden rows or columns that have non-standard height or width. For more information
about used range problems, see Minimize the used range.
A large number of controls (check boxes, hyperlinks, and so on) on worksheets can slow down
opening a workbook because of the number of temporary files that are used. This might also
cause problems opening or saving a workbook on a WAN (or even a LAN). If you have this
problem, you should consider redesigning your workbook.
If possible, open the workbooks that you are linking to before you open the workbook that
contains the links. Often it is faster to open a workbook than to read the links from a closed
workbook.
Some virus scanner settings can cause problems or slowness with opening, closing, or saving,
especially on a server. If you think that this might be the problem, try temporarily switching the
virus scanner off.
Under some circumstances, Excel recalculates your workbook when it opens or saves it. If the
calculation time for your workbook is long and is causing a problem, ensure that you have
calculation set to manual, and consider turning off the calculate before save option
(Tools > Options > Calculation).
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 22/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Check the size of your toolbar file. A typical toolbar file is between 10 KB and 20 KB. You can find
your XLB files by searching for *.xlb by using Windows search. Each user has a unique XLB file.
Adding, changing, or customizing toolbars increases the size of your toolbar.xlb file. Deleting the
file removes all your toolbar customizations (renaming it "toolbar.OLD" is safer). A new XLB file is
created the next time you open Excel.
PivotTables
Totals as final results. If you need to produce totals and subtotals as part of the final results
of your workbook, try using PivotTables.
Totals as intermediate results. PivotTables are a great way to produce summary reports, but
try to avoid creating formulas that use PivotTable results as intermediate totals and subtotals
in your calculation chain unless you can ensure the following conditions:
The PivotTable has not been changed so that the information is still visible.
Conditional formats and data validation are great, but using a lot of them can significantly slow
down calculation. If the cell is displayed, every conditional format formula is evaluated at each
calculation and when the display of the cell that contains the conditional format is refreshed. The
Excel object model has a Worksheet.EnableFormatConditionsCalculation property so that you
can enable or disable the calculation of conditional formats.
Defined names
Defined names are one of the most powerful features in Excel, but they do take additional
calculation time. Using names that refer to other worksheets adds an additional level of
complexity to the calculation process. Also, you should try to avoid nested names (names that
refer to other names).
Because names are calculated every time a formula that refers to them is calculated, you should
avoid putting calculation-intensive formulas or functions in defined names. In these cases, it can
be significantly faster to put your calculation-intensive formula or function in a spare cell
somewhere and refer to that cell instead, either directly or by using a name.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 23/24
2/1/23, 2:58 PM VBA-Docs/excel-tips-for-optimizing-performance-obstructions.md at main · MicrosoftDocs/VBA-Docs · GitHub
Many workbooks contain a significant number of formulas and lookups that are concerned with
getting the input data into the appropriate shape for the calculations, or are being used as
defensive measures against changes in the size or shape of the data. When you have blocks of
formulas that are used only occasionally, you can copy and paste special values to temporarily
eliminate the formulas, or you can put them in a separate, rarely opened workbook. Because
worksheet errors are often caused by not noticing that formulas have been converted to values,
the separate workbook method may be preferable.
The 32-bit version of Excel can use up to 2 GB of RAM or up to 4 GB of RAM for Large Address
Aware 32-bit versions of Excel 2013 and 2016. However, the computer that is running Excel also
requires memory resources. Therefore, if you only have 2 GB of RAM on your computer, Excel
cannot take advantage of the full 2 GB because a portion of the memory is allocated to the
operating system and other programs that are running. To optimize the performance of Excel on a
32-bit computer, we recommend that the computer have at least 3 GB of RAM.
The 64-bit version of Excel does not have a 2 GB or up to 4 GB limit. For more information, see the
"Large data sets and the 64-bit version of Excel" section in Excel performance: Performance and
limit improvements.
Conclusion
This article covered ways to optimize Excel functionality such as links, lookups, formulas, functions, and
VBA code to avoid common obstructions and improve performance.
https://github.com/MicrosoftDocs/VBA-Docs/blob/main/excel/Concepts/Excel-Performance/excel-tips-for-optimizing-performance-obstructions.md 24/24