Gérer des examens : élèves, épreuves, salles
Bonjour, je voudrais créer une appli ACCESS 2002 pour gérer les examens des élèves de lycée, en affectant tout un niveau dans des salles ayant un nombre de places limité. Je manipule bien Access mais je découvre vba.
Pour commencer, j'ai 4 tables : T_Epreuve, T_Elève, T_Salle et T_Examen. T_Epreuve contient les champs Id_Epreuve (NuméroAuto et clé primaire), NomEpreuve (ex: "Francais"), DateEpreuve.
T_Elèves contient les champs Id_Elèves (NuméroAuto et clé primaire), NomPrénomElève, NiveauElève (ex. Terminale).
La table T_Salle contient les champs Id_Salle (NuméroAuto et clé primaire), NomSalle, Capacité (Numérique entier ; exemple d'enregistrement = 35 places). Enfin la table T_Examen contient un champ clé primaire avec NuméroAuto "Id_Examen" ; Id_Epreuve, Id_Elève et Id_Salle" comme champs clé externe.
Question : je voudrais que la base répartisse automatiquement les candidats dans les salles en fonction de leur capacité. Je vois bien un formulaire dans lequel je sélectionnerais dans une liste déroulante le NomEpreuve ("Français"), le NiveauElève ("Première") et qui créerait par bouton de commande les enregistrements dans la table T_Examen (avec l'identifiant élève, salle, Epreuve), en changeant de salle dès que la capacité est atteinte.
Merci de votre aide !
Attribuer des salles en fonction des disponibilités
Voici une 1re ébauche, si on se contente
- d’un calcul pour une seule date à la fois ;
- de traiter manuellement les impasses.
Les données
http://claudeleloup.developpez.com/ForumAccess/k134.jpg
Un formulaire
http://claudeleloup.developpez.com/ForumAccess/k135.jpg
L’idée
La mise à jour des valeurs de Clé_MEF provoque la modification du SQL de la requête
http://claudeleloup.developpez.com/ForumAccess/k136.jpg
Qui ramène ceci :
http://claudeleloup.developpez.com/ForumAccess/k137.jpg
Les items sont classés par ordre décroissant de places nécessaires.
On lit ces enregistrements un à un et pour chacun, on lui affecte une salle encore libre, la plus petite possible qui puisse contenir toute la classe. Un message apparaît si aucune salle ne satisfait.
Le code du module du formulaire
À l’ouverture, on neutralise les données de l’exécution précédente
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Private Sub Form_Open(Cancel As Integer)
Dim qry As QueryDef
'Vider la requête SallesNecessaires
Set qry = CurrentDb.QueryDefs("SallesNecessaires")
qry.SQL = "SELECT Id_Eleve FROM T_Eleve WHERE Id_Eleve=0;"
Set qry = Nothing
'Réinitialiser les colonnes ClasseAffectee et NbreEleves dans T_Salle
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE T_Salle SET T_Salle.ClasseAffectee = Null, T_Salle.NbreEleves = 0;"
DoCmd.SetWarnings True
'Actualiser les sf
Me.CTNRsfBesoins.Form.RecordSource = Me.CTNRsfBesoins.Form.RecordSource
Me.CTNRsfAffectations.Form.RecordSource = Me.CTNRsfAffectations.Form.RecordSource
End Sub |
Après le choix des codes Clé_MEF
On formate le SQL de la requête SallesNecessaires, on déclenche la routine Affectation() et on actualise les sous-formulaires
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| Private Sub txtCodes_AfterUpdate()
Dim qry As QueryDef
'Adapter la requête SallesNecessaires
If IsNull(Me.txtCodes) Then
MsgBox "Pas de code sélectionné"
Else
Set qry = CurrentDb.QueryDefs("SallesNecessaires")
qry.SQL = "SELECT T_Eleve.Clé_MEF, T_Eleve.Code_Classe, Sum(1) AS Nbre " _
& "FROM T_Eleve " _
& "GROUP BY T_Eleve.Clé_MEF, T_Eleve.Code_Classe " _
& "HAVING (((T_Eleve.Clé_MEF) In (" & Replace(Me.txtCodes, ";", ",") & ") AND ((T_Eleve.Code_Classe) Is Not Null))) " _
& "ORDER BY Sum(1) DESC;"
Set qry = Nothing
End If
'Processus d'affectation
Call Affectation
'Actualiser les sf
Me.CTNRsfBesoins.Form.RecordSource = Me.CTNRsfBesoins.Form.RecordSource
Me.CTNRsfAffectations.Form.RecordSource = Me.CTNRsfAffectations.Form.RecordSource
End Sub |
La routine Affectation()
Pour chaque enregistrement levé par la requête SallesNecessaires, on recherche la plus petite salle qui puisse convenir :
d’abord la plus petite capacité qui convient
Code:
ClasDispoNbre = DMin("Capacite", "T_Salle", "Capacite>= " & rst("Nbre") & " and isnull(ClasseAffectee)")
ensuite l’id de « la » salle qui a cette capacité
Code:
idClasAAffecter = DLookup("id_Salle", "T_Salle", "Capacite=" & ClasDispoNbre & " and isnull(ClasseAffectee)")
et on construit alors le SQL d’une requête de cette forme :
http://claudeleloup.developpez.com/ForumAccess/k138.jpg
Code:
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 31 32 33 34 35 36
| Private Sub Affectation()
On Error GoTo GestionErreur
Dim rst As Recordset
Dim ClasDispoNbre As Integer
Dim idClasAAffecter
Dim sSQL As String
'Réinitialiser les colonnes ClasseAffectee et NbreEleves dans T_Salle
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE T_Salle SET T_Salle.ClasseAffectee = Null, T_Salle.NbreEleves = 0;"
DoCmd.SetWarnings True
Set rst = CurrentDb.OpenRecordset("SallesNecessaires")
Do While Not rst.EOF
ClasDispoNbre = DMin("Capacite", "T_Salle", "Capacite>= " & rst("Nbre") & " and isnull(ClasseAffectee)")
idClasAAffecter = DLookup("id_Salle", "T_Salle", "Capacite=" & ClasDispoNbre & " and isnull(ClasseAffectee)")
'Affectation
sSQL = "UPDATE T_Salle SET T_Salle.ClasseAffectee = """ & rst("Code_Classe") _
& """, T_Salle.NbreEleves =" & rst("Nbre") _
& " WHERE (((T_Salle.Id_Salle)=" & idClasAAffecter & "));"
DoCmd.SetWarnings False
DoCmd.RunSQL sSQL
DoCmd.SetWarnings True
AuSuivant:
rst.MoveNext
Loop
rst.Close
Set rst = Nothing
Exit Sub
GestionErreur:
Select Case Err.Number
Case 94 'on ne trouve pas de salle
MsgBox "Problème pour " & rst("code_classe") & " avec " & rst("Nbre") & " élèves.", vbCritical
Resume AuSuivant
Case Else
MsgBox Err.Number & " " & Err.Description
End Select
End Sub |
La db exemple est ici : http://claudeleloup.developpez.com/F...tionSalles.mdb