Adding a Field to a Linked Database Table
I have to admit I am always collecting odd procedures that I reuse. I usually dump them into a generic module that gets included in every database I build. The procedures below are a collection of ones I built over the years to do a number of things related to tables.
Most Access developers have rolled out a database with a backend file and later found they needed to change a table in the backend Access database. If there is only one installation, it is relatively easy to throw everyone off and make the changes. If like Project Perfect who have been selling Project Administrator software for about 15 years. there are tens of thousands of databases out there, it gets more complicated.
We developed the module below to add a field to the backend Access database from the frontend Access database. The trick is to import the table into the frontend, make the changes then export it to the backend overwriting the existing table. Of course you then need to link the table to the frontend.
Procedures – Brief Description
There are five procedures in the module.
subAddTableFields | Main calling procedure. After various checks, import, modifies and exports tables. Calls relink procedure. |
funTableExists
|
Check a table by that name exists.
|
funGetLinkedDBName
|
By passing a table name you know exists, you can find the file name of the linked database.
|
subLinkToOneBETable | Links a file name in the backend database |
funCheck4Nothing | Checks to see if a value is blank, null or zero. |
Use the Add Field to Linked Table Procedure
You need to pass a few values to the procedure. They are:
strTableName | The name of the linked table (e.g. tblCustomers, tblProducts) |
strFieldName | The name of the new field (e.g. CustomerType, ProductModel) |
strFieldType | The type of field including any size (e.g. TEXT(20), LONG) |
strIndex | This field is optional but can be used to set values such as nulls allowed or no nulls. (e.g. NULL) |
Here is an example. We wanted to add a field called “Period” to a table called tblWeeklyReport. We had a weekly report but decided to let users set their own period in case they wanted to do a 2 weekly or monthly report. We decided to make the type long integer and as many people would be using the same number in the field (7 days or 14 days, we wanted to allow duplicates. This is the calling line for the procedure.
subAddTableField “tblWeeklyReport”, “Period”, “Long”, “NULL”
The VBA Code
‘————————————————————————————— Public Sub subAddTableField(strTableName As String, strFieldName As String, strFieldType As String, Optional strIndex As String) Dim dbs As Database On Error GoTo Error_subAddTableField ‘————————————————————— If funTableExists(strTableName) = False Then GoTo Exit_subAddTableField End If ‘————————————————————— strTablesDatabase = funGetLinkedDBName(strTableName) If strTablesDatabase = CurrentDb.Name Then DoCmd.DeleteObject acTable, strTableName ‘ Delete the table Could be left over from previous modification. Not likely but best to be safe. End If ‘————————————————————— On Error GoTo Insert_Field ‘ If error, the field does not exist strSQL = “SELECT ” & strTableName & “.” & strFieldName & ” FROM ” & strTableName & “;” Set dbs = CurrentDb Exit_subAddTableField: On Error GoTo 0 Exit Sub Insert_Field: ‘————————————————————— Set tdfLinked = dbs.TableDefs(strTableName) ‘ Select a table. If no database, this will fail. DoCmd.DeleteObject acTable, tdfLinked.Name ‘ Delete the link to the table ‘————————————————————— DoCmd.TransferDatabase acImport, “Microsoft Access”, strTablesDatabase, acTable, strTableName, strTableName strSQL = “ALTER TABLE ” & strTableName & ” ADD COLUMN ” & strFieldName & ” ” & strFieldType & ” ” & Nz(strIndex, “”) subRunUpdateQuery strSQL DoCmd.TransferDatabase acExport, “Microsoft Access”, strTablesDatabase, acTable, strTableName, strTableName ‘————————————————————— DoCmd.DeleteObject acTable, tdfLinked.Name ‘ Delete the link Error_subAddTableField: MsgBox “An unexpected situation arose in your program.” & vbCrLf & _ Resume Exit_subAddTableField End Sub ‘————————————————————————————— Dim dbs As Database On Error GoTo Error_funTableExists funTableExists = False Set dbs = CurrentDb ‘————————————————————– For Each tbl In dbsExist Next tbl Exit_funTableExists: Error_funTableExists: Resume Exit_funTableExists End Function ‘————————————————————————————— Dim dbs As DAO.Database On Error GoTo Error_NoTable ‘ Handles table not found ‘————————————————————— Set dbs = CurrentDb() On Error GoTo Error_funGetLinkedDBName ‘ Normal error handling ‘————————————————————— funGetLinkedDBName = Right(varReturn, Len(varReturn) – (InStr _ Exit_funGetLinkedDBName: Error_NoTable: Error_funGetLinkedDBName: Resume Exit_funGetLinkedDBName End Function ‘————————————————————————————— Public Sub subLinkToOneBETable(strTableName As String, strBEPath As String) Dim dbs As Database ‘————————————————————– On Error GoTo Error_subLinkToOneBETable If funFileExists(strBEPath) = False Then Call MsgBox(“The path provided for the back end database is incorrect. Please ensure the correct path is provided. ” _ GoTo Exit_subLinkToOneBETable End If ‘————————————————————– Set tdf = Nothing ‘————————————————————– Set dbs = OpenDatabase(strBEPath, False, False) ‘ This will fail if there is a password on the BE If funCheck4Nothing(tdfLinked.Name) = True Then ‘ No tabledef exists strPW = InputBox(“Please enter the database password.” & _ Set dbs = OpenDatabase(strBEPath, False, False, “;pwd=” & strPW) ‘ Open the database using the password End If If funTableExists(tdfLinked.Name) Then DoCmd.DeleteObject acTable, tdfLinked.Name End If DoCmd.TransferDatabase acLink, “Microsoft Access”, _ DoCmd.Hourglass False Exit_subLinkToOneBETable: Error_subLinkToOneBETable: Resume Exit_subLinkToOneBETable End Sub ‘————————————————————————————— If IsNull(var) Or var = “” Or var = 0 Then funCheck4Nothing = True Else funCheck4Nothing = False End If Exit_funCheck4Nothing: Error_funCheck4Nothing: MsgBox “An unexpected situation arose in your program.” & vbCrLf & _ Resume Exit_funCheck4Nothing End Function |
Calling the Procedure
The easiest way to do this is to use the autoexec macro to call a function. The function in turn calls the subroutine to add the field. We have a function that calls a number of procedures to do things like confirm registration details, check for updates online for the program and also run any maintenance. A procedure called subMaintenance calls any fixes or database structure changes. By putting any change routines in subMaintenance we can quickly see what maintenance needs to run for each release.
The sequence is:
- autoexec macro calls a function called funInitialise.
- funInitialise calls a number of other procedures to check for updates, validate registration, set user security etc. One of those procedures called is subMaintenance.
- subMaintenance runs the table modification.
If the Field Exists
Once the change has taken place, the procedure will continue to run. At the start of the procedure, the program looks for the table. If it finds it, it looks for the field to be added. If it finds the field, it exits. If running the SQL query causes an error it means it cannot find the field. In this case the update part of the procedure runs.