You've optimized your forms and queries, but now you need to look at the entire application. Your application contains a lot of VBA code. What optimizations can you perform to make it run faster?
This solution demonstrates seven specific programmatic techniques you can apply to accelerate your code. The improvement can range from modest increases to increases of several orders of magnitude in performance.
To see the optimizations in action, open and run frmShowOptimizations from 08-05.MDB, shown in Figure 8-14. Click the Run Tests button, and the tests will run one by one, displaying the results in milliseconds. The tests compare two different methods of using VBA to achieve a result.
Follow these steps to apply the optimizations suggested by these tests to your applications:
When dividing integers, use integer division. A majority of the division operations performed by your application are probably done on integer values. Many developers use the slash (/) operator to divide two numbers, but this operator is optimized for floating-point division. If you're dividing integers, you should use the backslash (\) integer division operator instead. With \, Access works at the integer level instead of the floating-point level, so computation is faster. (Of course, this is useful only if you're assigning the results of the division operation to an integer. If you care about the fractional portion of the division, you'll need to use floating-point math and the / operator after all.) For example, instead of:
intX = intY / intZ
intX = intY \ intZ
Use specific data types instead of variants. Variants offer convenience at the expense of performance. Every time you refer to a variant, Access needs to perform type conversion to ensure the data is in the correct format. By using the data type that matches your variable, you eliminate the need for this type conversion, and your code runs faster. In addition, a variant variable is twice as large as an integer (on a 32-bit operating system) and thus takes longer to manipulate.
Test for blank strings using the Len function. You probably have code that tests for blank strings by comparing them to an empty string (""). However, because Access stores the length of the string as the first byte in the string, testing for a length of zero using the Len function is always faster. Instead of:
If strTemp = "" Then MsgBox "The string is blank" End If
If Len(strTemp) = 0 Then MsgBox "The string is blank" End If
If you refer to an object more than once in a section of code, assign it to an object variable. Every time you reference an object, Access has to perform some work to figure out which object you are referring to. This adds overhead to your code each time the object is referenced. But if you assign the object to an object variable, Access "finds" the object once and caches the reference in memory. So after the first reference, you can refer to the object through the object variable and your code will run faster. For example, instead of this code:
Dim strTmp As String Dim lngCount As Long For lngCount = 0 To acbcMaxIterations / 2 strTmp = DBEngine.Workspaces(0).Groups(0).Name Next lngCount
Dim grp As DAO.Group Dim strTmp As String Dim lngCount As Long Set grp = DBEngine.Workspaces(0).Groups(0) For lngCount = 0 To acbcMaxIterations / 2 strTmp = grp.Name Next lngCount
We created two variations of this test. First, we changed the function to refer to a control on an open form instead of a DAO group. The cached reference version of the code was 2.8 times faster?significantly improved, but not of the same magnitude as the DAO group comparison. Second, we compared using an object variable against using the VBA With...End With construct (without an object reference). With...End With was slower than using an object variable, but still much faster than using neither an object variable nor With...End With.
Don't worry about comments. In VBA the use of comments exacts no measurable performance penalty, so there's no excuse for omitting them!
Use If...Then...Else instead of the IIf function. By replacing IIf statements with the equivalent If...Then...Else statement, your code will run faster. For example, instead of:
MsgBox IIf(intX = 1, "One", "Not One")
If intX = 1 Then MsgBox "One" Else MsgBox "Not One" End If
When initializing a string so that it's empty, don't use a literal value (""). Instead, use the built-in vbNullString constant. You'll get better performance, as the test demonstrates.
Many optimizations that apply to other languages can also apply to VBA. For example, checking for blank strings using the Len function is a common optimization in other languages. Don't be afraid to try new techniques. The small performance improvements you get from optimizing VBA code can add up if you are running code in a repetitive loop, and many small improvements may result in a noticeable overall difference in your application.
Optimization techniques for programming languages are a vital part of your toolbox. But don't sacrifice other vital elements for the sake of speed. First, make sure your code works correctly before you optimize. Second, write your code so that it's easily understood; it can be very difficult to optimize code you don't understand. Finally, don't break working code when optimizing it. By optimizing code that works correctly (albeit slowly), you may introduce bugs. Follow the three rules of optimization:
Make it right before you make it faster.
Make it clear before you make it faster.
Keep it right as you make it faster.
You may find that there are no easy optimizations for a particular piece of code. No matter what you do, it just won't run fast enough. A favorite saying in software design is "Don't diddle code to make it faster; find a better algorithm." Often you need to step back from a piece of slow code. Maybe there is a better overall approach or a better algorithm you can employ. A good way to get over a hurdle such as this is to ask other programmers how they handle the same situation. Overall, you will find that code optimizations have a much smaller impact on your application's performance than optimizations to your data access; for example, adding one extra index can have a greater impact than hours and hours of time spent optimizing VBA.