I found the following function while browsing the Web that allows me to dynamically link a table to my Access database at the execution:
Function createAttached(strTable As String, strPath As String, strBaseTable As String) As Boolean
'************************************************************************************
'* Create an attached table in the current database from a table in a different MDB file.
'* In: *
'* strTable - name of linked table to create *
'* strPath - path and name of MDB file containing the table *
'* strBaseTable - name of table in strPath MDB *
'* Out: *
'* Return value: True/False, indicating success *
'* Modifies: *
'* Nothing, but adds a new table. *
'************************************************************************************
On Error GoTo CreateAttachedError
Dim tdf As TableDef
Dim strConnect As String
Dim fRetval As Boolean
Dim myDB As Database
DoCmd.SetWarnings False
Set myDB = CurrentDb
Set tdf = myDB.CreateTableDef(strTable)
With tdf
.Connect = ";DATABASE=" & strPath
.SourceTableName = strBaseTable
End With
myDB.TableDefs.Append tdf
fRetval = True
DoCmd.SetWarnings True
CreateAttachedExit:
createAttached = fRetval
Exit Function
CreateAttachedError:
If Err = 3110 Then
Resume CreateAttachedExit
Else
If Err = 3011 Then
Resume Next
End If
End If
End Function
This script works, however, if the table is already linked, it just does nothing (but an error event is still triggerered). I would like the same script to delete the linked table if it exists, or at least refresh that link so that the path is the right one. I have no idea of how to do this, it's probably quite simple but I don't know where to start.
Thank you.
Here's what I use. It also tests for if the table is a linked table before trying to refresh the link.
This code assumes that the db you're linking to is in the same folder as the db you're linking from. If not, remove the "Application.CurrentProject.Path" and add the appropiate path.
Public Sub RelinkTables()
Dim dbs As Database
Dim Tdf As TableDef
Dim Tdfs As TableDefs
Set dbs = CurrentDb
Set Tdfs = dbs.TableDefs
For Each Tdf In Tdfs
If Tdf.SourceTableName <> "" Then 'If the table source is other than a base table
Tdf.Connect = ";DATABASE=" & Application.CurrentProject.Path & "\filename.accdb" 'Set the new source
Tdf.RefreshLink 'Refresh the link
End If
Next 'Goto next table
End Sub
Related
I want to export each table of one database in separate accdb files and I don't get it.
With the following code -> https://www.devhut.net/2012/09/27/ms-access-vba-export-database-objects-to-another-database/ the destination database must already exist.
How can I create e.g. for table1 the file table1.accdb and export only one table into this database? If the main database has 10 tables 10 files should be created and the belonging table should export as well.
Here is how:
Public Function ExportTables()
Const Path As String = "C:\Test\"
Dim Workspace As DAO.Workspace
Dim Database As DAO.Database
Dim Table As DAO.TableDef
Dim Tablename As String
Set Workspace = DBEngine(0)
For Each Table In CurrentDb.TableDefs
If Table.Attributes = 0 Then
' This is a local table and not a system table.
Tablename = Table.Name
Set Database = Workspace.CreateDatabase(Path & Tablename, dbLangGeneral)
DoCmd.TransferDatabase acExport, "Microsoft Access", Database.Name, acTable, Tablename, Tablename
Debug.Print "Exported " & Tablename
End If
Next
End Function
Here is some code to create a Database
Private Sub CreateDatabase(nameOfDatabase As String)
On Error Resume Next
Dim accessApp As Access.Application
Set accessApp = New Access.Application
accessApp.DBEngine.CreateDatabase nameOfDatabase & ".accdb", DB_LANG_GENERAL
accessApp.Quit
Set accessApp = Nothing
End Sub
At work we have MS Access databases that use sharepoint lists as linked tables because we like the stability. The address of our sharepoint site is going to change. I want to run a VBA sub to change the tables from the old address to the new. Here is what I have so far, but there are two problems:
It does not automatically detect which tables are sharepoint lists without asking
Some tables are 'participating in one or more relationships' and give an error when deleted
How do I make it better?
Sub ChangeSPTables()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim MBr As VbMsgBoxResult
Dim N As String
Set db = CurrentDb
For Each tdf In db.TableDefs
If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") Then
N = tdf.Name
MBr = MsgBox("Delete and relink " & N & "?", vbYesNoCancel)
If MBr = vbYes Then
DoCmd.DeleteObject acTable, N
DoCmd.TransferSharePointList acLinkSharePointList, "https://redacted", N
End If
End If
Next
Set tdf = Nothing
Set db = Nothing
End Sub
Related tables can't be deleted but can be dropped. Adding a table will also add related tables, so I was having troubles with duplicate adds. I stored all names to delete first and re-add later (if they don't already exist). The sharepoint address is part of the connection string so I was able to sift the tables I wanted like that.
Edit: Using the DoCmd.TransferSharePointList can cause lists with lookup columns to come in as read-only. For lists like that, delete and add them manually after running.
Sub ChangeSPTables()
'Step through all table definitions and check if the old sharepoint address appears in the connection string
'If so, stores the name of the table, deletes all such tables, and re-adds them from the new sharepoint address
'The list is used because sometimes other tables are brought in automatically as relationships and I don't
'want extra copies or instances where the table has a 1 on the end of the name
'Will not work on things that have been renamed since they were brought in from sharepoint
'You should probably only run this on a copy of the database for saftey's sake
Dim db As dao.Database
Dim tdf As dao.TableDef
Dim MBr As VbMsgBoxResult
Dim i As Long: i = 1
Dim ListNames(1 To 20) As String 'Assumed to be 20 or less
'The old and new sharepoint addresses
Dim OldSP As String
Dim NewSP As String
OldSP = "https://old"
NewSP = "https://new"
Set db = CurrentDb
For Each tdf In db.TableDefs
If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") And InStr(1, tdf.Connect, OldSP) > 0 Then
ListNames(i) = tdf.Name
i = i + 1
Debug.Print tdf.Name 'For review of which tables were redone
db.Execute "drop table [" & tdf.Name & "]", dbFailOnError 'drop table avoids problems with relationships between tables
End If
Next
i = 1
Do Until ListNames(i) = ""
If IsNull(DLookup("Name", "MSysObjects", "Name='" & ListNames(i) & "'")) Then 'Some things get re-added by relationship
DoCmd.TransferSharePointList acLinkSharePointList, NewSP, ListNames(i)
End If
i = i + 1
Loop
'Hide the sharepoint tables
For Each tdf In db.TableDefs
If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") And InStr(1, tdf.Connect, NewSP) > 0 Then
Application.SetHiddenAttribute acTable, tdf.Name, True
End If
Next
Set tdf = Nothing
Set db = Nothing
End Sub
I'm working with a database in Access 2007, one front end and a few backends.
I like to convert all my linked tables to local for offline work so that i don't accidentally spoil the data.
I delete all the relations and tables and then run a saved import.
I'd like to recreate linked tables after I'm done with modifications. Problem is, Access won't save the import of linked tables. Is there a way to simply link all the tables from backend to frontend with VBA
I found this on the net that works, though slow
Function createAttached(strTable As String, strPath As String, strBaseTable As String) As Boolean
On Error GoTo CreateAttachedError
Dim tdf As TableDef
Dim strConnect As String
Dim fRetval As Boolean
Dim myDB As Database
DoCmd.SetWarnings False
Set myDB = CurrentDb
Set tdf = myDB.CreateTableDef(strTable)
With tdf
.Connect = ";DATABASE=" & strPath
.SourceTableName = strBaseTable
End With
myDB.TableDefs.Append tdf
fRetval = True
DoCmd.SetWarnings True
CreateAttachedExit:
createAttached = fRetval
Exit Function
CreateAttachedError:
If Err = 3110 Then
Resume CreateAttachedExit
Else
If Err = 3011 Then
Resume Next
End If
End If
End Function
https://www.microsoftaccessexpert.com/Microsoft-Access-Code-LinkTable.aspx
I am trying to output the name of all linked tables, including their fields which are Date/Time, and that fields values.
The following code can output the first table, field name and their first value, not all values, although when it gets to the next linked table, I get this error
Run-time Error '3622'
You must use the dbSeeChanges option with OpenRecordSet when accessing a SQL Server table that has an IDENTITY column.
Here is my code
Private Sub btnGetFields_Click()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim f As Field
Dim rst As DAO.Recordset
Dim numField As Integer
Set db = CurrentDb
For Each tdf In db.TableDefs
If Left$(tdf.Connect, 9) = "ODBC;DSN=" Then
Set rst = CurrentDb.OpenRecordset(tdf.Name)
numField = rst.Fields.Count
Debug.Print "Table: " & tdf.Name
For index = 0 To numField - 1
If rst.Fields(index).Type = dbDate Then
Debug.Print "Field: " & rst.Fields(index).Name; " Value : "; rst.Fields(index).Value
End If
Next
End If
Next
Set tdf = Nothing
Set db = Nothing
End Sub
I read something that if I'm using sql tables I should use ADO?
Any ideas?
You can continue to use your existing DAO code, just change
Set rst = CurrentDb.OpenRecordset(tdf.Name)
to
Set rst = CurrentDb.OpenRecordset(tdf.Name, dbOpenSnapshot)
That opens a static read-only Recordset, so dbSeeChanges is not required.
I have actually this little function working as supposed:
Function createAttached(strTable As String, strPath As String, strBaseTable As String) As Boolean
On Error GoTo CreateAttachedError
Dim tdf As TableDef
Dim strConnect As String
Dim fRetval As Boolean
Dim myDB As Database
DoCmd.SetWarnings False
Set myDB = CurrentDb
Set tdf = myDB.CreateTableDef(strTable)
With tdf
.Connect = ";DATABASE=" & strPath
.SourceTableName = strBaseTable
End With
myDB.TableDefs.Append tdf
myDB.TableDefs.Refresh
fRetval = True
DoCmd.SetWarnings True
CreateAttachedExit:
createAttached = fRetval
Exit Function
CreateAttachedError:
If Err = 3110 Then
Resume CreateAttachedExit
Else
If Err = 3011 Then
Resume Next
Else
If Err = 3012 Then
Set tdf = myDB.TableDefs(strTable)
tdf.Connect = ";DATABASE=" & strPath
tdf.RefreshLink
fRetval = True
GoTo CreateAttachedExit
End If
End If
End If
End Function
This code works fine, I can call the function as many times as I want to add links to tables from another database. However, I have about 30 tables to import from the same database and this script restarts from scratch everytime I call it. Because the database is located on another server, it takes about 1 min to link the 30 tables.
Is there anything I could do with that function to make it work faster when I need to link multiple tables from the same database? I would like it to work with multiple strTable and strBaseTable in parameters instead of one (maybe arrays?), but I don't know how to do this.
Thank you.
You can loop through the tabledefs collection in the external database or use a table of tables that lists all the tables to be connected and the external database.
Dim db As Database
Dim ThisDb As Database
Set ThisDb = CurrentDB
sDb = "z:\docs\test.accdb"
Set db = OpenDatabase(sDb)
For Each tdf In db.TableDefs
''Connect
If Left(tdf.Name, 4) <> "MSys" Then
If IsNull(DlookUp("Name","MsysObjects","Type In (1,4,5,6) And Name='" _
& tdf.Name & "'")) Then
DoCmd.TransferDatabase acLink, "Microsoft Access", _
sDb, acTable, tdf.Name, tdf.Name
Else
If ThisDb.TableDefs(tdf.Name).connect <> vbNullString Then
ThisDb.TableDefs(tdf.Name).connect = ";DATABASE=" & sDb
ThisDb.TableDefs(tdf.Name).RefreshLink
End If
End If
End If
Next
A table of tables would work in a similar fashion in that you can select the database (select distinct) from the table and loop through that recordset attaching the tables in a further selection (select table where database ...)
What you could also do is set up the database connect in a different sub as well as the database disconnect (which I might be missing here?).
So then the code that calls this script normally (I assume you have a loop) will look like this:
call function/sub that opens the connection to DATABASE= strPath
your loop that calls Function createAttached
call function/sub that closes the connection to DATABASE= strPath
That way you avoid the repetitive (usually time consuming) connection to the external database