How can I link a table from one MS Access Database (*.mdb or *.accdb) to another Access database in VBA?
Basically I just was to use VBA to replicate what the External Data wizard does.
I've googled this and I see many examples of how to update or relink tables and many examples of linking to SQL databases, but very few of simple linking tables between Access databases.
You can use the DoCmd.TransferDatabase Method to create a link to a table in another Access database.
DoCmd.TransferDatabase TransferType:=acLink, _
DatabaseType:="Microsoft Access", _
DatabaseName:="C:\share\Access\Example Database.accdb", _
ObjectType:=acTable, _
Source:="Addresses", _
Destination:="Addresses_link"
I included the option names hoping that would make it easier to track which option is which. But if that seems too verbose, you can omit the option names and do it all on one line:
DoCmd.TransferDatabase acLink, "Microsoft Access", "C:\share\Access\Example Database.accdb", acTable , "Addresses", "Addresses_link"
It's actually pretty easy--you just create a new tabledef and set its .connect property to an ODBC connection string that links to the other Access database.
Private Function LinkTable(LinkedTableName As String, TableToLink As String, connectString As String) As Boolean
Dim tdf As New dao.TableDef
On Error GoTo LinkTable_Error
With CurrentDb
.TableDefs.Refresh
Set tdf = .CreateTableDef(LinkedTableName)
tdf.Connect = connectString
tdf.SourceTableName = TableToLink
.TableDefs.Append tdf
.TableDefs.Refresh
End With
Set tdf = Nothing
End Function
The connection string would look something like this (taken from connectionstrings.com):
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\myFolder\myAccessFile.accdb;Persist Security Info=False;
DataWriter, are you not mixing DAO with ADO. That's like water & oil. The connectionstring is OLEDB (which is ADO) and TableDef is from CurrentDb (which is DAO).
The Connect Property of a TableDef is in the form of:
;DATABASE=[Full path to Db]\[Db Name]
Related
I have the following procedure that I run (in an MS Access module) on a regular basis to switch the linked table connection strings from Test to Production and vice-versa:
Public Function TableRelink()
Dim db As Database
Dim strConnect As String
Dim rs As Recordset
Dim tdf As TableDef
strConnect = "ODBC;DRIVER=SQL Server;SERVER=MYTESTSERVER;Trusted_Connection=Yes;APP=Microsoft Office 2013;DATABASE=MyDB;"
'strConnect = "ODBC;DRIVER=SQL Server;SERVER=MYLIVESERVER;Trusted_Connection=Yes;APP=Microsoft Office 2013;DATABASE=MyDB;"
CurrentDb.TableDefs.Refresh
For Each tdf In CurrentDb.TableDefs
If tdf.Connect <> "" Then
tdf.Connect = strConnect
tdf.RefreshLink
End If
Next
MsgBox ("Done!")
End Function
The above has been working for months and months. About a week ago, the following error randomly popped up. Then, after a few minutes, without any intervention on my part, it would allow me to run the procedure again. Today, the error has come back.
Run-time error '3035': System resource exceeded.
It is thrown on this line: tdf.RefreshLink
I did a Google search and found an article out there talking about a hotfix (that wouldn't install on my machine), and another about editing a registry value (which didn't seem fix it). As I type this, the error has stopped popping up and I can again re-link my tables, so at this point, I can't really do any more troubleshooting. I was reading another SO post talking about the lock file, but couldn't really make heads or tails of the accepted answer, and I'm not really convinced it has anything to do with my particular scenario. Does anyone know what might be causing this and/or what can be done to prevent it?
For reference, I'm running Office 365 ProPlus on a Win10 64-bit machine.
First, do use your db object:
Public Function TableRelink()
Dim db As Database
Dim strConnect As String
Dim rs As Recordset
Dim tdf As TableDef
strConnect = "ODBC;DRIVER=SQL Server;SERVER=MYTESTSERVER;Trusted_Connection=Yes;APP=Microsoft Office 2013;DATABASE=MyDB;"
'strConnect = "ODBC;DRIVER=SQL Server;SERVER=MYLIVESERVER;Trusted_Connection=Yes;APP=Microsoft Office 2013;DATABASE=MyDB;"
Set db = CurrentDb
db.TableDefs.Refresh
For Each tdf In db.TableDefs
If tdf.Connect <> "" Then
tdf.Connect = strConnect
tdf.RefreshLink
End If
Next
MsgBox ("Done!")
Set td = Nothing
Set db = Nothing
End Function
However, another and a much faster method is to have both sets of tables linked permanently and then rename them for switching the database.
For example, to switch from Production to Test:
Table1 -> Table1_p
Table2 -> Table2_p
...
Table1_t -> Table1
Table2_t -> Table2
Of course, if you modify a table schema, you must relink as usual.
I have already referenced other pages for my problem but I still can't get this to work. I feel a bit slow given that I have three examples below and still can't figure this out.
Changing linked table location programatically
Linked table ms access 2010 change connection string
Update an Access linked table to use a UNC path
Here is the code that I am using:
Dim tdf As TableDef
Dim db As Database
Set db = CurrentDb
Set tdf = db.TableDefs("DeviceListT")
tdf.Connect = "ODBC;DATABASE=" & CurrentProject.path _
& "\HarmonicProfileDatabase_be.accdb"
tdf.RefreshLink
The problem is that when I run it a window pops up.
I am not exactly sure what I am supposed to do with that nor do I want it to pop up in the first place as I will be giving the ms access files to someone else and they won't know what to do with this window either.
You are using SQL Server references but linking MS Access. For MS Access, you do not need an ODBC link, just refer to DATABASE:
DBFile = CurrentProject.path & "\HarmonicProfileDatabase_be.accdb
''Check the file exists
strFile = Dir(DBFile)
If strFile <> "" Then
With CurrentDb
For Each tdf In .TableDefs
''Check that this is a linked table
''It can be useful to use table of tables instead
If tdf.Connect Like "*HarmonicProfileDatabase_be.accdb*" Then
tdf.Connect = ";DATABASE=" & DBFile
tdf.RefreshLink
End If
Next
End With
MsgBox "Link HarmonicProfileDatabase_be.accdb"
Else
MsgBox "Problem"
End If
You could also use:
sConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
& DBFile & ";Jet OLEDB:Database Password=pw;"
Hey.
I have the main access database located on a stand alone PC off the network and i have a access database with linked tables on the network linked back to the stand alone PC. I have linked the tables by creating a network share to the stand alone PC and linking them though a path. Can i set it up so that when the database is opened it automatically updates the linked tables.
Ben
You can. I often find it convenient to use a small check form that runs on start-up (set through start-up options) and checks a variety of things, including linked tables. To this end, I also hold a table of linked tables on the local machine, although a list of linked tables can be obtained by iterating through the TableDefs collection, I think it is slightly safer to keep a list.
The check form can check all links and if a link is broken or missing, either ask the user for a new location or use a fixed location. If no problems are found, the form can close itself and open a menu or other form.
In the case of linking to a linked table, it is possible to get the connection to use from:
CurrentDB.TableDefs("TableName").Connection
Here are some more notes:
Sub RelinkTables(Optional strConnect As String = "")
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL
Dim tdf As DAO.TableDef
On Error GoTo TrapError
Set db = CurrentDb
If strConnect = "" Then
''Where Me.txtNewDataDirectory is a control on the check form
strConnect = "MS Access;PWD=databasepassword;DATABASE=" & Me.txtNewDataDirectory
End If
''Table of tables to be linked with two fields TableName, TableType
Set rs = CurrentDb.OpenRecordset("Select TableName From sysTables " _
& "WHERE TableType = 'LINK'")
Do While Not RS.EOF
''Check if the table is missing
If IsNull(DLookup("[Name]", "MSysObjects", "[Name]='" & rs!TableName & "'")) Then
Set tdf = db.CreateTableDef(RS!TableName, dbAttachSavePWD, _
rs!TableName, strConnect)
''If the table is missing, append it
db.TableDefs.Append tdf
Else
''If it exists, update the connection
db.TableDefs(rs!TableName).Connect = strConnect
End If
db.TableDefs(rs!TableName).RefreshLink
RS.MoveNext
Loop
Set db = Nothing
RS.Close
Set RS = Nothing
Exit_Sub:
Exit Sub
TrapError:
HandleErr Err.Number, Err.Description, "Relink Tables"
End Sub
I have an Access 2003 database MDB where all of the tables exist as linked tables within SQL Server 2005. The MDB file contains all of the ODBC information that points to the correct SQL Server and log-on credentials (trusted connection).
What I would like to do is add a new linked table to the MDB file however I am not sure how to go about specifying the ODBC connection information. When I try to add a new linked table I keep getting prompted to locate or create a DSN file. I don't want to have to create a new DSN entry on every machine, rather I would like all that information stored within the Access MDB file itself.
In the existing database I can "hover" over the table names and see the ODBC connection info as a tool-tip. All I need to do is add another linked table using the same connection information.
I do have access to the SQL Server where the tables are linked to,. I have already created the new table I wanted to add. I just need to find a way to link to it.
For what it's worth, I'm lazy. I keep a DSN on my development machine, and use it to create new linked tables. I then run Doug Steele's code to convert the links to dsnless connections before distribution of the front end to the end users.
You can use the connection string from an existing table, or you can do something like:
''This is a basic connection string, you may need to consider password and so forth
cn = "ODBC;DSN=TheDSNName;Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=TheDatabaseName;"
There are a few was to connect a table:
sLocalName = "TABLE_SCHEMA" & "_" & "TABLE_NAME"
With CurrentDb
If DLookup("Name", "MSysObjects", "Name='" & sLocalName & "'") <> vbNullString Then
If .TableDefs(sLocalName).Connect <> cn Then
.TableDefs(sLocalName).Connect = cn
.TableDefs(sLocalName).RefreshLink
End If
Else
''If the table does not have a unique index, you will neded to create one
''if you wish to update.
Set tdf = .CreateTableDef(sLocalName)
tdf.Connect = cn
tdf.SourceTableName = "TABLE_NAME"
.TableDefs.Append tdf
.TableDefs.Refresh
End If
End With
This will produce a message box if the table does not have a unique index
DoCmd.TransferDatabase acLink, "ODBC Database", cn, acTable, "TABLE_NAME", sLocalName
I was able to add the table successfully and wanted to detail the steps here.
I added the new table by clicking "New" within Access and chose "Link Table"
When prompted with the Link file dialog I chose ODBC from the file type list box
I created a new DSN item (only used for initial linking to table)
Proceed with creating DSN and you will follow process of linking to the table created in SQL Server
Table should show up in Access
I then created the following sub routine in the code module. It essentially loops through all your tables in Access that have ODBC connections and sets the proper ODBC connection info into the Table definitions. You can delete the DSN you created previously as it is no longer needed.
Public Sub RefreshODBCLinks()
Dim connString As String
connString = "ODBC;DRIVER=SQL Server Native Client 10.0;" & _
"SERVER=<SQL SERVER NAME>;UID=<USER NAME>;" & _
"Trusted_Connection=Yes;" & _
"APP=<APP NAME>;DATABASE=<DATABASE NAME>"
Dim db As DAO.Database
Dim tb As DAO.TableDef
Set db = CurrentDb
For Each tb In db.TableDefs
If Left(tb.Connect, 4) = "ODBC" Then
tb.Connect = connString
tb.RefreshLink
Debug.Print "Refreshed ODBC table " & tb.Name
End If
Next tb
Set db = Nothing
End Sub
NOTE ... To execute the above SubRoutine I just typed in it's name into the "immediate" windows within the Access code module. You could also create a macro that executes this routine and then whenever you create a new table you could just run the macro.
Thanks to "Remou" for his answer and assistance!
P.S. If you are interested in APP=<APP NAME> in the connection string and what it is for check out this article. http://johnnycoder.com/blog/2006/10/24/take-advantage-of-application-name/
I can create an Access mdb and add a linked table to an Sql Server database via ODBC. If I change the Sql Server that the ODBC is connecting to with the ODBC control panel applet the mdb still connects to the original Sql Server until Access is restarted.
Is there a way to relink these linked server tables without restarting Access?
EDIT: I would like to do this in code
You can use the code below to refresh all ODBC tables in your Access project to a given DSN.
How to use it
Just copy the code in a new or existing VBA module and, where you want to refresh the links, call it with the proper DSN for the new ODBC connection:
RefreshODBCLinks "ODBC;DRIVER=SQL Server Native Client 10.0;" & _"
"SERVER=SQLSERVER;UID=Administrator;" & _
"Trusted_Connection=Yes;" & _
"APP=2007 Microsoft Office system;DATABASE=OrderSystem;"
Also, have a look at the Access help for the TableDef.RefreshLink method.
Code version 1
Classic way of relinking but Access may keep connection information in memory if the tables have been used before RefreshODBCLinks is called.
Public Sub RefreshODBCLinks(newConnectionString As String)
Dim db As DAO.Database
Dim tb As DAO.TableDef
Set db = CurrentDb
For Each tb In db.TableDefs
If Left(tb.Connect, 4) = "ODBC" Then
tb.Connect = newConnectionString
tb.RefreshLink
Debug.Print "Refreshed ODBC table " & tb.Name
End If
Next tb
Set db = Nothing
End Sub
Code version 2
This will completely re-create the ODBC linked tables: the old ones will be renamed, then new tables using the given DSN will be created before deleting the old linked version.
Please make sure you test this and maybe add some code to better handle errors as necessary.
Note also that the parameter dbAttachSavePWD passed during creation of the ODBC table will save the ODBC password (if any) in Access. Just remove it if that's not what you need.
Public Sub RefreshODBCLinks(newConnectionString As String)
Dim db As DAO.Database
Dim tb As DAO.TableDef
Dim originalname As String
Dim tempname As String
Dim sourcename As String
Dim i As Integer
Set db = CurrentDb
' Get a list of all ODBC tables '
Dim tables As New Collection
For Each tb In db.TableDefs
If (Left(tb.Connect, 4) = "ODBC") Then
tables.Add Item:=tb.Name, key:=tb.Name
End If
Next tb
' Create new tables using the given DSN after moving the old ones '
For i = tables.count To 1 Step -1
originalname = tables(i)
tempname = "~" & originalname & "~"
sourcename = db.TableDefs(originalname).SourceTableName
' Create the replacement table '
db.TableDefs(originalname).Name = tempname
Set tb = db.CreateTableDef(originalname, dbAttachSavePWD, _
sourcename, newConnectionString)
db.TableDefs.Append tb
db.TableDefs.Refresh
' delete the old table '
DoCmd.DeleteObject acTable, tempname
db.TableDefs.Refresh
tables.Remove originalname
Debug.Print "Refreshed ODBC table " & originalname
Next i
Set db = Nothing
End Sub
One last thing: if you're still getting issues that require that you restart Access for the changes to be visible, then have a look at my code in Restarting and compacting the database programmatically on my site.
Note: Code Version 2 was inspired in part from this Access Web article.
What version of Access are you using? In 2000, you can go to Tools>Database Utilities>Linked Table Manager to change your settings.