Alison Balteramp;#039;s Mastering Microsoft Office Access 1002003 [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Alison Balteramp;#039;s Mastering Microsoft Office Access 1002003 [Electronic resources] - نسخه متنی

Alison Balter

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



Making Coding Changes to Improve Performance


No matter what you do to optimize the operating system environment and improve your data design, poor code can continue to bog you down. A properly optimized application is optimized in terms of the environment, data design, and code. Just as poor table design can degrade performance, poor coding techniques also can have a dramatic negative effect on performance. Changes to your code include eliminating variants and dead code, using built-in collections, and using specific object types. An important code-related optimization is to deliver your modules precompiled.

The following changes and techniques can aid in the improvement of performance. It is important to recognize that any one change won't make much of a difference. However, an accumulation of all the changes, especially where code is being re-executed in a loop, can make a significant impact on your application's performance.

Eliminate Variants and Use the Smallest Data Type Possible


Variant variables are the slowest for the operating system to process; they carry a lot of overhead because the compiler resolves them at runtime. Remember that this statement declares a variant type of variable:

Dim intCounter

To strong-type this variable as an integer, for example, you must modify your code to look like this:

Dim intCounter As Integer

Not only should you strong-type your variables, but you also should use the smallest data type possible. Remember that data types such as Boolean, Byte, Integer, and Long are the smallest and therefore the fastest to resolve. These are followed by Single, Double, Currency, and (finally) Variant. Of course, if you must store very large numbers with decimal points in a variable, you cannot pick Single. Just keep in mind that it is wise to select the smallest data type appropriate for the use of the variable. Listing 17.1 provides code that illustrates the difference between using a variant and a long integer.

Listing 17.1 Data Type Benchmark Illustrating the Effect of Data Type on Performance

Private Sub cmdVariantBenchMark_Click()
Dim vntAny
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop with variant
dblStartTime = Timer
Do Until vntAny = 500000
vntAny = vntAny + 1
Loop
dblTime1 = Timer - dblStartTime
'Execute loop with integer
dblStartTime = Timer
Do Until intCounter = 500000
intCounter = intCounter + 1
Loop
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

The code, found in the form frmBenchmark in the CHAP17EX.MDB sample database, loops using a variant, and then a long integer. The example displays the amount of time required to execute each loop, along with the percent difference between the two techniques.

Use Specific Object Types


Just as using the General variant data type is inefficient, using generic object variables also is inefficient. This is because the compiler needs to evaluate their type at runtime. The MakeItBold subroutine uses a generic object variable, as shown in Listing 17.2.

Listing 17.2 The MakeItBold Subroutine

Private Sub cmdMakeBold_Click()
Call MakeItBold(Screen.PreviousControl)
End Sub
Sub MakeItBold(ctlAny As Control)
ctlAny.FontBold = True
End Sub

NOTE

The code in Listing 17.2 is overly simplified. It contains no error handling. The control passed as Screen.PreviousControl could be any type of control. The type of control received by the MakeItBold routine might not have a FontBold property, in which case an error occurs. It is therefore important for either one or both of these routines to contain proper error handling.

On the other hand, the SpecificBold subroutine uses a specific object variable, as Listing 17.3 shows.

Listing 17.3 The SpecificBold Subroutine

Private Sub cmdSpecificBold_Click()
Call SpecificBold(Screen.PreviousControl)
End Sub
Sub SpecificBold(txtAny As TextBox)
txtAny.FontBold = True
End Sub

The difference is that the SpecificBold routine expects to receive only text boxes. It does not need to resolve the type of object it receives and therefore is more efficient.

This code is contained in the CHAP17EX.MDB database on the accompanying CD-ROM. You can find the example in frmObjVar.

The best way to truly compare using a specific control versus a generic control is to benchmark the techniques, as shown in Listing 17.4.

Listing 17.4 Object Type Benchmark Compares Using a Specific Control and a Generic Control

Private Sub cmdObjectTypes_Click()
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop with generic control
dblStartTime = Timer
For intCounter = 1 To 5000
Call MakeItBold(Me.txtOptimized)
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with specific control
dblStartTime = Timer
For intCounter = 1 To 5000
Call SpecificBold(Me.txtOptimized)
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

The code, found in frmBenchmark, passes a text box to two different routines. The first routine receives any control as a parameter. The second routine receives only text boxes as a parameter. The benchmarks prove that routines that use specific object types take less time and are therefore more efficient.

Use Inline Code


There is a tendency to call out to procedures for everything. This is good from a maintenance standpoint, but not from an efficiency standpoint. Each time VBA calls out to a procedure, it takes additional time to locate and execute the procedure. This is particularly evident when the procedure is called numerous times. The alternative is to use inline code. Executing inline code is more efficient than calling out to procedures, because Access does not need to locate the code. The downside of inline code is that it is more difficult to maintain. You must decide how important maintainability is compared to speed.

Listing 17.5 shows the same code called as a routine and executed inline. The benchmark shows that the inline code executes much more quickly.

Listing 17.5 Inline Code Benchmark

Private Sub cmdInLine_Click()
Dim dblAny As Double
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop calling out to procedure
dblStartTime = Timer
For intCounter = 1 To 50000
Call SmallRoutine
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with inline code
dblStartTime = Timer
For intCounter = 1 To 50000
dblAny = 5 / 3
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub
Private Sub SmallRoutine()
Dim dblAny As Double
dblAny = 5 / 3
End Sub

Toggle Booleans Using Not


This code is very inefficient:

If bFlag = True Then
bFlag = False
Else
bFlag = True
End If

You should modify it to look like this:

bFlag = Not bFlag

Besides requiring fewer lines of code, this expression evaluates much more quickly at runtime. Listing 17.6 proves that toggling the Boolean variable is a much more efficient approach to the problem than having to test each condition separately. You can find this code in frmBenchmarks on the CD-ROM accompanying this book.

Listing 17.6 Toggling Boolean Benchmark

Private Sub cmdBooleans_Click()
Dim boolAny As Boolean
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop with If statement
dblStartTime = Timer
For intCounter = 1 To 100000
If boolAny = True Then
boolAny = False
Else
boolAny = True
End If
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop toggling Boolean
dblStartTime = Timer
For intCounter = 1 To 100000
boolAny = Not boolAny
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Use the Built-In Collections


The built-in collections are there whether or not you use them. By using For Each...Next and a collection of objects, you can write very efficient code, as shown in Listing 17.7.

Listing 17.7 Using For Each...Next

Sub FormCaption()
Dim frm As Form
For Each frm In Forms
frm.Caption = frm.Caption & " - " & CurrentUser()
Next
End Sub

In this example, you use the Forms collection to quickly and efficiently loop through each form, changing the caption on its title bar. The code shown in Listing 17.8 illustrates the use of the Forms collection, as well as an alternative method of accomplishing the same task.

Listing 17.8 For Each...Next Benchmark

Private Sub cmdCollections_Click()
Dim frm As Form
Dim intNumForms As Integer
Dim intLoop As Integer
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop with For Next
dblStartTime = Timer
For intCounter = 1 To 50
intNumForms = Forms.Count - 1
For intLoop = 0 To intNumForms
Forms(intLoop).Caption = "Hello"
Next intLoop
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with For Each
dblStartTime = Timer
For intCounter = 1 To 50
For Each frm In Forms
frm.Caption = "Hello"
Next frm
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Without the For Each..Next loop, you must use a variable to loop through the forms. Notice that the code sets intNumForms equal to the number of forms in the Forms collection minus one. The loop goes from zero to the value stored in intNumForms, changing the caption of the specified form. Although the performance gains realized by using the Forms collection are not dramatic, the Forms collection technique is much simpler to implement.

Use the Len Function


Using the Len function (as shown in Listing 17.9) is more efficient than testing for a zero-length string (as shown in Listing 17.10).

Listing 17.9 Using the Len Function

Sub SayNameLen(strName As String)
If Len(strName) Then
MsgBox strName
End If
End Sub
Listing 17.10 Testing for a Zero-Length String

Sub SayNameZero(strName As String)
If strName <> " Then
MsgBox strName
End If
End Sub

Listing 17.9 is easier for VBA to evaluate and therefore runs more quickly and efficiently. This is emphasized by the code shown in Listing 17.11 (located in frmBenchmark). The code shows two loops. One uses the Len function and the other does not. The benchmark proves that the routine that uses the Len function executes more quickly.

Listing 17.11 Len Benchmark

Private Sub cmdLen_Click()
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
Dim strTextBoxValue As String
strTextBoxValue = Me.txtOptimized
'Execute loop with zero-length string
dblStartTime = Timer
For intCounter = 1 To 50000
If strTextBoxValue <> " Then
End If
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with Len
dblStartTime = Timer
For intCounter = 1 To 50000
If Len(strTextBoxValue) Then
End If
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Use True and False Instead of 0


This example is similar to the preceding one. It is better to evaluate for True and False (as shown in Listing 17.12) instead of 0 (as shown in Listing 17.13).

Listing 17.12 Evaluating for True and False

Sub SaySalaryTrue(lngSalary As Long)
If lngSalary Then
MsgBox "Salary is " & lngSalary
End If
End Sub
Listing 17.13 Evaluating for 0

Sub SaySalaryZero(lngSalary As Long)
If lngSalary <> 0 Then
MsgBox "Salary is " & lngSalary
End If
End Sub

The code in Listing 17.12 runs more efficiently. The benchmark shown in Listing 17.14 provides an example. The lngSalary variable is evaluated against zero in the top loop. The bottom loop tests lngSalary against True. The second loop runs more quickly.

Listing 17.14 True/False Benchmark

Private Sub cmdTrueFalse_Click()
Dim intCounter As Long
Dim lngSalary As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop with zero
dblStartTime = Timer
For intCounter = 1 To 50000
If lngSalary <> 0 Then
End If
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with True/False
dblStartTime = Timer
For intCounter = 1 To 50000
If lngSalary Then
End If
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

NOTE

Although both the Len function and the use of True/False provided consistently better results in Access 2000 and earlier versions of Access, they appear to provide inconsistent results in Access 2003. This leads me to believe that there might have been changes to how these functions or their alternatives execute in Access 2003. I suggest that you test both the Len function and the use of True/False in your own environments to determine whether they result in improved performance.

Eliminate Unused Dim and Declare Statements


As you modify your subroutines and functions, you often declare a variable and then never use it. Each Dim statement takes up memory, whether or not you are using it. Furthermore, Declare statements, which you use to call external library functions, also take up memory and resources. You should remove these statements if you are not using them.

Eliminate Unused Code


Most programmers experiment with various alternatives for accomplishing a task. This often involves creating numerous test subroutines and functions. The problem is that most people do not remove this code when they are done with it. This dead code is loaded with your application and therefore takes up memory and resources. Several third-party tools are available that can help you find both dead code and variable declarations. One tool that many people use is called Total Access Analyzer, by FMS, Inc. (http://www.fmsinc.com).

Use Variables to Refer to Properties, Controls, and Data Access Objects


If you are going to repeatedly refer to an object, you should declare an object and refer to the object variable rather than the actual control, as shown in Listing 17.15.

Listing 17.15 Declaring an Object and Referring to the Object Variable

Forms!frmAny.txtHello.FontBold = True
Forms!frmAny.txtHello.Enabled = True
Forms!frmAny.txtHello.Left = 1
Forms!frmAny.txtHello.Top = 1

This is a very scaled-down example, but if numerous properties are being changed, or if this code is being called recursively, an object variable can make the code more efficient, as Listing 17.16 shows.

Listing 17.16 Using an Object Variable to Make Your Code More Efficient

Private Sub cmdChangeObject_Click()
Dim txt As TextBox
Set txt = Forms!frmHello.txtHello1
txt.FontBold = True
txt.Enabled = True
txt.Left = 100
txt.Top = 100
End Sub

The benchmark shown in Listing 17.17 contains two loops. The first loop sets four properties of the same control, explicitly referencing the control as each property is set. The second loop uses an object variable to accomplish the same task. The difference in performance between the two loops is somewhat dramatic.

Listing 17.17 Object Variable Benchmark

Private Sub cmdObjectVariable_Click()
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop without object variable
dblStartTime = Timer
For intCounter = 1 To 1000
Forms.frmBenchMark.txtOptimized.FontBold = True
Forms.frmBenchMark.txtOptimized.Enabled = True
Forms.frmBenchMark.txtOptimized.Locked = False
Forms.frmBenchMark.txtOptimized.BackStyle = vbNormal
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with object variable
dblStartTime = Timer
For intCounter = 1 To 1000
Dim txt As TextBox
Set txt = Forms.frmBenchMark.txtOptimized
txt.FontBold = True
txt.Enabled = True
txt.Locked = False
txt.BackStyle = vbNormal
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Use With...End With


Another way to optimize the code in the preceding example is to use a With...End With construct, as shown in Listing 17.18.

Listing 17.18 Using With...End With

Private Sub cmdChangeObjectWith_Click()
With Forms!frmHello.txtHello2
.FontBold = True
.Enabled = True
.Left = 100
.Top = 100
End With
End Sub

The code in Listing 17.19 shows two different loops. The first loop explicitly references the text box four different times to set four different properties. The second loop uses a With statement to reference the same control and set the four properties. The code in the second loop executes much more efficiently.

Listing 17.19 Object Variable Resolution Benchmark

Private Sub cmdWith_Click()
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop without With statement
dblStartTime = Timer
For intCounter = 1 To 1000
Forms.frmBenchMark.txtOptimized.FontBold = True
Forms.frmBenchMark.txtOptimized.Enabled = True
Forms.frmBenchMark.txtOptimized.Locked = False
Forms.frmBenchMark.txtOptimized.BackStyle = vbNormal
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with With statement
dblStartTime = Timer
For intCounter = 1 To 1000
With Forms.frmBenchMark.txtOptimized
.FontBold = True
.Enabled = True
.Locked = False
.BackStyle = vbNormal
End With
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Resolve Variables Outside a Loop


Although both the object variable reference and the With statement significantly improve performance, Listings 17.17 and 17.19 can be further improved by resolving the object variable outside the loop whenever possible. Listing 17.20 provides an example.

Listing 17.20 Resolving the Object Variable Outside the Loop

Private Sub cmdVariable_Click()
Dim txtAny As TextBox
Dim intCounter As Long
Dim dblStartTime As Double
Dim dblTime1 As Double
Dim dblTime2 As Double
'Execute loop without object resolution
dblStartTime = Timer
For intCounter = 1 To 1000
Forms.frmBenchmark.txtOptimized.FontBold = True
Forms.frmBenchmark.txtOptimized.Enabled = True
Forms.frmBenchmark.txtOptimized.Locked = False
Forms.frmBenchmark.txtOptimized.BackStyle = vbNormal
Next intCounter
dblTime1 = Timer - dblStartTime
'Execute loop with object resolution
dblStartTime = Timer
Set txtAny = Forms.frmBenchmark.txtOptimized
For intCounter = 1 To 1000
With txtAny
.FontBold = True
.Enabled = True
.Locked = False
.BackStyle = vbNormal
End With
Next intCounter
dblTime2 = Timer - dblStartTime
'Display time and percent differences
Me.txtSlow = dblTime1
Me.txtOptimized = dblTime2
Me.txtPercent = (1 - (dblTime1 / dblTime2)) * 100
End Sub

Notice that the object variable is resolved outside the loop. This loop executes significantly faster than the loops in Listings 17.17 and 17.19.

Use the Me Keyword


The preceding example uses Forms!frmHello.txtHello to refer to a control on the current form. It is more efficient to refer to the control as Me.txtHello because VBA searches only in the local name space. Although this makes your code more efficient, the downside is that the Me keyword only works within form, report, and class modules. It won't work within standard code modules. This means that you cannot include the Me keyword in generic functions that are accessed by all your forms.

Use String Functions When VBA Provides a Variant and String Alternative


Several VBA functions come in two forms :
one with a dollar sign ($) and one without. An example is Left(sName) versus Left$(sName). Whenever it is acceptable to return a string, it is more efficient to use the version with the dollar sign, which return strings rather than variants. When a string variable is returned, VBA doesn't need to perform type conversions.

Use Dynamic Arrays


Array elements take up memory, whether or not you use them. It's therefore sometimes preferable to use dynamic arrays. You can increase the size of a dynamic array as necessary. If you want to reclaim the space used by all the elements of the array, you can use the Erase keyword, as in this example:

Erase aNames

If you want to reclaim some of the space being used by the array without destroying data in the elements you want to retain, use Redim Preserve:

Redim Preserve aNames(5)

This statement sizes the array to six elements (it's zero-based). Data within those six elements is retained.

CAUTION

You must be careful when using dynamic arrays with Redim Preserve. When you resize an array using Redim Preserve, the entire array is copied in memory. If you are running in a low-memory environment, this can mean that virtual disk space is used, which slows performanceor worse than that, the application can fail if both physical and virtual memory are exhausted.

Use Constants When They Are Available


Constants improve both readability and performance. A constant's value is resolved after compilation. The value the constant represents is written to code. A normal variable has to be resolved as the code is running because VBA needs to obtain the current value of the variable.

Use Bookmarks


A bookmark provides you with the most rapid access to a record. If you are planning to return to a record, set a variable equal to that record's bookmark, making it very easy to return to that record at any time. Listing 17.21 shows an example that uses a bookmark.

Listing 17.21 Using a Bookmark

Sub BookMarkIt()
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Dim varBM As Variant
rst.Open "tblProjects", CurrentProject.Connection, adOpenStatic
varBM = rst.Bookmark
Do Until rst.EOF
Debug.Print rst!ProjectID
rst.MoveNext
Loop
rst.Bookmark = varBM
Debug.Print rst!ProjectID
End Sub

You can find this code in basOptimize of CHAP17EX.MDB. The code stores the bookmark in a variable until the Do...Until loop executes. Then the code sets the recordset's bookmark equal to the value contained within the variable.

Set Object Variables Equal to Nothing


Object variables take up memory and associated resources. Their value should be set to Nothing when you are finished using them. For example:

Set oObj = Nothing

This conserves memory and resources.

Use Action Queries Instead of Looping Through Recordsets


Besides being easier to code, executing a stored query is much more efficient than looping through a recordset, performing some action on each record. Listing 17.22 shows an example that loops through a recordset.

Listing 17.22 Looping Through a Recordset

Sub LoopThrough()
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
rst.Open "tblProjects", CurrentProject.Connection, adOpenDynamic, _
adLockOptimistic
Do Until rst.EOF
rst!ProjectTotalEstimate = rst!ProjectTotalEstimate + 1
rst.UPDATE
rst.MoveNext
Loop
End Sub

This code, which is located in basOptimize of CHAP17EX.MDB, loops through a recordset, adding 1 to each project's total estimate. Contrast this with the code in Listing 17.23.

Listing 17.23 Executing a Stored Query

Sub ExecuteQuery()
Dim adoCat As ADOX.Catalog
Dim cmd As ADODB.Command
Set adoCat = New ADOX.Catalog
Set cmd = New ADODB.Command
Set adoCat.ActiveConnection = CurrentProject.Connection
Set cmd = adoCat.Procedures("qupdLowerEstimate").Command
cmd.Execute
End Sub

This code uses a command object to execute a stored query called qupdLowerEstimate. The query runs much more efficiently than the Do...Until loop shown in Listing 17.22.

NOTE

The most efficient method to update records is with a stored procedure. You can use stored procedures with a client/server database engine such as Microsoft SQL Server. This is covered in detail in

Alison Balter's Mastering Access 2002 Enterprise Development .

Deliver Your Application with the Modules Compiled


Applications run slower when they are not compiled. Forms and reports load slower, and the application requires more memory. If you deliver your application with all the modules compiled, they do not need to be compiled on the user's machine before they run.

To easily recompile all modules, choose Debug, Compile with the Visual Basic Editor (VBE) active. This command opens and compiles all code in the application, including the code behind forms and reports. It then saves the modules in the compiled state, preserving the compiled state of the application.

Retain the Compiled State


Don't bother choosing the Debug, Compile command if you plan to make additional changes to the application. An application becomes decompiled whenever you modify the application's controls, forms, reports, or modules. Even something as simple as changing a single line of code causes the application to lose its compiled state. It's therefore important to choose the Debug, Compile command immediately before you distribute the application.

CAUTION

Renaming a database file causes the code contained in the database to decompile. It's therefore important to always choose the Compile command after renaming a database.

Distribute Your Application as an MDE


The process of creating an MDE file compiles all modules, removes editable source code, and compacts the destination database. All Visual Basic code will run, but cannot be viewed or edited. This improves performance, reduces the size of the database, and protects your intellectual property. Memory use also is improved. The process of saving an application as an MDE and the implications of doing so are covered in Chapter 27, "Database Security Made Easy," and Chapter 32, "Distributing Your Application."

Organize Your Modules


VBA code theoretically can be placed in any module within your application. The problem is that the compiler does not load a module until you call a function within it. After you call a single procedure in a module, the compiler loads the entire module into memory. Furthermore, if a single variable within a module is used, the compiler loads the entire module into memory. As you might imagine, if you design your application without much thought, every module in your application will be loaded.

If you place similar routines all in one module, that module will be loaded, and others will not. This means that if people are using only part of the functionality of your application, they will never be loading other code modules. This conserves memory and therefore optimizes your application.


/ 544