FAQ MS-Access
FAQ MS-AccessConsultez toutes les FAQ
Nombre d'auteurs : 140, nombre de questions : 926, dernière mise à jour : 15 juin 2021
- Comment déconnecter les utilisateurs d'une base de données ?
- Comment documenter une base Access ?
- Comment ouvrir une base en mode exclusif ?
- Comment programmer une date d'expiration pour une application ?
- Comment inhiber la touche MAJ au démarrage ?
- Comment afficher la liste des utilisateurs connectés à une BDD ?
- Comment concevoir un formulaire login/mot de passe ?
- Comment lister les tables liées ?
- Comment dans du code vérifier qu'un utilisateur appartient à un groupe ?
- Comment tester la version d'Access utilisée ?
- Comment nettoyer le journal des connexions afin d'enlever les utilisateurs qui ne sont en fait plus connectés ?
- Comment réparer une base Access par décompilation ?
- Pourquoi l'erreur : "Signet non valide" à l'ouverture de ma base de données ?
- Comment faire si je dois reprendre une application Access et que tout est sur le serveur (formulaires, états...) ?
- Comment gérer le fait que plusieurs utilisateurs aient accès à mon application ?
- Pourquoi les formulaires de mon application partagée sont-ils très longs à ouvrir ?
- Comment modifier le mot de passe de la base de données en VBA ?
- Comment ajouter/modifier une propriété sur une base de données ?
L'idée est que le formulaire principal de l'application sache quand il faut lancer la routine de déconnexion des utilisateurs.
Pour cela, on crée une table avec un seul champ de type oui/non et un seul enregistrement : Administration(LogOff(oui/non)).
L'administrateur de la base peut ensuite cacher cette table (propriétés de la table, cocher Masqué) et lui seul peut cocher la case LogOff.
Il faut maintenant utiliser l'événement minuterie du formulaire principal qui lance la vérification de la routine qui déconnectera
les utilisateurs (on utilise un intervalle de 5 minutes).
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Private
Sub
Form_Timer
(
)
On
Error
GoTo
Err_LogOffChk
Dim
Lancer As
Boolean
Dim
rcd As
DAO.Recordset
Set
rcd =
CurrentDb.OpenRecordset
(
"Administration"
)
rcd.MoveFirst
Lancer =
rcd.Fields
(
0
)
rstLO.Close
CurrentDb.Close
' --Si la case est cochée
If
Lancer Then
Application.Quit
acQuitSaveAll
Exit_LogOff
:
Exit
Sub
Err_LogOffChk
:
MsgBox
Err
.Number
&
vbCrLf
&
Err
.Description
, vbInformation
, "Erreur"
Resume
Exit_LogOff
End
Sub
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Lien : Comment utiliser une application en mode multi-utilisateur par Dolphy35
Menu Outils/Analyse/Documentation.
Lien : Comment sortir un descriptif détaillé de toutes ses tables et de leurs attributs ?
Function
Ouvrir_Base_Exclusif
(
)
Dim
Bd As
Database
On
Error
Resume
Next
Set
Bd =
DbEngine (
0
).OpenDatabase
(
"C:\Ma_base.mdb"
, True
)
If
Err
.Number
<>
0
Then
Msgbox
Err
.Number
&
" Impossible d\'ouvrir la base en mode Exclusif "
&
vbcrlf
&
Err
.Description
, VbInformation
Else
MsgBox
"La base de données est ouverte en mode exclusif."
, VbInformation
End
If
End
Function
Si on obtient le numéro d'erreur 3262, c'est que la base est ouverte en mode partagé par un autre utilisateur.
Pour mettre une date d'expiration à la base et désactiver le run-time de votre application Access, appelez cette fonction à l'ouverture du formulaire de démarrage
Public
Function
DateExpirationApplication
(
)
If
Date
>=
DateSerial
(
2003
, 12
, 31
) Then
MsgBox
"La date d\'expiration de l\'application est dépassée"
, vbExclamation
DoCmd.Quit
End
If
End
Function
Il est parfois intéressant d'inhiber l'effet de la touche MAJ (ne pas exécuter les événements de chargement de la base) pour ne pas afficher le conteneur de la base à l'utilisateur. Pour cela on dispose de deux procédures, l'une qui l'inhibe SetBypassProperty, l'autre qui l'active UnSetBypassProperty.
Sub
SetBypassProperty
(
)
Const
DB_Boolean As
Long
=
1
ChangeProperty "AllowBypassKey"
, DB_Boolean, False
End
Sub
Sub
UnSetBypassProperty
(
)
Const
DB_Boolean As
Long
=
1
ChangeProperty "AllowBypassKey"
, DB_Boolean, True
End
Sub
Function
ChangeProperty
(
strPropName As
String
, varPropType As
Long
, varPropValue As
Variant
) As
Integer
Dim
dbs As
Database, prp As
Variant
Const
conPropNotFoundError =
3270
Set
dbs =
CurrentDb
On
Error
GoTo
Change_Err
dbs.Properties
(
strPropName) =
varPropValue
Change_Bye
:
Exit
Function
Change_Err
:
If
Err
=
conPropNotFoundError Then
' Propriété non trouvée.
Set
prp =
dbs.CreateProperty
(
strPropName, _
varPropType, varPropValue)
dbs.Properties.Append
prp
Resume
Next
Else
' --Erreur inconnue.
Resume
Change_Bye
End
If
End
Function
Lien : Comment empêcher le lancement du formulaire de démarrage ou de la macro AUTOEXEC ?
Pour connaître la liste des connectés à une base de données, il suffit d'explorer le fichier .ldb. Pour ce faire, on aura besoin de définir un type :
Private
Type
Un_Connecté
' --Nom PC
PC
(
1
To
32
) As
Byte
' --Nom utilisateur
User
(
1
To
32
) As
Byte
End
Type
Cette fonction renvoie alors la chaîne des connectés :
Public
Function
WHO_IS
(
) As
String
' -- Retourne une liste séparée par des points-virgules indiquant le nom de l'ordinateur ainsi que
' -- L'utilisateur connecté à la base.
On
Error
GoTo
Err_WHO_IS
Dim
Mon_LDB As
Integer
, i As
Integer
Dim
Mon_Chemin As
String
Dim
Mon_Log As
String
, Ma_Connexion As
String
Dim
Nom_PC As
String
, Nom_Utilisateur As
String
Dim
utilisateur As
Un_Connecté
Mon_Chemin =
CurrentDb.Name
CurrentDb.Close
' --Aller chercher le LDB
Mon_Chemin =
Left
(
Mon_Chemin, InStr
(
1
, Mon_Chemin, "."
)) +
"LDB"
Mon_LDB =
FreeFile
' --Ouvrir le LDB
Open Mon_Chemin For
Binary Access Read Shared As
Mon_LDB
' -- Lire le LDB
Do
While
Not
EOF
(
Mon_LDB)
' -- Chaque enregistrement lu est placé dans la variable utilisateur pour y être traité.
Get
Mon_LDB, , utilisateur
With
utilisateur
i =
1
Nom_PC =
""
' -- Nom du PC
While
.PC
(
i) <>
0
Nom_PC =
Nom_PC &
Chr
(
.PC
(
i))
i =
i +
1
Wend
i =
1
Nom_Utilisateur =
""
' -- Nom de l'utilisateur
While
.User
(
i) <>
0
Nom_Utilisateur =
Nom_Utilisateur &
Chr
(
.User
(
i))
i =
i +
1
Wend
End
With
Mon_Log =
Nom_PC &
" | "
&
Nom_Utilisateur
If
InStr
(
Ma_Connexion, Mon_Log) =
0
Then
Ma_Connexion =
Ma_Connexion &
Mon_Log &
";"
End
If
Loop
Close Mon_LDB
' --WHO_IS contient la liste des utilisateurs
WHO_IS =
Ma_Connexion
Exit_WHO_IS
:
Exit
Function
Err_WHO_IS
:
MsgBox
Err
.Number
&
vbCrLf
&
Err
.Description
, vbInformation
, "Erreur"
Close Mon_LDB
Resume
Exit_WHO_IS
End
Function
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Le formulaire login/mot de passe permettra à un utilisateur de s'identifier et à la base de le reconnaître et de décider de lui donner
ou non la permission d'accéder à la base. Pour ce faire, on aura besoin d'une table T_User et d'un formulaire " F_Connexion ".
Table T_User (TRIGRAMME, NOM, PRENOM, GROUPE, PASWD) tous les champs sont de type texte. Un enregistrement exemple
de cette table : T_User(SED, SEBASTIEN, DULOT, Administrateur, root).
L'événement on_click du bouton Connexion :
Private
Sub
connexion_Click
(
)
Me.Requery
Dim
sql, User_id, User_groupe As
String
Dim
rs As
DAO.Recordset
Static
i As
Byte
sql =
"SELECT * FROM T_USERS WHERE TRIGRAMME = \'"
&
Me.txt_user
&
"\' AND PASWD =\'"
&
Me.txt_pass
&
"\';"
Set
rs =
CurrentDb.OpenRecordset
(
sql)
If
Not
rs.EOF
Then
DoCmd.OpenForm
"F_Autre_Formulaire"
, acNormal, , , , acWindowNormal
DoCmd.close
acForm, "F_CONNEXION"
User_id =
rs
(
"TRIGRAMME"
).value
User_groupe =
rs
(
"GROUPE"
).value
Else
MsgBox
"(Identifiant, Mot de Passe) incorrect "
, vbInformation
, "Connexion"
i =
i +
1
End
If
If
i =
3
Then
Msgbox
"Vous avez dépassé le nombre de tentatives autorisées"
, vbCritical
DoCmd.Quit
End
If
End
Sub
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Pour connaître l'origine des tables liées, il suffit d'explorer la table MSysObjects. Vous pouvez alors créer un formulaire avec trois zones de texte dans la section détail : Nom de la table, Nom étranger de la table, Chemin de la table. Dans la source de données du formulaire, il faut mettre cette requête :
SELECT
Name, ForeignName, Database
FROM MSysObjects
WHERE MSysObjects.Type
=
6
;
N'oubliez pas de renseigner la source de données des zones de texte.
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Exemple en DAO :
Dim
Utilisateur As
DAO.User
, MonGroup As
DAO.Group
Set
Utilisateur =
DBEngine.Workspaces
(
0
).Users
(
DBEngine.Workspaces
(
0
).UserName
)
For
Each
MonGroup In
Utilisateur.Groups
If
MonGroup.Name
=
"Admins"
Then
MsgBox
Utilisateur.Name
&
" est dans le groupe "
&
MonGroup.Name
Exit
For
End
If
Next
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Dim
Valeur As
Variant
Valeur =
SysCmd
(
acSysCmdAccessVer)
Si Valeur vaut 8.0, la version est Access97. 9.0 correspond à Access 2000, etc.
Pour exécuter ce code, il faut activer les références : Microsoft DAO 3.x Object Library, Microsot ADO Ext 2.X for dll and security et Microsof ActiveX Data Object 2.X Library.
Const
JET_SCHEMA_USERROSTER =
"{947bb102-5d43-11d1-bdbf-00c04fb92675}"
Sub
WriteUserConnected
(
)
'To determine who is logged onto a database
Dim
cn As
New
ADODB.Connection
Dim
rs As
New
ADODB.Recordset
Dim
i, j As
Long
Dim
rsUC As
DAO.Recordset
Set
rsUC =
db.OpenRecordset
(
"T_USER_CONNECTED"
, dbOpenDynaset)
Set
cn =
CurrentProject.Connection
' The user roster is exposed as a provider-specific schema rowset
' in the Jet 4.0 OLE DB provider. You have to use a GUID to
' reference the schema, as provider-specific schemas are not
' listed in ADO's type library for schema rowsets
Set
rs =
cn.OpenSchema
(
adSchemaProviderSpecific, , JET_SCHEMA_USERROSTER)
' Output the list of all users in the current database.
db.Execute
"DELETE * FROM T_USER_CONNECTED"
While
Not
rs.EOF
With
rsUC
.AddNew
!COMPUTER_NAME =
rs.Fields
(
0
)
!LOGIN_NAME =
rs.Fields
(
1
)
!CONNECTED =
rs.Fields
(
2
)
!SUSPECTED_STATE =
rs.Fields
(
3
)
.Update
End
With
rs.MoveNext
Wend
End
Sub
Pensez à créer une table T_USER_CONNECTED.
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Il y a beaucoup de messages qui évoquent des applications corrompues qu'il faut reprendre en exportant tout ce qui peut l'être dans un nouveau fichier .mdb, les problèmes de mémoire "written" "read", etc.
Bien souvent, ces problèmes pourraient être résolus par une décompilation.
Je m'explique:
L'application Access permet d'utiliser différentes options dans la ligne de commande de démarrage.
Dans l'aide, chercher :
>> Options de la ligne de commande de démarrage
Il existe une option non documentée /decompile ; elle permet de remettre en ordre de marche une application MDB qui donne des signes de dysfonctionnement incompréhensibles.
Voici un exemple d'utilisation:
"C:\Program Files\Microsoft Office\Office\MSACCESS.EXE"
"d:\bd1.mdb"
/
decompile
Il existe beaucoup de pages sur le web qui traitent la question.
Entre autres, le lien:
http://www.granite.ab.ca/access/decompile.htm
CONSEILS :
1. Faire une sauvegarde du fichier avant de le décompiler.
2. Après avoir décompilé le fichier, le compacter pour récupérer tout l'espace libéré par la décompilation.
CERISE SUR LE GÂTEAU DE LA BASE DE REGISTRE :
Astuce pour ne plus avoir à retaper toujours et encore cette sacrée ligne de commande, ni créer des raccourcis ad hoc.
Sur mon PC, j'ai modifié la base de registre de Windows pour que le menu contextuel géré par le bureau (Windows explorer inclus) donne enfin un accès rapide aux fonctions de décompactage et de décompilation.
Le code qui suit doit être copié dans un fichier nommé [AccessDecomp.reg] (c'est l'extension .reg qui importe).
Il ne reste plus qu'à l'exécuter pour enrichir le menu contextuel.
ATTENTION : ceci ne convient que pour Access 2000 (version 9).
Pour d'autres versions merci d'adapter à votre cas et de nous communiquer les modifications utiles.
REGEDIT4
[HKEY_CLASSES_ROOT\
Access.Application.9
\
shell]
[HKEY_CLASSES_ROOT\
Access.Application.9
\
shell\
Compacter]
"EditFlags"
=
hex
:01
,00
,00
,00
@=
"&Compacter"
[HKEY_CLASSES_ROOT\
Access.Application.9
\
shell\
Compacter\
command]
@=
"\"
C:\\
Program Files\\
Microsoft Office\\
Office\\
MSACCESS.EXE
\
" \"
%1
\
" /COMPACT "
[HKEY_CLASSES_ROOT\
Access.Application.9
\
shell\
Décompiler]
"EditFlags"
=
hex
:01
,00
,00
,00
@=
"&Décompiler"
[HKEY_CLASSES_ROOT\
Access.Application.9
\
shell\
Décompiler\
command]
@=
"\"
C:\\
Program Files\\
Microsoft Office\\
Office\\
MSACCESS.EXE
\
" \"
%1
\
" /DECOMPILE "
Hélas, même si décompiler apporte souvent une solution, il n'empêche que de temps à autre il faut quand même "reprendre" un fichier .mdb récalcitrant. Et, à mon avis, c'est le pire défaut d'Access et c'est un énorme défaut !!!
Cela signifie que le fichier de la base de données est corrompu. Dans la plupart des cas, un simple compactage de la base de données ou une réparation avec l'utilitaire JetComp sera suffisant.
Si cela ne résout pas le problème, il vous faudra importer un à un chacun des objets dans une nouvelle base de données.
Si jamais vous devez travailler sur une base de données ne respectant pas le schéma classique de Client/Serveur il faut que vous sépariez :
- les tables (qui restent sur le serveur), -> n'oubliez pas la sauvegarde quotidienne ;
- de l'application : tout le reste ainsi que les mêmes tables, mais attachées. -> pas besoin de sauvegardes tous les jours, juste une seule copie de sauvegarde pour tout le monde.
Une fois ces modifications apportées vous allez constater des performances hors du commun (il n'est pas rare de voir des formulaires mettre jusqu'à 20 minutes pour s'ouvrir, lorsque l'application est sur le serveur, puis 15 à 30 secondes, après avoir recopié l'application localement...).
Lien : Comment gérer le fait que plusieurs utilisateurs aient accès à mon application ?
Tout d'abord, une chose à ne jamais faire est de mettre l'application sur le serveur puis de créer un raccourci pour chaque utilisateur devant l'utiliser. Car dans ce cas deux utilisateurs sur deux postes différents peuvent ouvrir le même formulaire partagé sur un serveur.
Voici la logique à suivre :
- on partage les tables contenant les données, dans une base de données située sur un serveur .
- on ne partage jamais l'application (tables attachées, formulaires, requêtes, états, etc.). Chaque poste possède une application.
Sinon, dès qu'un utilisateur modifie un formulaire, il faut s'attendre à voir les mêmes modifications sur tous les postes, avec de longs délais (passage d'info par le réseau), d'où un cafouillage total pour Access.
Votre projet est sans doute divisé en deux fichiers Access : la base de données et l'application (formulaires, états...).
Il faut impérativement que vous recopiiez l'application sur chaque poste et que la base de données soit sur le Serveur.
En effet, seule la base de données est destinée à être partagée.
L'application ne doit jamais l'être, sous peine :
- de mettre très longtemps (jusqu'à plusieurs minutes si le réseau est encombré) pour ouvrir certains formulaires ;
- d'obtenir des erreurs quasi incompréhensibles lorsque plusieurs utilisateurs ouvrent les mêmes formulaires en même temps : affichage incomplet de certains contrôles, etc. ;
- s'il y a des tables locales, dans l'application elle-même, ces tables doivent être propres à chaque utilisateur et non pas partagées, sous peine de voir les données changer toutes seules lorsqu'un autre utilisateur les modifie...
De plus, ceci est cohérent avec une bonne politique de sauvegarde :
- une copie de secours de l'application (pourquoi pas sur le serveur) suffit pour réinstaller l'application en cas de panne sur un poste. Inutile de la sauvegarder tous les jours, si elle n'est pas modifiée par un programmeur ;
- des copies quotidiennes de la base de données sont indispensables dans les sauvegardes (backups).
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Il faut appliquer la méthode NewPassword de l'objet DataBase en utilisant DAO.
Sub
ChangeMotPass
(
)
On
Error
GoTo
err
Dim
odb As
DAO.Database
Set
odb =
CurrentDb
odb.NewPassword
"ancien"
, "nouveau"
MsgBox
"Mot de passe changé"
fin
:
Set
odb =
Nothing
Exit
Sub
err
:
Select
Case
err
.Number
Case
3031
MsgBox
"Mot de passe non valide"
, vbCritical
, "Sécurité"
Case
Else
MsgBox
"Une erreur est survenue pendant le changement du mot de passe"
, _
vbCritical
, "Erreur"
End
Select
Resume
fin
End
Sub
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Pour exécuter ce code, il faut activer la référence : Microsoft DAO 3.x Object Library.
Sub
SetProperty
(
strName As
String
, intType As
Variant
, vValue As
Variant
)
Dim
prpNew As
DAO.Property
Dim
db As
DAO.Database
Set
db =
CurrentDb
(
)
' Tente de définir la propriété spécifiée.
On
Error
GoTo
Err_SetProperty
db.Properties
(
strName) =
vValue
Exit_SetProperty
:
db.Close
Set
db =
Nothing
Exit
Sub
Err_SetProperty
:
' L'erreur 3270 signifie que la propriété est
' introuvable.
Select
Case
Err
.Number
Case
3270
' Crée une propriété, définit sa valeur et
' l'ajoute à la collection Properties.
Set
prpNew =
db.CreateProperty
(
strName, intType, vValue)
db.Properties.Append
prpNew
Case
Else
MsgBox
"erreur n°"
&
Err
.Number
&
vbCrLf
&
Err
.Description
End
Select
GoTo
Exit_SetProperty
End
Sub
exemples d'utilisation :
setproperty "NouvellePropriete"
, dbboolean, false
ou
setproperty "RepTravail"
, dbtext, "C:\Program Files\Office\"
Il sera ensuite facile de récupérer dans le code cette propriété :
Dim
strPath as
String
strPath =
CurrentDB.Properties
(
"RepTravail"
)
Lien : Définition et manipulation de données avec DAO par Tofalu
Lien : Comment déclarer une référence dans MS Access ?
Lien : Comment modifier le titre de l'application ?