Je sais que j’ai plutôt l’habitude d’écrire à propos de logiciel libre, et que je préfère aborder un point concernant GNU/Linux que le système privateur Windows et ses outils associés. Seulement parfois, un étudiant en informatique n’a pas le choix des technos à utiliser pour réaliser son projet et est contraint d’utiliser des solutions privatrices. Ce fut le cas sur un projet de base de données où le logiciel imposé était Access. Cet article va donc aborder un point précis qui m’avait demandé de nombreuses heures de recherche, essais, etc avant d’arriver à réaliser la fonctionnalité voulue. En espérant que ces informations pourront aider d’autres étudiants par la suite et leur feront gagner un peu de temps. Je vais donc aborder la mise en place d’un système de liaison automatique des tables dans Access.
Tout d’abord, il faut savoir que dans notre situation, nous possédons deux fichiers. L’un contient l’ensemble des tables de notre base de données, l’autre contient l’application les utilisant. Dans le fichier de l’application, il est nécessaire de réaliser la liaison avec les tables de notre base de données. Cette liaison peut être facilement réalisée à la main. Néanmoins, un problème se pose avec cette façon de faire. En effet, Access retient l’emplacement absolu de votre fichier de données depuis la racine du disque dur soit quelque chose comme C:\Utilisateurs\Public\MonProjet\data.mdb par exemple. Et c’est là que l’on commence à s’arracher les cheveux puisque si je déplace le dossier MonProjet, la liaison des tables continue de pointer vers C:\Utilisateurs\Public\MonProjet\data.mdb. L’horreur quand vous êtes amené à changer d’ordinateur. Il existe pourtant une solution qui consiste à vérifier l’attachement des tables à chaque lancement de l’application. Si le chemin est correct, pas de problème, sinon, on refait la liaison automatiquement en construisant nous même le chemin absolu jusqu’au fichier. Il faut noter que dans l’exemple que je vais développer, le formulaire de démarrage de l’application ne fait aucune requête vers la base de données, afin d’éviter des erreurs (bien qu’il doit être possible de faire ces requêtes seulement lorsque la liaison a été vérifié et est correcte).
Je crée donc un fichier Access qui contiendra ma base de donnée et le nomme EXEMPLE_DATA. Pour notre exemple, on y ajoute une table PERSONNES avec divers champs. Par ailleurs, il faut créer le fichier qui contiendra l’application EXEMPLE_APPLI. Maintenant que nous disposons de nos deux fichiers, nous allons pouvoir effectuer la première liaison des tables manuellement. Onglet External Data, icône Linked Table Manager. Une fois la liaison effectuée, nous ajoutons un bête formulaire d’accueil dans notre application. Celui-ci ne contient rien d’autre qu’un simple texte. Nous pouvons alors mettre en évidence notre problème, couper/coller votre fichier EXEMPLE_DATA dans un autre dossier que le dossier courant, ré-ouvrez EXEMPLE_APPLI, le fichier contenant les tables est maintenant introuvable. Nous allons donc y remédier en mettant en place la liaison automatique des tables à chaque démarrage de l’application. Il est bien sûr possible de mettre en place un système permettant de ne lier les tables que si le fichier de base de données est introuvable.
Dans notre application, nous allons donc ajouter le module suivant nommé liaison_auto qui contient les fonctions dont nous avons besoin pour la liaison. Enfin, à l’ouverture de notre formulaire d’accueil, nous appelons les fonctions qui vont bien.
Option Compare Database Public Function VerifAttach() As Boolean Dim tdf As DAO.TableDef, strTemp As Variant, strPath As String, i As Long For Each tdf In CurrentDb.TableDefs ' Recherche d'une table liée If tdf.Connect <> "" Then strTemp = Split(tdf.Connect, ";") For i = LBound(strTemp) To UBound(strTemp) ' Recherche du paramètre de connection If strTemp(i) Like "DATABASE=*" Then strPath = Split(strTemp(i), "=")(1) ' Vérification de l'existence de la bdd If Dir(strPath) <> "" Then VerifAttach = True Exit Function End If End If Next i End If Next End Function Public Sub DeleteTables() ' Supprimer toutes les tables attachées On Error Resume Next Dim db As DAO.Database 'Database to import Dim tdf As DAO.TableDef Dim arrTablename() As String, i As Long ReDim arrTablename(0) Set db = CurrentDb ' Répertorier les tables à supprimer For Each tdf In db.TableDefs If tdf.Connect <> "" Then ReDim Preserve arrTablename(UBound(arrTablename) + 1) arrTablename(UBound(arrTablename)) = tdf.Name End If Next ' Suppression For i = LBound(arrTablename) To UBound(arrTablename) db.TableDefs.Delete arrTablename(i) Next i Set db = Nothing End Sub Public Function ActualiserAttaches(ByVal strCheminBd As String, Optional ByVal strMotPasse As String = "") As Boolean On Error GoTo ActualiserAttaches_Err Dim tdf As DAO.TableDef strSourceConnect = "MS Access;PWD=" & strMotPasse & ";DATABASE=" & strCheminBd ' Supprimer les tables avant tout DeleteTables 'Permet de lier toutes les tables Dim strConnect As String Dim strNomsTables() As String Dim strTemp As String Dim i As Integer Dim oDb As DAO.Database Dim oDbSource As DAO.Database Dim oTbl As DAO.TableDef Dim oTblSource As DAO.TableDef 'Définit la chaine de connexion permettant la liaison des tables strConnect = "MS Access;pwd=" & strMotPasse & ";DATABASE=" & strCheminBd 'Instancie l'objet Database de la base courante Set oDb = CurrentDb 'Instancie l'objet Database de la base protégée Set oDbSource = DBEngine.OpenDatabase(strCheminBd, True, True, strConnect) 'Parcours l'ensemble des tables de la base de données protégée 'et stocke leur nom For Each oTblSource In oDbSource.TableDefs 'Ignore les tables system If (oTblSource.Attributes And dbSystemObject) = 0 Then strTemp = strTemp & oTblSource.Name & "|" End If Next 'Ferme la base de données sources (impératif pour la liaison) oDbSource.Close: Set oDbSource = Nothing 'Parcours le tableau de noms de tables strNomsTables = Split(Left(strTemp, Len(strTemp) - 1), "|") For i = 0 To UBound(strNomsTables) 'Crée une nouvelle table dans la base de données courante Set oTbl = oDb.CreateTableDef(strNomsTables(i)) 'Lie les deux tables oTbl.Connect = strConnect oTbl.SourceTableName = strNomsTables(i) 'Ajoute la table à la base de données oDb.TableDefs.Append oTbl Next i 'Rafraichit la liste des tables oDb.TableDefs.Refresh ActualiserAttaches = True If ActualiserAttaches = True Then MsgBox "Tables de la base de données " & strCheminBd & " liées avec succés" End If Exit Function ActualiserAttaches_Err: MsgBox "Error " & Err.Number & " (" & Err.Description & _ ") in Function ActualiserAttaches of Module mdFonctions", vbCritical End Function
Ce code devrait donc vous permettre de réaliser sans difficulté la liaison automatique des tables au démarrage de votre application. Il est bien sûr possible de ne faire l’opération de liaison que lorsque celle-ci est nécessaire, ce que j’avais fait à l’époque mais qui me levait des erreurs pour cet exemple et que j’ai donc simplifié, n’ayant pas envie de débugger du VBA pendant des heures ;). Implémenter la fonctionnalité en s’inspirant de cet exemple devrait donc être plutôt rapide.
Il reste toutefois un peu de code à écrire du côté du formulaire d’accueil. Celui-ci est relativement simple, à noter tout de même que l’on considère que nos deux fichiers sont stockés au même endroit sur le disque pour la génération du chemin vers la base Data.
Option Compare Database Private Sub Form_Open(Cancel As Integer) ' Permet de contrôler la mise à jour des tables Dim strTemp As String Dim strChemin As String 'CHANGER LE NOM DE LA BASE DATA ICI strChemin = CurrentProject.Path & "\EXEMPLE_DATA.accdb" DeleteTables If ActualiserAttaches(strChemin) = True Then VerifAttach Else MsgBox "Mise à jour des Tables non éffectuées, " & vbCrLf & _ "veuillez contacter l'administrateur de la base.", vbCritical, "Liaisons des tables" 'Fermeture de l'application DoCmd.Close End If End Sub
J’espère que cet exemple sera utile au lecteur qui aura fait l’effort de me lire jusqu’au bout. Enfin, n’hésitez pas à laisser une remarque, addition ou autre en commentaire.
Zip contenant les fichiers d’exemple: EXEMPLE.
Articles intéressants pour un projet Access:
Gestion de photos par formulaire
Splash-screen
Mode Multi-Utilisateurs
Note: Le module de liaison avait été trouvé sur le net, très certainement sur developpez.com.
Super. Merci pour ce code !
Merci beaucoup!
Le code et les explications sont simples et efficaces. Bravo!
Merci pour ce code, très performant et simple à réutiliser.
Deux questions :
– à quoi sert exactement la fonction « VerifAttach » (je comprends son fonctionnement mais rien n’est prévu si la fonction renvoie false)
– pourquoi appeler deletetables au début de ActualiserAttaches ? (elle est appelée juste avant lors de l’ouverture du formulaire)
La fonction « VerifAttach » permet de s’assurer qu’il existe bien une base liée et que la liaison est correcte. A la relecture de ce code, je suis également surpris par l’absence de retour « false ». Je me souviens qu’à la création de l’exemple, j’avais cherché à simplifier au maximum pour ne garder que l’essentiel. A l’origine, le projet qui utilisait ces lignes comportait davantage de code de gestion d’erreurs. C’est donc soit un oubli soit un élagage de code hasardeux.
Il semble effectivement qu’il y ait un appel à « deleteTables » en trop. On doit donc pouvoir enlever l’un ou l’autre sans difficultés; à tester.
Bonjour,
Je tiens à vous remercier pour ce tuto, ça m’a vraiment aider à faire le premier pas en liaison automatique des données, mais j’ ai une question en espérant que vous aurez la réponse, donc je voudrais faire a liaison automatique entre les tables d’une base avec certaines tables de différentes bases. Par exemple on a deux fichiers: EXEMPLE_DATA et EXEMPLE_DATA_1 qui ne sont pas dans le répertoire et qui contiennent pas les mêmes table, l’objective est on cliquant sur un bouton on récupére une table T1 de EXEMPLE_DATA et T2 de EXEMPLE_DATA_1, est ce que possible?
Merci
Bonjour
quand on a plusieurs tables non reliée à une base de donnée en entrées comment aller les chercher une par une?
Merci
Grand merci !
Un grands merci ¨!!!
un grand merci. je ne me serais jamais lancé là dedans !
et vive linux (et virtuelbox)
Merci. Très utile.
Par contre, si l’on veut protéger la bade data avec un mot de passe, comment peut-on faire pour qu’il soit demandé à la phase d’actualisation mais mémorisé lors de l’utilisation de la base liées en routine?
Merci d’avance