Voir le flux RSS

User

Une alternative aux champs multivalués Access

Noter ce billet
par , 22/03/2020 à 21h30 (462 Affichages)
On présente dans ce billet une alternative aux champs multivalués utilisés dans les tables Access.

I. Introduction

Les champs multivalués permettent d'afficher directement dans les tables, les requêtes ou les formulaires, des listes de choix avec des cases à cocher pour sélectionner des données provenant d'une autre source.

Par exemple, on peut choisir les employés devant participer à une visioconférence directement dans la table des événements :

Nom : champs-multivalues.jpg
Affichages : 89
Taille : 86,3 Ko

Cependant, comme ces champs peuvent contenir plusieurs valeurs pour un même enregistrement, ils ne répondent pas à la première forme normale de la théorie de la normalisation, nécessaire pour concevoir un bon schéma d'une de base de données.

Leur utilisation dans les requêtes comme dans le code peut ainsi sembler déroutante aux puristes.

En résumé, ils peuvent par la suite compliquer le développement et la maintenance de la base Access.

Pour éviter ces problèmes, on se basera pour réaliser notre exemple, sur le modèle conceptuel de données suivant :

Nom : MCD.jpg
Affichages : 34
Taille : 24,3 Ko

On a une relation plusieurs-à-plusieurs dans laquelle un employé peut participer à un ou plusieurs événements, de même un événement peut regrouper un ou plusieurs employés.

On va donc devoir créer une table intermédiaire entre les tables T_Employe et T_Evenement nécessaire pour concevoir un bon schéma relationnel.

II. Description du contexte

On souhaite réaliser une liste permettant de choisir les employés devant participer à un événement (visioconférence, réunion, etc..).

Pour cela, on va utiliser un sous-formulaire basé sur une requête affichant la liste des employés accompagnés de cases à cocher pour effectuer les choix :

Nom : SF_Employes_Evenement.jpg
Affichages : 79
Taille : 57,7 Ko

On bénéficiera ainsi en plus, de tous les avantages qu'offrent les sous-formulaires par rapport aux zones de liste, notamment au niveau de la mise en forme.

III. Tables nécessaires

III-A. T_Employe

Elle permet d'enregistrer les données concernant les employés.

Nom du champ Type de données Description
IdEmploye NuméroAuto Identifiant de l'employé
NomEmploye Texte Nom de l'employé
PrenomEmploye Texte Prénom de l'employé
DateEntree Date/Heure Date d'entrée de l'employé dans la société
DateSortie Date/Heure Date de sortie de l'employé de l'entreprise

III-B. T_Evenement

Elle contient les informations relatives aux événements.

Nom du champ Type de données Description
IdEvent NuméroAuto Identifiant de l''événement
ObjetEvent Texte Objet de l'événement
EmplacementEvent Texte Lieu de l'événement
DateEvent Date/heure Date de l'événement
HeureDebutEvent Date/heure Heure de début de l'événement
HeureFinEvent Date/heure Heure de fin de l'événement

III-C. T_Employe_Evenement

Elle permet de faire le lien entre les 2 tables précédentes.

Nom du champ Type de données Description
IdEmploye Entier long Identifiant de l'employé : clé étrangère
IdEvenement Entier long Identifiant de l'événement : clé étrangère

La clé primaire est composée des champs IdEmploye et IdEvenement, elle permet ainsi d'identfier de manière unique l'enregistrement de la table, on est donc assuré de ne pas avoir deux fois le même employé pour un événement donné.

III-D. T_Employe_Evenement_Temp

Elle permet de faire le lien entre les 2 tables précédentes.

Nom du champ Type de données Description
IdEmploye Entier long Identifiant de l'employé : clé étrangère
IdEvenement Entier long Identifiant de l'événement : clé étrangère
Participant oui/non Indique si l'employé participe ou pas à l'événement.

La colonne Participant a comme valeur par défaut Non.

La clé primaire est placée sur le champ IdEmploye. Cette table est mise à jour à chaque changement d'enregistrement sur le formulaire.

IV. Relations entre les tables

On définit :

  • Une relation 1 à plusieurs entre les tables T_Employe et T_Employe_Evenement sur le champ IdEmploye.
  • Une relation 1 à plusieurs entre les tables T_Evenement et T_Employe_Evenement sur respectivement les champs IdEvent et IdEvenement.


Nom : Relations.jpg
Affichages : 79
Taille : 31,0 Ko

V. Requêtes

V-A. R_Employes_Evenement

Elle relie la table temporaire avec celle des employés, et affiche, pour chaque événement, la liste des employés accompagnés de leur participation et ordonnés suivant leur nom et prénom :

Nom : R_Employes_Evenement.jpg
Affichages : 32
Taille : 110,4 Ko

Elle constitue la source de données du sous-formulaire destiné à afficher la liste de choix des employés filtrés en fonction de leurs dates d'entrée et de sortie dans l'entreprise.

V-B. R_Ajouter_Employes

Cette requête insertion ajoute les nouveaux employés dans la table temporaire :

Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
INSERT INTO T_Employe_Evenement_Temp ( IdEmploye )
SELECT T_Employe.IdEmploye
FROM T_Employe LEFT JOIN T_Employe_Evenement_Temp ON T_Employe.IdEmploye = T_Employe_Evenement_Temp.IdEmploye
WHERE IsNull([T_Employe_Evenement_Temp].[IdEmploye])=True;
Elle est exécutée à l'ouverture du formulaire pour mettre à jour la table temporaire.

VI. Formulaire principal

Il est basé sur la table T_Evenement et affiche les informations sur un événement. Il contient en plus le sous-formulaire permettant de choisir les employés participants à l'événement.

Nom : F_Evenement.jpg
Affichages : 77
Taille : 95,5 Ko

VI-A. Procédure sur ouverture du formulaire

Le code insére les nouveaux employés dans la table temporaire :

Code VBA : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
Private Sub Form_Open(Cancel As Integer)
    Dim db As DAO.Database ' variable objet pour faire référence à la base de données
 
    Set db = CurrentDb ' référence à la base courante
 
    db.Execute "R_Ajouter_Employes", dbFailOnError ' on ajoute les nouveaux employés dans la table temporaire
 
    Set db = Nothing ' on libère la variable objet
End Sub

On exécute dans ce code la requête insertion R_Ajouter_Employes vu précédemment.

VI-B. Procédure sur activation

Ce code met à jour la liste des employés dans le sous-formulaire, sur activation d'un enregistrement, c'est à dire quand on se positionne sur un enregistrement.

Déroulé de la procédure événementielle :

  • Si on est sur un nouvel enregistrement, on génrère un nouveau NuméroAuto dans le champ IdEvent de la table T_Evenement.
  • On met à jour dans la table T_Employe_Evenement_Temp, l'identifiant de l'événement et la participation de l'employé.
  • On rafraîchit le sous-formulaire basée sur la requête R_Employes_Evenement, pour afficher la liste des employés accompagnés de cases à cocher.


Code VBA : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Private Sub Form_Current()
    Dim db As DAO.Database ' variable objet pour faire référence à la base courante
    Dim sSQL As String ' variable contenant la chaîne SQL
 
    If IsNull(Me.IdEvent) Then ' si on est en mode ajout, sur un nouvel enregistrement
        Me.DateEvent = Date() ' on saisit une valeur dans un champ, ce qui génère le numéro-auto dans le champ IdEvent
    End If
 
    Me.cmbRechercher.Value = Me.IdEvent ' on copie l'identifiant de l'événement dans la liste de recherche
 
    Set db = CurrentDb ' référence à la base courante
 
    ' Constitution de la chaîne SQL destinée à mettre à jour la table temporaire avec l'identifiant de l'événement
    sSQL = "UPDATE T_Employe_Evenement_Temp " & _
           "SET T_Employe_Evenement_Temp.IdEvenement = " & Me.IdEvent & ", T_Employe_Evenement_Temp.Participant = False;"
 
    db.Execute sSQL, dbFailOnError ' on déselectionne tous les employés dans la table temporaire
 
    ' Constitution de la chaîne SQL destinée à mettre à jour la table avec les données saisies dans la table T_Employe_Evenement
    sSQL = "UPDATE T_Employe_Evenement_Temp INNER JOIN T_Employe_Evenement ON  (T_Employe_Evenement_Temp.IdEmploye = T_Employe_Evenement.IdEmploye) AND (T_Employe_Evenement_Temp.IdEvenement = T_Employe_Evenement.IdEvenement) " & _
           "SET T_Employe_Evenement_Temp.Participant = True "
 
    db.Execute sSQL, dbFailOnError ' on sélectionne les participants dans la table temporaire
 
    Me.SF_Employes_Evenement.Requery  'on rafraîchit le sous-formulaire
 
    Set db = Nothing ' on libère la variable objet
End Sub

VII. Sous-formulaire SF_Employes_Evenement

Il est contenu dans le formulaire principal et est basé sur la requête R_Employes_Evenement. Ce sous-formulaire est en mode feuille de données, avec ajout et suppression des données interdits.

Il affiche donc les noms et prénoms des employés, avec pour chacun une case à cocher pour indiquer s'il participe ou pas à l'événement :

Nom : SF_Employes_Evenement.jpg
Affichages : 79
Taille : 57,7 Ko

VII-A. Liaison entre le formulaire principal et le sous-formulaire

Pour les relier, on définit dans les propriétés du sous-formulaire, IdEvent comme champ père, et IdEvenement comme champ fils.

Nom : Liaison_SousForm.jpg
Affichages : 77
Taille : 60,2 Ko

VII-B. Procédure sur avant MAJ du sous-formulaire

Elle permet de supprimer ou d'ajouter dans la table T_Employe_Evenement un employé pour un événement donné.

Déroulé de la procédure :

  • On recherche s'il y a un enregistrement dans la table T_Employe_Evenement avec les identifiants de l'employé et de l'événement.
  • Si la case Participant n'est pas cochée, et si un enregistrement a été trouvé dans la table T_Employe_Evement, alors on le supprime.
  • Sinon, si la case est cochée, alors on ajoute l'enregistrement dans la table T_Employe_Evenement.


Code VBA : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Private Sub Form_BeforeUpdate(Cancel As Integer)
    Dim db As DAO.Database ' variable objet pour faire référence à la base en cours
    Dim rs As DAO.Recordset ' variable objet pour faire référence au recordset
 
    Set db = CurrentDb ' référence à la base courante
 
    ' ouverture du recordset lié à la table T_Employe_Evenement
    Set rs = db.OpenRecordset("T_Employe_Evenement", dbOpenDynaset)
 
    ' recherche s'il y a un enregistrement dans la table T_Employe_Evenement avec les identifiants de l'employé et de l'événement
    rs.FindFirst "IdEmploye=" & Me.IdEmploye & " and IdEvenement=" & Me.IdEvenement
 
    If Not Participant Then ' si la case du participant n'est pas cochée
        If Not rs.NoMatch Then ' si un employé a été enregisté pour cet événement dans la table T_Employe_Evenement
            rs.Delete ' on supprime l'enregistrement correspondant
        End If
    Else ' sinon si la case est cochée
        ' on ajoute les identifiants de l'employé et de l'événement dans la table T_Employe_Evenement
        rs.AddNew
        rs!IdEmploye = Me.IdEmploye
        rs!IdEvenement = Me.IdEvenement
        rs.Update
    End If
 
    ' on ferme et libère les variables objet
    rs.Close
    Set rs = Nothing
 
    Set db = Nothing
End Sub

Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Viadeo Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Twitter Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Google Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Facebook Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Digg Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Delicious Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog MySpace Envoyer le billet « Une alternative aux champs multivalués Access » dans le blog Yahoo

Mis à jour 13/04/2020 à 14h45 par User

Catégories
Access , VBA

Commentaires