One of the hardest things to manage in Excel solutions is version control. You know, that embarrassing knowledge that there are orphaned versions of your application floating through your company. And that horrifying sense that these useless versions are actually being used. There is nothing more embarrassing than asking one of your users to try and catch the splash screen to read off the version number. That's just sad dude…sad.
In this post, I'll show you a couple of techniques that will help you hack your own version control for your Excel solutions (BTW: This works for Access too).
The Basic Idea
The basic idea behind this technique is actually very simple. You place a version number internally into your Excel solution. Then you keep a version number in network file or a server table.
When your Excel solution opens, it calls back to your server/network file and looks at the version number there. If the internal number matches, the external number, then the Excel solution continues. If the two numbers don't match, then Excel pops up a message and quits.
There are certainly dozens of ways to get this to work. However, I'll show you two: A method for those of you who don't use a database server, and a method for those of you who have access to a database server.
I don't have a database server:
If you don't have the luxury of a database server, you can implement version control using an XML file. Here are the steps:
Step 1: Create your XML file
Open up Notepad or some other text editor and enter this XML code. Notice the Version element (in line three) is tagged with a 1.
-
<!--xml version="1.0-->
-
<VersionCheck>
-
<Version>1<Version>
-
</VersionCheck>
As you create new versions of your application, the idea is to edit this XML code to increment the version number.
Step 2: Save your XML file
Save your Notepad file as a VersionCheck.xml and place it into a location your users can get to. Typically, this means saving your XML file onto a shared drive or a network directory.
Step 3: Create an XML Map to Your VersionCheck File
Open your Excel program/solution, then go to the Developer tab on the Ribbon. There, you will click Import under the XML group.

Select the XML file you are mapping.

Then assign a place to park it. In this case, I'll just pick A1.

Make sure you give the tab with your XML map a distinct name. Here, I'm using VersionCheck.

Step 4: Build an On Open Event
Once you have your XML map in place, you need to create an Open event for the workbook that will:
- Refresh the XML Map
- Compare the internal version number with the external number
- Close if there is no match
Open the VBE and click "ThisWorkbook". Then choose Workbook from the Object selector.

Enter the following code. Notice that you are setting a Constant called ThisVersion. This is what you'll use as the internal version number.
-
Private Sub Workbook_Open()
-
Const ThisVersion As Integer = 1 '<--Change this internal version number
-
-
'Refresh XML Binding
-
ActiveWorkbook.XmlMaps("VersionCheck_Map").DataBinding.Refresh
-
-
'Exit if external version number doesn't match internal number
-
If Sheets("VersionCheck").Range("A1").Value <> ThisVersion Then
-
MsgBox "Please download the current version", vbCritical, "You don't have the lastest version!"
-
ThisWorkbook.Close SaveChanges:=True
-
Exit Sub
-
End If
-
-
End Sub
The idea is that each time you build a new version of your application; you will increment both the internal ThisVersion constant and the number in the XML - so they match.
Any user using the latest file, will have the correct match. Any user using an older file will get a message telling them to get the new version.

I have a database server:
If you've got access to a database server, then it's a bit simpler for you.
First, create a new table in your database called VersionCheck, with one field called Version. Fill it with the number 1.
Next, enter this code in the workbook's Open Event.
-
Private Sub Workbook_Open()
-
'Be Sure to set a Reference to the Microsoft ActiveX Data Objects Library.
-
Dim MyRecordset As ADODB.Recordset
-
Dim MySQL As String
-
-
'Change this to the appropriate database connection string
-
Const MyConnection As String = "Provider=sqloledb;" & _
-
"Data Source=204.204.20.24;" & _
-
"database=SOSDB;" & _
-
"User ID=SOSUSER;" & _
-
"Password=SOSPASSWORD"
-
-
Const MyVersion As Integer = 1 '<;--Change Version Number Here
-
-
'Start Recordset and connect to server
-
Set MyRecordset = New ADODB.Recordset
-
MySQL = "SELECT [Version] FROM [dboVersionCheck]"
-
MyRecordset.Open MySQL, MyConnection, adOpenStatic, adLockReadOnly
-
-
'Exit if external version number doesn't match internal number
-
If MyRecordset!Version <> MyVersion Then
-
MsgBox "Please download the current version", vbCritical, "You don't have the latest version!"
-
Exit Sub
-
End If
-
End Sub
Notes:
- Obviously, your users will need to be able to hit the designated external server or network file for this to work.
- As a courtesy, I typically take the user to the download site automatically. But that's for another post.
- I know about SharePoint version control - this is different.
If you have a different/better way to handle version control in your applications, I'd love to hear it.
RELATED STUFF
- Zoom into Spreadsheet on Double-Click
- VBE Tips I Wish I Knew 5 Years Ago
- Highlighting the Active Row and Column
- Using the Switch Function in Excel
- Why is Excel so Negative about Hiding Subtotals
- Running an Access Parameter Query from Excel
- Creating a Zoom Box in Excel
- Smart Scroll Bars in Excel
- Excel Zoom Box Font Size Follow Up
- Fun with Custom Lists


For version control/automatic updates, I have implemented a class that wraps the WinHTTP API, and use it to download a plain TXT file from the download server. The version number is in the first line of the text file; subsequent lines contain a summary of the changes that is displayed in the userform, so that the users can decide whether they want to update or not. The same clsWinHTTP class is also used to download the update itself. All in all, users have to click just once, the rest is automatic.
"And that horrifying sense that these useless versions are actually being used." -- In those cases where users send me feedback, I'm often surprised what old versions are still being used. I think a lot of people have updating angst!
@daniel
I would love to see in action. Can you post some example code in here? Really the part I'm interrested is the auto downloading of the new version. We don't have a HTTP server so I would like to use datapig's version control along with the ability to auto download.
Thanks
Sometimes your updates won't be critical, so you may want to specify a minimum version required - any version older than this will not run, while any version that is newer will simply tell you there is a newer version, and suggest you get it.
Using a spreadsheet to download a newer version of itself is kinda tricky, so one solution is to launch your app with a separate little spreadsheet that checks versions and does any updating, then it launches the main spreadsheet.
Oh, and I might just save the version number as text in an ordinary text file or web page. No need for databases and XML unless you're building industrial strength software.
Drew,
to see my autoupdate in action, you can download an older release of my addin (e.g.: http://sourceforge.net/projects/xltoolbox/files/XL_Toolbox_2.62b.exe/download ) and install it. When you start up Excel (and have an internet connection), you should see the update prompt immediately. The addin is open source, so you can examine the code yourself.
As dermotb pointed out, updating "in place" is essentially not possible. My addin downloads the update installer (generated with InnoSetup), then starts the installer with a special "/update" command line switch. This causes the installer to shut down Excel (by sending a WM_CLOSE message through the Windowing system). When the setup process is finished, the installer restarts Excel.
Interesting. Generalizing the pattern, you could use the XML-Map Refresh to perform any initialization with current data. For example, you could load a set of active jobs into a timesheet workbook.
Nope, that's no better - and there isn't a 'preview post' button to help me with trial and error.
Therefore, I surrender (somewhat gracefully) and if anyone is actually interested in what the .xml structure looks like, we'll figure out a way...
James: try again using these vb tags without the quotes
"["vb"]"
Code goes here
"[/"vb"]"
Jan Karel Pieterse has an article on his site about using the URLDownloadToFile API to check a website for updates and grab the latest file. Can't find a link right now though.
I have a need to do version control in other-than-Office applications that do use VBA, and so created
an all-VBA (no worksheet) version that doesn't use a database server. In general, there will be more
than one application that needs version control, the following .xml file structure was created:
Supposedly, it's possible to select a single node by spedifying an element value with syntax in VBA that looks like:
Dim objElement As MSXML2.IXMLDOMElement
Set objElement = objXML.SelectSingleNode("//*[@progName=""TXO_Gate_Compliance_Analyzer.xlsm""]")
But I've not been able to puzzle out any version that works. If it DID work, it would (probably) be faster than the looping over all program elements implemented below. If anyone knows what the correct syntax is, I'd love to learn it!
Can anyone take a stab at the right syntax?
BTW - lots of credit to Tim Hastings' blog entry at http://www.nonhostile.com/howto-xml-vb6.asp - it gave
me a big leg up on getting this to work...
Great solution to one of my biggest headaches - are you planning on following up with how to take users to the latest version automatically?!
Thx.