Preserving linked tables for Access DBs in same folder when the folder changes

前端 未结 4 1532
陌清茗
陌清茗 2020-12-30 11:40

I\'ve got two Access databases that share linked tables. They are deployed together in a directory and accessed via code in a Word form.

How can I make sure that the

相关标签:
4条回答
  • 2020-12-30 11:54

    Update 14APR2009 I found that the previous answer I gave here was erroneous, so I updated it with new code.

    How to proceed

    • Copy the code below to a VBA module.
    • From code or from the Immediate window in the VBA IDE, simply type:

      RefreshLinksToPath Application.CurrentProject.Path
      

    This will now relink all the linked tables to use the directory where your application is located.
    It only needs to be done once or whenever you relink or add new tables.
    I recommend doing this from code every time you start your application.
    You can then move your databases around without problems.

    Code

    '------------------------------------------------------------'
    ' Reconnect all linked tables using the given path.          '
    ' This only needs to be done once after the physical backend '
    ' has been moved to another location to correctly link to    '
    ' the moved tables again.                                    '
    ' If the OnlyForTablesMatching parameter is given, then      '
    ' each table name is tested against the LIKE operator for a  '
    ' possible match to this parameter.                          '
    ' Only matching tables would be changed.                     '
    ' For instance:                                              '
    ' RefreshLinksToPath(CurrentProject.Path, "local*")          '
    ' Would force all tables whose ane starts with 'local' to be '
    ' relinked to the current application directory.             '
    '------------------------------------------------------------'
    Public Function RefreshLinksToPath(strNewPath As String, _
        Optional OnlyForTablesMatching As String = "*") As Boolean
    
        Dim collTbls As New Collection
        Dim i As Integer
        Dim strDBPath As String
        Dim strTbl As String
        Dim strMsg As String
        Dim strDBName As String
        Dim strcon As String
        Dim dbCurr As DAO.Database
        Dim dbLink As DAO.Database
        Dim tdf As TableDef
    
        Set dbCurr = CurrentDb
    
        On Local Error GoTo fRefreshLinks_Err
    
        'First get all linked tables in a collection'
        dbCurr.TableDefs.Refresh
        For Each tdf In dbCurr.TableDefs
            With tdf
                If ((.Attributes And TableDefAttributeEnum.dbAttachedTable) = TableDefAttributeEnum.dbAttachedTable) _
                   And (.Name Like OnlyForTablesMatching) Then
                    collTbls.Add Item:=.Name & .Connect, key:=.Name
                End If
            End With
        Next
        Set tdf = Nothing
    
        ' Now link all of them'
        For i = collTbls.count To 1 Step -1
            strcon = collTbls(i)
            ' Get the original name of the linked table '
            strDBPath = Right(strcon, Len(strcon) - (InStr(1, strcon, "DATABASE=") + 8))
            ' Get table name from connection string '
            strTbl = Left$(strcon, InStr(1, strcon, ";") - 1)
            ' Get the name of the linked database '
            strDBName = Right(strDBPath, Len(strDBPath) - InStrRev(strDBPath, "\"))
    
            ' Reconstruct the full database path with the given path '
            strDBPath = strNewPath & "\" & strDBName
    
            ' Reconnect '
            Set tdf = dbCurr.TableDefs(strTbl)
            With tdf
                .Connect = ";Database=" & strDBPath
                .RefreshLink
                collTbls.Remove (.Name)
            End With
        Next
        RefreshLinksToPath = True
    
    fRefreshLinks_End:
        Set collTbls = Nothing
        Set tdf = Nothing
        Set dbLink = Nothing
        Set dbCurr = Nothing
        Exit Function
    
    fRefreshLinks_Err:
        RefreshLinksToPath = False
        Select Case Err
            Case 3059:
    
            Case Else:
                strMsg = "Error Information..." & vbCrLf & vbCrLf
                strMsg = strMsg & "Function: fRefreshLinks" & vbCrLf
                strMsg = strMsg & "Description: " & Err.Description & vbCrLf
                strMsg = strMsg & "Error #: " & Format$(Err.Number) & vbCrLf
                MsgBox strMsg
                Resume fRefreshLinks_End
        End Select
    End Function
    

    This code is adapted from this source: http://www.mvps.org/access/tables/tbl0009.htm.
    I removed all dependency on other functions to make it self-contained, that's why it's a bit longer than it should.

    0 讨论(0)
  • 2020-12-30 11:54

    Are you referring to updating the links within your Word form, or the linked table links between your Access databases?

    For the former, the best way that I know is to keep your connection string(s) at the Module level within your Word document/VBA project and make them const strings. Then when setting the connection string for your ADO Connection objects, pass it the relative connection string const.

    For the latter, I would be tempted to use a relative path in the connection string to data within each Access database to the other. For example,

    Dim connectionString as String
    
    connectionString = ";DATABASE=" & CurrentProject.Path & "\[Database Name Here].mdb"
    

    if as you say, the databases are copied together to a different folder (I'm assuming into the same folder).

    0 讨论(0)
  • 2020-12-30 11:54

    Renaud's answer no longer works in Access 2010 with Excel or CSV files.

    I have made a few modifications:

    • Adapted to the current pattern for the connection string
    • Handled the database path differently for Excel files (includes filename) and CSV files (does not include filename)

    Here is the code:

    Public Function RefreshLinksToPath(strNewPath As String, _
    Optional OnlyForTablesMatching As String = "*") As Boolean
    
    Dim collTbls As New Collection
    Dim i As Integer
    Dim strDBPath As String
    Dim strTbl As String
    Dim strMsg As String
    Dim strDBName As String
    Dim strcon As String
    Dim dbCurr As DAO.Database
    Dim dbLink As DAO.Database
    Dim tdf As TableDef
    
    Set dbCurr = CurrentDb
    
    On Local Error GoTo fRefreshLinks_Err
    
    'First get all linked tables in a collection'
    dbCurr.TableDefs.Refresh
    For Each tdf In dbCurr.TableDefs
        With tdf
            If ((.Attributes And TableDefAttributeEnum.dbAttachedTable) = _
               TableDefAttributeEnum.dbAttachedTable) _
               And (.Name Like OnlyForTablesMatching) Then
                Debug.Print "Name: " & .Name
                Debug.Print "Connect: " & .Connect
                collTbls.Add Item:=.Name & ";" & .Connect, Key:=.Name
            End If
        End With
    Next
    Set tdf = Nothing
    
    ' Now link all of them'
    For i = collTbls.Count To 1 Step -1
        strConnRaw = collTbls(i)
        ' Get table name from the full connection string
        strTbl = Left$(strConnRaw, InStr(1, strConnRaw, ";") - 1)
        ' Get original database path
        strDBPath = Right(strConnRaw, Len(strConnRaw) - (InStr(1, strConnRaw, "DATABASE=") + 8))
        ' Get the name of the linked database
        strDBName = Right(strDBPath, Len(strDBPath) - InStrRev(strDBPath, "\"))
        ' Get remainder of connection string
        strConn = Mid(strConnRaw, InStr(1, strConnRaw, ";") + 1, InStr(1, strConnRaw, "DATABASE=") _
                    - InStr(1, strConnRaw, ";") - 1)
    
        ' Reconstruct the full database path with the given path
        ' CSV-Files are not linked with their name!
        If Left(strConn, 4) = "Text" Then
            strDBPath = strNewPath
        Else
            strDBPath = strNewPath & "\" & strDBName
        End If
    
        ' Reconnect '
        Set tdf = dbCurr.TableDefs(strTbl)
        With tdf
            .Connect = strConn & "Database=" & strDBPath
            .RefreshLink
            collTbls.Remove (.Name)
        End With
    Next
    RefreshLinksToPath = True
    
    fRefreshLinks_End:
        Set collTbls = Nothing
        Set tdf = Nothing
        Set dbLink = Nothing
        Set dbCurr = Nothing
        Exit Function
    
    fRefreshLinks_Err:
        RefreshLinksToPath = False
        Select Case Err
            Case 3059:
    
            Case Else:
                strMsg = "Error Information..." & vbCrLf & vbCrLf
                strMsg = strMsg & "Function: fRefreshLinks" & vbCrLf
                strMsg = strMsg & "Description: " & Err.Description & vbCrLf
                strMsg = strMsg & "Error #: " & Format$(Err.Number) & vbCrLf
                MsgBox strMsg
                Resume fRefreshLinks_End
        End Select
    End Function
    
    0 讨论(0)
  • 2020-12-30 12:18

    I am unfortunately still on Access 2007. I started with one of the code blocks above which was not working for me. Having less access vba power I simplified it to only the first loop which gets the table paths and updates it in place. The next guy running into this can comment or update.

    Option Compare Database

    '------------------------------------------------------------'
    ' Reconnect all linked tables using the given path.          '
    ' This only needs to be done once after the physical backend '
    ' has been moved to another location to correctly link to    '
    ' the moved tables again.                                    '
    ' If the OnlyForTablesMatching parameter is given, then      '
    ' each table name is tested against the LIKE operator for a  '
    ' possible match to this parameter.                          '
    ' Only matching tables would be changed.                     '
    ' For instance:                                              '
    ' RefreshLinksToPath(CurrentProject.Path, "local*")          '
    ' Would force all tables whose ane starts with 'local' to be '
    ' relinked to the current application directory.             '
    '
    ' Immediate window type
    ' RefreshLinksToPath Application.CurrentProject.Path
    
    '------------------------------------------------------------'
    Public Function RefreshLinksToPath(strNewPath As String, _
        Optional OnlyForTablesMatching As String = "*") As Boolean
    
        Dim strDBPath As String
        'Dim strTbl As String
        'Dim strMsg As String
        Dim strDBName As String
        Dim dbCurr As DAO.Database
        Dim dbLink As DAO.Database
        Dim tdf As TableDef
    
        Set dbCurr = CurrentDb
        Dim strConn As String
        Dim strNewDbConn1 As String
        Dim strNewDbConn2 As String
        Dim strNewDbConn  As String
    
        '  On Local Error GoTo fRefreshLinks_Err
    
        'First get all linked tables in a collection'
        dbCurr.TableDefs.Refresh
        For Each tdf In dbCurr.TableDefs
            With tdf
                If ((.Attributes And TableDefAttributeEnum.dbAttachedTable) = TableDefAttributeEnum.dbAttachedTable) _
                   And (.Name Like OnlyForTablesMatching) Then
    
                    strConn = tdf.Connect
                    strDBPath = Right(strConn, Len(strConn) - (InStr(1, strConn, "DATABASE=") + 8))
                    strDBName = Right(strDBPath, Len(strDBPath) - InStrRev(strDBPath, "\"))
                    Debug.Print ("===========================")
                    Debug.Print (" connect is " + strConn)
                    Debug.Print (" DB PAth is " + strDBPath)
                    Debug.Print (" DB Name is " + strDBName)
    
                    strDBNewPath = strNewPath & "\" & strDBName
                    Debug.Print (" DB NewPath is " + strDBNewPath)
    
                    strNewDbConn1 = Left(strConn, (InStr(1, strConn, "DATABASE=") - 1))
                    strNewDbConn2 = "DATABASE=" & strDBNewPath
                    strNewDbConn = strNewDbConn1 & strNewDbConn2
                    Debug.Print (" DB strNewDbConn is " + strNewDbConn)
    
                    'Change the connect path
                    tdf.Connect = strNewDbConn
                    tdf.RefreshLink
                End If
            End With
        Next
    End Function
    
    0 讨论(0)
提交回复
热议问题