Because I use the settings functionality in nearly every Excel project, my goal is to create a template that I can use to kick off each Excel application I build.. Listing 22.1: Impleme
Trang 1Chapter 22
Application Deployment Strategies
One thing that will become evident to you shortly after you release your first Excel application
is that even though you’ve finished developing, your work is far from complete You have users to support, bugs to fix (though many strive for it, nobody’s perfect), and new features to add You know the saying “If you fail to plan, you plan to fail”? After just a couple of releases, if you don’t plan your application releases and upgrades, you may find your state of affairs bordering on chaos—especially
if you’ve got lots of users (dozens to hundreds)
In order to manage the product distribution and release cycle, you can employ numerous strategies, from rudimentary to comprehensive fail-proof release management systems This chapter introduces you to a few strategies you can use to manage application distribution
Another issue related to application deployment is determining what form your application will
be in when you distribute it You can choose from distributing your application as a standard workbook, a template, or an add-in I’ll present the pros and cons of each form so that you can make an informed choice The choice of an application deployment strategy is a decision that is best made near the beginning of the development process because the decisions you make during the development process can be impacted depending on the distribution form of your application
Choose the Form
Do you remember the movie Ghostbusters (1984)? The Ghostbusters are fighting the evil demon Gozer
(aka Gozer the Gozerian, Gozer the Destructor, Voguss Zildrohar, The Traveller) Just prior to assuming a physical presence, Gozer asks the Ghostbusters to choose the form of their destroyer As they all stop to ponder their decision, Gozer appears as a giant Stay Puft marshmallow man Sure enough, Stantz (played by Dan Akroyd) made the mental decision without the input of his colleagues His reasoning? “I tried to think of the most harmless thing… something that could never destroy us… something I loved from my childhood.” As it turned out, the Ghostbusters eventually destroyed Gozer before Gozer could bring about worldwide destruction
When it comes to choosing the form of distribution for your application, it’s safe to say that your choice won’t have worldwide life and death consequences There are consequences however
Trang 2I Like Vanilla
The most common form an Excel application takes is as a plain vanilla workbook This next sentence
is very important so pay attention In order to create an application that assumes this form, you must save your workbook (File � Save) OK, I’m playing a little bit Telling you how to save a workbook
is kind of like telling you how to breathe
The biggest benefit of using a standard Excel workbook is that you don’t need to worry about installing it before using it You can e-mail the workbook, place it in a shared network folder, or save
it to portable media As long as your users can open the workbook, they can use the functionality it supplies, provided it passes the Microsoft Office security checks
That said, it is not uncommon for a handful of your users to experience issues related to either a faulty Office or Excel installation Well, it’s not necessarily that the original Excel installation was faulty— rather something probably happened to the computer after the fact that caused an incompatibility or removed critical system files If your application works for the vast majority of your users and doesn’t work at all for a tiny minority, your leading suspect should be the details associated with these individual computers If you quiz these users, usually you’ll find out that they recently had software pack
age X (substitute any number of software programs here) installed or removed, and that ever since,
Excel has exhibited unpredictable behavior If my application doesn’t work after I verify that all of the software requirements it needs have been met, I’ll devise a trivial procedure that should work on every computer to test the offending computers If the trivial procedure fails as well, I’ll have the users or their IT support department reinstall Microsoft Office and all applicable service packs Most of the time this solves the problem
Repeat Your Success with Templates
Another form your solution can assume is a template Templates are useful for applications that provide functionality that is used to help automate repeated processes or procedures
For example, maybe your firm has a standard capital spending approval process that requires financial justification as part of the approval process You could develop a template that facilitates this process by assisting users with the data input process, producing reports, and submitting workbook data for approval
Though you could add functionality to a normal workbook solution to make it act like a template, why not just save the original as a template and get all of the template functionality for free? (A counterpoint is provided in two paragraphs.) When your users need to create a new capital spending approval request, all they need to do is select File � New, choose the On My Computer link underneath Templates in the task pane, and then select the capital spending template
Templates also allow you to develop worksheet-based solutions That is, you can develop a worksheet that performs some specific task and then save it as a worksheet template Then you can insert the worksheet template as a new worksheet in any workbook that requires the functionality provided
by the worksheet
The minor disadvantage of a template is that it requires a little more knowledge to use than a standard workbook Occasionally I find it difficult to remember that some people don’t know how to add two cells together in Excel (probably a larger percentage of users than you think) The fact is, if your solution is being distributed to a large number of users, you’ll need to create a utility to install the template to the proper template directory (or provide documentation on how to do this manually) Additionally, you will also need to train people on how to create a workbook based on a template How
Trang 3you deliver this training (proactive documentation, proactive communication/training, or reactive communication) is up to you, but you will end up delivering it
The alternative to using a template is to distribute a standard workbook that contains a user interface element that says something like “Create New <your solution>” When you click the Create New button, or whatever, all your code needs to do is provide a way for the user to name the new workbook and select a location to save it (you can use the GetSaveAsFilename method) and then save the solution workbook using the new name and location Whenever the user needs to create a new document, they open up the original file you distributed and click the Create New button
Perhaps an example of the different alternatives for delivering template functionality is in order at this point I’d like to demonstrate three things: how to create a template, how to create a workbook that acts like a template, and how to create a worksheet template
As an example of how to create a template and how to create a workbook that acts like a template, I’ve taken the Setting and Settings classes along with the Settings worksheet from Chapter 12 and placed them into a workbook with two empty worksheets Because I use the settings functionality in nearly every Excel project, my goal is to create a template that I can use to kick off each Excel application I build Though this example just adds the settings functionality to this workbook, you may want to add other components that you find yourself using in nearly every project Figure 22.1 shows
an example of the Excel Project workbook that I’ll turn into a template
Creating a template given an existing workbook is easy as the following steps illustrate:
1. Select File � Save As
2. Change Save As Type to Template (*.xlt)
3. In order to have the template appear in the list of templates displayed by the Templates dialog box, you should save the file to the Templates folder, which is located by default at
C:\Documents and Settings\username\Application Data\Microsoft\Templates I saved
mine with the name Excel Project
Figure 22.1
This otherwise empty workbook contains the compo
nents necessary
to implement set
tings as covered in Chapter 12
Trang 4Tip You can determine the path to the Templates folder programmatically using Application.TemplatesPath
Piece of cake! To use the template, follow these steps:
1 Select File � New
2 Choose the On My Computer option underneath the Templates section in the task pane
3 Double-click the Excel Project template
Warning The most common error made by users trying to use a template is that they open the template itself (by open ing a template workbook directly) rather than creating a new workbook based on a copy of the template
As you might infer from the warning about opening templates directly being the most common error, in order to modify a template, you need to open the template up directly by selecting File � Open and then selecting the template file
In order to create a pseudo-template (a workbook that imitates Template functionality) you need to use some VBA Listing 22.1 presents an example of code you can use to implement pseudo-template functionality If some of the procedures in this listing look familiar, it’s because you saw
a few of them in Chapter 6 when you learned about the Workbook object
Listing 22.1: Implementing Pseudo-Template Functionality
Option Explicit ' Create new workbook based on this workbook Sub SimplePsuedoTemplate()
Dim wb As Workbook Dim sName As String Dim sDefault As String Dim sFilter As String ' Default file name sDefault = GetDefaultName ' Filter for GetSaveAsFilename method sFilter = "Microsoft Office Excel Workbook (*.xls), *.xls"
' Ask user where to save new file sName = Application.GetSaveAsFilename(sDefault, sFilter) ' False means user clicked cancel or dismissed dialog box ' without making a choice
If sName <> "False" Then ' See if a file already exists at the selected location
If FileExists(sName) Then ' There IS an existing file - see if the user ' wants to overwrite it
Trang 5If OkToOverwrite(sName) Then ' Turn off alerts so Excel doesn't bug ' the user about the existing file Application.DisplayAlerts = False ThisWorkbook.SaveAs sName
' Turn alerts back on Application.DisplayAlerts = True End If
End Sub ' Generates a default file name Function GetDefaultName() As String Dim bGotName As Boolean
Dim sName As String Dim nIndex As Integer
Do sName = Left(ThisWorkbook.Name, Len(ThisWorkbook.Name) - 4) & _ CStr(nIndex)
If IsWorkbookOpen(sName & ".xls") Then nIndex = nIndex + 1
Else bGotName = True End If
Loop Until bGotName GetDefaultName = sName & ".xls"
End Function ' See if a given workbook is open or not Function IsWorkbookOpen(sWorkbookName As String) As Boolean Dim wb As Workbook
If StrComp(sWorkbookName, wb.Name, vbTextCompare) = 0 Then IsWorkbookOpen = True
Exit For
Trang 6' Ask if it's ok to overwrite a file Function OkToOverwrite(sFullName As String) As Boolean Dim sMsg As String
Dim nButtons As Long Dim nResponse As Long Dim bOverwrite As Boolean bOverwrite = False sMsg = sFullName & " already exists Do you want to overwrite it?"
nButtons = vbYesNoCancel + vbExclamation + vbDefaultButton2 nResponse = MsgBox(sMsg, nButtons, "Overwrite File?")
If nResponse = vbYes Then bOverwrite = True End If
' See if a file exists or not Function FileExists(sFullName As String) As Boolean Dim bExists As Boolean
Dim nLength As Integer nLength = Len(Dir(sFullName))
Basically all this listing does is save the workbook using a different name In order to be a little more convenient, the listing does things like generate a default filename, prompt the user for a filename and storage location, check to see if a file with the same name already exists, and if so, ask if it’s
Trang 7OK to overwrite the existing file Of course, to make things even more user friendly, if this were a production application, you would want to add a user interface element (menu item, command button, etc.) that calls the SimplePsuedoTemplate procedure for the user
One of the advantages of using a pseudo-template in place of a real template is that you can build initialization code into the process that creates the new workbook For example, it would be easy to modify Listing 21.1 to prompt for the initial settings for the project such as the App Name, App Version, and App Date
Using Worksheet Templates
Though many people are not aware of it or don’t take advantage of it, you can also create a worksheet template Worksheet templates allow you to insert worksheets exhibiting predefined formatting or functionality into a workbook Using the Settings functionality as an example, let me explain one way that you could put a worksheet template to good use—by creating a Settings worksheet template Then, if you wanted to add Settings functionality to a particular workbook, you could add a new Settings worksheet (based on the Settings template you’ll create shortly) and import the two classes that provide setting functionality (the Settings and Setting classes)
Creating a worksheet template is very similar to creating a workbook template The main difference is that you need to be sure to limit the worksheets in the workbook to just those that you want
to appear when you insert them into a workbook based on the template To create a worksheet template based on the Settings worksheet, follow these steps:
1. Create a workbook that contains just one worksheet (the Settings worksheet)
2. Select File � Save As
3. Change Save As Type to Template (*.xlt)
4. In order to have the template appear in the list of templates displayed by the Templates dialog box, you should save the file to the Templates folder, which is located by default at C:\Doc-
uments and Settings\username\Application Data\Microsoft\Templates I saved mine with
the name Settings
Using a worksheet template is easy enough if you know where to look The only way I know to insert a worksheet template is to right-click the worksheet tab that I want to insert a worksheet in front of and select Insert This displays the Insert dialog box shown in Figure 22.2 Then all I need
to do is select the desired template and click OK
Note If you select a template containing more than one worksheet, Excel will insert a worksheet for every worksheet found in the template
Blend in with Add-Ins
Add-ins are useful when you have functionality that is not workbook specific—for example, you could develop a bunch of user-defined functions and distribute them as an add-in This works wonderfully, because generally you’ll want to use the functions from within many different workbooks
Trang 8Figure 22.2
Inserting a work
sheet based on a template is as easy
as double-clicking the appropriate template
Another benefit of an add-in is that its structure is not visible to the user A workbook (and therefore a template) must have at least one visible worksheet This rule does not apply to an add-in Though you can protect a workbook so that it is difficult, at best, to modify, add-ins cannot be modified in anyway by a user The only way to modify an add-in is to modify the workbook with which the add-in was created
As an example, I’ve created a simple add-in that contains two user-defined functions: one function that prints out the connection details of the query table associated with a given range and another that lists all of the very hidden worksheets in the active workbook To test this out, create a new workbook and enter the code from Listing 22.2
Listing 22.2:Useful Add-In Functions
Option Explicit ' Lists the connection details of the query table that ' intersects with the QueryTableCell parameter
Function ViewQueryTableConnection(QueryTableCell As Range) As String Dim sResult As String
On Error Resume Next sResult = ""
Trang 9ViewQueryTableConnection = sResult End Function
' Lists any worksheets in the active workbook ' that are very hidden
Function ListVeryHiddenSheets(AnyCell As Range) As String
On Error Resume Next sResult = ""
For Each ws In AnyCell.Parent.Parent.Worksheets
If ws.Visible = xlSheetVeryHidden Then sResult = sResult & ws.Name & ", "
End If Next ' Strip off trailing ", " if needed
If Len(sResult) > 2 Then sResult = Left(sResult, Len(sResult) - 2) Else
sResult = "There are no very hidden worksheets."
End If Set ws = Nothing ListVeryHiddenSheets = sResult End Function
The ViewQueryTableConnection function is useful to view the connection details associated with
a query table When you use Microsoft Query to bring data from a database into a worksheet, the data
is displayed in a range of cells called a query table If you use Microsoft Query frequently, occasionally you will need to figure out what database a particular query table is associated with You can use ViewQueryTableConnection to display this information To use ViewQueryTableConnection, all you need to do is pass it a reference to a cell that is part of the query table Figure 22.3 shows an example that uses ViewQueryTableConnection
I added the ListVeryHiddenSheets function as another example in case you wanted to test an
add-in without creatadd-ing a query table Pass this function as a reference to any cell add-in the workbook you want to inspect and it will return a comma-delimited list of the names of any very hidden worksheets
in the workbook
To make an add-in, all you need to do is save a workbook as one Prior to saving the workbook, you may want to lock the VBA project so that people can’t view the code that implements your add-in For this example, perform the following actions:
Trang 10Figure 22.3
Viewing the details associated with a query table
1. Select the VBA project associated with Listing 22.2 in the Project Explorer window
2. Right-click and select VBAProject Properties
3. Click the Protection tab
4. Check Lock project for viewing and provide a password (I used “password”)
5. Save the workbook as Simple Add-in.xls
6. Now you’re ready to make the add-in Save the workbook as Simple Add-in.xla You can do this by changing the file type to Microsoft Office Excel Add-in (*.xla) When you do this, Excel will automatically select the AddIns folder associated with your user ID On my computer, the default AddIn folder is C:\Documents and Settings\shansen\Application Data\Microsoft\AddIns
To test the in, you need to load it into memory In addition, the first time you use an
add-in, you need to instruct Excel where to find it To test the Simple Add-add-in, follow these steps
1. Select Tools � Add-Ins from the Excel menu
2. The first time you use an Add-In you need to add it to the list of Add-Ins by clicking Browse
3. Locate the In file you created in step 6 of the previous set of instructions Select the
Add-In and click OK to add the add-in to the list of Add-Add-Ins
Trang 114 Once an add-in appears in the list, you can load/unload it by checking/unchecking it in the Add-Ins dialog box In the following screenshot I’ve loaded the Simple Add-In add-in
Managing Change
Now that you understand the various ways that you can deliver your solution, let’s move on It has now been six months since you released your application to dozens or possibly hundreds of happy users You’ve got minor issues to correct and a list of enhancements to implement One of your biggest considerations is going to be how to go about releasing another version Addressing that consideration is the topic of this section
One way you can reduce the impact of version management is to deploy “master” copies to shared network locations and then create shortcut links on users computers that point to the master copies
In case of emergency, you can take measures to upgrade or fix existing applications by creating your own “service pack” that you distribute to your users A service pack contains all of the code necessary
to fix an existing application
The best way to go about version management, however, is to plan for it from the beginning
Expect that you will need to release future versions from day one in the development cycle By incorporating this expectation into the decisions you make as you develop an application, you can take advantage of the opportunity to make design decisions that will facilitate version management You will learn more about this topic later on in the section titled “Implementing Version Awareness.”
Employing Centralized Template Deployment
One problem that is associated with releasing new versions is that it complicates support because not all of your users may be using the same version Depending on the extent of your changes, the versions may not be compatible Dealing with multiple versions and slow adoption of the latest version are
Trang 12most often problems when you are distributing your application using a plain old workbook (not as
a template or add-in) and are using a loosely defined distribution mechanism such as e-mail One way that you can reduce the impact of this issue for template-based applications is to use shortcuts in the Template folder that point to a centralized master copy The shortcut could point
to a template on a shared server, the intranet, or the Internet That way, every time a user creates a new workbook based on the template, they’ll be assured they’ve used the most recent version of the template available Of course, this tip does not address any deficiencies in workbooks created using older versions of the template
As an example, let’s assume that you placed the Excel Project template that you saved earlier in the chapter on your company’s intranet and the URL to the template is http://intranet/templates/ Excel%20Project.xlt Rather than have your users constantly refer to the site to check for updates,
it is much more efficient to instruct them to put a shortcut to this URL in their templates folder as the following exercise demonstrates
1. Right click the Windows Start button and select Explore Using Windows XP Professional, this action places you in Windows Explorer at the Start folder associated with your user ID
2. Locate and expand the Templates folder associated with your user ID By default, the relative path to this starting with the documents folder associated with your login (i.e C:\Documents and Settings\shansen) is Application Data\Microsoft\Templates Figure 22.4 shows an example of this
3. With the Templates folder selected, choose File � New � Shortcut
Figure 22.4
Create a shortcut to master copies of a template in the Templates folder
Trang 134. In the Create dialog box, browse for or enter the URL to the desired template, such as http:/ /intranet/templates/Excel%20Project.xlt, and then click OK (Substitute the actual URL
to your template) The following screenshot shows an example of this
5 Enter the name of the shortcut and click OK The text you enter here will appear in the Templates dialog box when you create a new workbook based on a template
Once you’ve created the shortcut, from the user’s perspective, it works just like any other template
Go ahead, give it a try!
Implementing Version Awareness
For the ultimate amount of control regarding version management, you can build version awareness into your solution Version awareness is functionality that allows the application to know which version it is and check to see if it is up to date or not, this functionality also communicates any versioning issues to the user, and has some ability for self-healing and updating How much or how little of this functionality you develop depends on your needs The most basic solution just checks to see if the version being used is the most current and displays a message to the user Ultimately the amount of functionality you build is only limited by your time and imagination
Trang 14Version awareness solutions aren’t for all types of applications For one thing, it can take a great deal of effort to implement version awareness depending on how much functionality you build into
it Also, any version awareness solution is going to need access to version data (typically stored in a database) located on another computer Because not everyone is connected to a network all of the time (especially those users using laptops), the version awareness functionality must not assume constant network availability Finally, you want to be very careful with the version awareness functionality that you implement Nothing’s worse than bugs in the functionality that’s supposed to help fix bugs
In order to stimulate your thoughts, I’ll walk you through a basic version awareness implementation As I mentioned earlier, typically a database is used as a centralized store of the version information needed to facilitate the required functionality Though I’m using Access for this example, you could easily modify the example to work with other database products
Step 1: Build the Database
To begin, create a new database in Access I named my database versions.mdb You can get by with one table for the basic version awareness implemented in this exercise Create a new table and add the fields shown in Table 22.1 Name this table VersionInfo and make the VersionID field the primary key
Table 22.1: Fields Needed in the VersionInfo Table Field Name Data Type Field Size Description
VersionID AutoNumber Long Integer Version ID of the version MinimumVersionID Number Long Integer Version ID of the earliest version
that is still compatible with this version
CurrentMessage Text 255 Message displayed if the user’s
version is equal to this version NonCurrentMessage Text 255 Message displayed if the user’s
version is not current, but is still compatible
NonCompatibleMessage Text 255 Message displayed if the user’s
version is not current and is not compatible with this version IsCurrent Yes/No Yes/No Flag to indicate whether the version
is current or not
major.minor.revision format (ex: 1.3.13)
VersionComment Text 255 Description of comment about the
version VersionLocation Text 255 Instructions on how to obtain the
version ReleaseDate Date/Time Short Date Date the version was released
Trang 15This table will work fine, though it is not optimal More astute database readers may want to tweak this to either use more tables or take advantage of features available in their database product of choice For example, the MinimumVersionID field is related to the VersionID field The only valid values in the MinimumVersionID field should be those values that are already found in VersionID
It would be a good idea to enforce this relationship
Another minor flaw in using a simple table structure like this can be found in the IsCurrent field Theoretically, only one record should be in the table that has the value YES; this is because only one version can be current Nothing is preventing you from having multiple records with the value YES
in this table This isn’t much of a problem as long as you know about it in advance and write queries that have a way to determine the “real” current version in case more than one version is marked as current Later in the implementation, you’ll see that I also sorted the results of my query that checks for the latest version so that they descend by VersionID If more than one record is marked as current, the implementation will use the one that was added most recently A better way to do this may be to have
a separate table with just one record and one field that contains the VersionID of the current version Anyway, I digress, for this is a book about Excel VBA, not about database design
While you still have the database open, you could go ahead and enter a few test versions into the VersionInfo table Table 22.2 lists some example data you could use For the fields that aren’t shown
in Table 22.2, go ahead and make up an appropriate message for the CurrentMessage, Message, and NonCompatibleMessage fields
NonCurrent-Table 22.2: Sample Data for the VersionInfo NonCurrent-Table VersionID MinimumVersionID IsCurrent Version
Step 2: Prepare an Excel Project
The next thing to do is to put the handy Excel Project template you created earlier in the chapter to good use and create an empty Excel Project workbook If you recall, the Excel Project template creates
a workbook that contains the Setting and Settings classes along with a Settings worksheet You still have a few details to take care of before you start writing any code
1. On the Settings worksheet, provide a value for the App Version setting Choose a version number that can be found in the Version field of the VersionInfo table
2. You could provide values for the App Name and App Date settings but these settings are not needed for this exercise
3. Add a setting named Version Connection This setting will hold the connection string used to connect to the versions database The value of this setting should be Provider= Microsoft.Jet.OLEDB.4.0;Data Source=C:\versions.mdb If you placed the versions database somewhere else, modify the data source aspect of the connection string appropriately
Trang 164. Switch over to the VBE and add a reference (Tools � References) to Microsoft ActiveX Data Objects 2.7 Library
Note Not all of your users may have the latest version of ADO It is a good idea to sample some of your users’ com puters before choosing which version of ADO to use Choose the latest version that is available on each user’s computer Alternatively, you can have your users update their computers with the latest available version For more information see http://msdn.microsoft.com/data/
5. Save the workbook I saved mine as Version Example.xls
Step 3: Implement Version Awareness
Now you’re ready to write some code Insert a module into the project and add the code shown in Listing 22.3 Listing 22.3 contains six procedures as shown in Table 22.3
Table 22.3: Procedures Needed to Implement Version Awareness
PerformVersionCheck This is the main procedure and the only one that should be called by
a user or user interface element
CheckVersion CheckVersion compares the version indicated in the workbook
against the current version indicated in the database and displays a message indicating the results
GetVersionID Retrieves the VersionID in the database that is associated with the
version given by the App Version setting
QueryDB A generic procedure that executes a query against the database and
returns a recordset containing the results
GetConnection Retrieves the connection string stored in the Version Connection
setting
IsConnectionAvailable Determines whether a connection to the database can be made or not
Listing 22.3: Implementing Basic Version Awareness
Option Explicit Sub PerformVersionCheck() ' see if you can make a connection ' to the database before checking
If IsConnectionAvailable Then CheckVersion
Else MsgBox "Sorry, can't check version at this time."
Trang 17End If End Sub Private Sub CheckVersion() Dim rst As ADODB.Recordset Dim nWBVersion As Integer Dim sSQL As String
On Error GoTo ErrHandler ' SQL statement to retrieve list of employees
' Make sure we got a recordset If QueryDB runs into problems ' it returns nothing
If rst Is Nothing Then Exit Sub
If Not rst.EOF Then ' Get the version ID associated with the version indicated ' on the settings worksheet
nWBVersion = GetVersionID ' Compare the version ID against various possibilities Select Case nWBVersion
Case Is = -1 MsgBox "Unknown version status Could not find " & _ "version information in the database related " & _ "to the version indicated in this workbook."
Case Is = rst.Fields("VersionID").Value
If Not IsNull(rst.Fields("CurrentMessage").Value) Then MsgBox rst.Fields("CurrentMessage").Value
Else MsgBox "Your version is current.", vbOKOnly End If
Case Is >= rst.Fields("MinimumVersionID").Value
If Not IsNull( _ rst.Fields("NonCurrentMessage").Value) Then MsgBox rst.Fields("NonCurrentMessage").Value & _ " The current version is: " & _
Trang 18rst.Fields("Version").Value Else
MsgBox "Your version is out of date but still " & _ "compatible.", vbOKOnly
End If Case Is < rst.Fields("MinimumVersionID").Value
If Not IsNull( _ rst.Fields("NonCompatibleMessage").Value) Then MsgBox rst.Fields("NonCompatibleMessage").Value & _ " The current version is: " & _
rst.Fields("Version").Value Else
MsgBox "Your version is out of date and no " & _ "longer compatible.", vbOKOnly + vbCritical End If
Case Else ' greater than current version in database ' database not updated
' or incorrect version number in workbook MsgBox "You are using a version newer " & _
ExitPoint:
Set rst = Nothing Exit Sub
ErrHandler:
MsgBox "Error checking version: " & Err.Description, vbOKOnly Resume ExitPoint
End Sub ' Retrieves the version ID associated with the version ' indicated in this workbook
Private Function GetVersionID() As Integer
On Error GoTo ErrHandler sVersion = oSettings.Item("App Version").Value ' SQL statement to retrieve list of employees
Trang 19If rst.State = adStateOpen Then rst.Close ExitPoint:
Set oSettings = Nothing Set rst = Nothing Exit Function ErrHandler:
GetVersionID = -1 Resume ExitPoint End Function
' Generic function to retrieve a query into a recordset Private Function QueryDB(sSQL As String) As ADODB.Recordset Dim sConn As String
Dim rst As ADODB.Recordset
On Error GoTo ErrHandler
Set QueryDB = rst ExitPoint:
Set rst = Nothing Exit Function ErrHandler:
Debug.Print "QueryDB error: " & Err.Description Set QueryDB = Nothing
Resume ExitPoint
Trang 20End Function ' Retrieve the connection string stored on ' the settings worksheet
Private Function GetConnection() As String Dim oSettings As New Settings
On Error GoTo ErrHandler ' Connection details - this is the kind of thing ' that you can use the Settings class for GetConnection = oSettings.Item("Version Connection").Value ExitPoint:
Set oSettings = Nothing Exit Function
End Function ' Check to see if a connnection can be made to the database Private Function IsConnectionAvailable() As Boolean
Dim sConn As String Dim conn As New ADODB.Connection
On Error GoTo ErrHandler sConn = GetConnection conn.Open sConn
If conn.State = adStateOpen Then conn.Close IsConnectionAvailable = True
ErrHandler:
IsConnectionAvailable = False Resume ExitPoint
Trang 21as current, the query orders the records in descending order by VersionID, and only the first record
is used Because VersionID is an AutoNumber field in this example, it should represent the last record that was added (and is marked as current) Once you have the data associated with the current version from the database, you need to figure out what version is indicated in the workbook To do this, I used the GetVersionID procedure to query the database for the VersionID associated with the version indicated in the workbook GetVersionID returns –1 if it cannot find the VersionID associated with a given version Anyway, CheckVersion compares (using a Select…Case statement) the VersionID associated with the workbook’s version to the VersionID of the version that is flagged in the database as current to figure out which message to display to the user
QueryDB is a fairly generic procedure used to query the database QueryDB depends on the Connection procedure to retrieve the connection string stored on the Settings worksheet Figure 22.5 demonstrates an example of basic version awareness
Get-So there you have a basic example of version awareness You could call the PerformVersionCheck procedure from the Workbook Open event procedure and/or call the procedure when the user interacts with a given user interface element such as a command button or menu item If you spend more than five minutes thinking about it, I bet you could come up with a decent list of enhancements that you could easily implement For example, because you have to go to the database to check version info, why not use this database for more things such as news items or messages that are displayed somewhere in the workbook You could also build in functionality for basic self-healing For example, maybe you have a table that contains formula fixes that lists worksheet name, cell address, and new formula You could build a process to look in this table and then “fix” a workbook with corrected formulas, values, or whatever To learn more, read on.…
Trang 22Fear Not When Things Go Wrong
Mistakes happen—if you haven’t learned that yet, if you build any applications that get distributed
to other users, you will Whether it is through programmer error, misinformation supplied to programmers, or misunderstanding Depending on the severity of the consequences of the mistake, how widely the application is distributed, and other factors, the anxiety associated with the mistake will vary widely Although it is often embarrassing and tempting to point fingers, don’t blow your top You have a lot of options available for rectifying the situation
Of course, you can always fix the error and redistribute Occasionally, however, this may be impractical and should be seen as a last-resort option For example, if your users have already expended a lot of effort entering information into a financial model, they will loathe anything that requires them to throw away their work and start from scratch Inconvenience notwithstanding, starting over may be expensive to boot For example, if you’ve distributed an application to 500 users and each user has 2 hours of time invested in customizing, entering data into, or otherwise working with the application in a way that a new version will undo, that’s 1000 hours of work that would be thrown out All of a sudden, the extra work associated with a solution that fixes existing applications rather than replaces them seems worth it Hmm, an extra 8 or 16 hours to figure out how to distribute a service pack or 1000 hours of collective user effort I know which one I’d recommend
In the previous section, I hinted at using a version database to provide self-healing functionality Due to space concerns, I’m not going to show you how to do this However, I will show you a solution using many of the procedures you’ve seen throughout this book From there, it’s not much of a stretch
to make the modifications necessary to make this work from the database
You’ve already seen the framework that can enable this functionality From a high level you need to
1 Provide a way for the user to indicate which workbook(s) need to be fixed
2 Loop through the set of workbooks indicated by the user
3 Open, fix, save, and close each workbook
Keeping these three needs in mind, go back to Chapter 6 and skim over the ProcessFileBatch listing (Listing 6.1) This procedure, along with the procedures it depends on, handles maybe 90 percent of the work you need to do to provide service pack functionality All you need to do is write a procedure
to fix the workbook and then call this procedure from within ProcessFileBatch
As an example, let’s say you need to fix a bunch of formulas in a workbook that you released You could use a procedure similar to Listing 22.4 to fix the workbook and call it from ProcessFileBatch
Note I’ve included ProcessFileBatch and its dependencies in Listing 22.4 for your convenience For discussion and analysis of these procedures please refer back to Chapters 5 and 6
Listing 22.4: Simple Procedure to Fix a Workbook
Option Explicit Private Sub FixWorkbook(wb As Workbook) Dim ws As Worksheet
Trang 23Set ws = Nothing End Sub
Sub ProcessFileBatch() Dim nIndex As Integer Dim vFiles As Variant Dim wb As Workbook Dim bAlreadyOpen As Boolean Dim sFile As String
On Error GoTo ErrHandler
Application.ScreenUpdating = False
' Get the workbook
End If Application.StatusBar = "Processing workbook: " & wb.Name ' Code to process the file goes here
Trang 24FixWorkbook wb ' Close workbook unless it was already open
If Not bAlreadyOpen Then Debug.Print "Closing workbook: " & wb.Name wb.Close True
ErrHandler:
Application.StatusBar = False Application.ScreenUpdating = True End Sub
' This function checks to see if a given workbook ' is open or not This function can be used ' using a short name such as MyWorkbook.xls ' or a full name such as C:\Testing\MyWorkbook.xls Function IsWorkbookOpen(sWorkbook As String) As Boolean Dim sname As String
Dim sPath As String Dim sFullName As String
On Error Resume Next IsWorkbookOpen = True ' See if we were given a short name or a long name
If InStr(1, sWorkbook, "\", vbTextCompare) > 0 Then ' We have a long name
' Need to break it down sFullName = sWorkbook BreakdownName sFullName, sname, sPath
If StrComp(Workbooks(sname).FullName, sWorkbook, 1) <> 0 Then IsWorkbookOpen = False
End If Else ' We have a short name
If StrComp(Workbooks(sWorkbook).Name, sWorkbook, 1) <> 0 Then IsWorkbookOpen = False
End If End If End Function
Dim sFilter As String
Trang 25Dim bMultiSelect As Boolean
GetExcelFiles = Application.GetOpenFilename(FileFilter:=sFilter, _ Title:=sTitle, MultiSelect:=bMultiSelect)
End Function Function GetShortName(sLongName As String) As String Dim sPath As String
Dim sShortName As String BreakdownName sLongName, sShortName, sPath GetShortName = sShortName
End Function
Sub BreakdownName(sFullName As String, _
ByRef sname As String, _ ByRef sPath As String) Dim nPos As Integer
Else 'Invalid sFullName - don't change anything End If
End Sub ' Returns the position or index of the first ' character of the file name given a full name ' A full name consists of a path and a filename ' Ex FileNamePosition("C:\Testing\Test.txt") = 11 Function FileNamePosition(sFullName As String) As Integer
Do While bFound = False
Trang 26bFound = True Else
' Working right to left nPosition = nPosition - 1 End If
Loop
If bFound = False Then FileNamePosition = 0 Else
FileNamePosition = nPosition End If
End Function
Believe it or not, some service packs are as easy as the FixWorkbook procedure Of course, other times you’ll have to overcome many more issues For example, you might have to consider whether worksheets have been renamed, added, or deleted Also, rows and columns may shift as they are added
or deleted In situations such as this, you’ll come to appreciate your foresight in incorporating multiple points of reference in your workbook and other decisions you made during the development process “just in case.” Named ranges and worksheet code names come in very handy for this purpose
Summary
Depending on the functionality delivered by your solution, you may choose to deliver your application in one of three forms: as a standard workbook, as a template, or as an add-in The most common form for an application is as a standard workbook Standard workbooks have the advantage of being easy to distribute as well as easy to use and develop
Templates are useful for situations in which your application will be used repeatedly, but each use needs to remain distinct from others Though templates aren’t hard to use, you’ll have to provide some basic instruction to some of your users on how to use a template and how to set it up (unless you write a utility to install it in the correct location) You can help minimize the ills associated with upgrading templates by putting a master template on your network and having users install shortcuts
to the master copy in their template directories
Add-ins are useful in situations in which you need to develop functionality that needs to be accessed from all workbooks An add-in essentially extends the functionality of Excel Though you construct an add-in using a normal Excel workbook, when a user installs an add-in, they do not see any of the underlying Excel structure (the worksheets) that makes up the add-in
Trang 27Regardless of which form you choose to use, once you release an application invariably you’ll need
to release updated versions in the future that fix bugs or provide additional functionality Consider the possibility of future updates from day one so that you can incorporate features into the application that will aid the update process
For the ultimate amount of control, consider building version awareness into your applications Version awareness functionality can range from the simple version-checking example presented in this chapter to elaborate self-updating/healing solutions This type of functionality requires a central versioning database of some sort to store version information
Finally, when things don’t go right or you have an urgent need to fix a widely distributed application, don’t fret It is fairly easy to create your own “service pack” that you can distribute to your users with which they can fix their copy of the application