Parcourir des enregistrements 2
Malgré mes efforts dans le premier opus je constate que certains ont encore des difficultés pour comprendre la manipulation des recordsets.
Pour rappel, Access , par défaut, ne gère que l'enregistrement sélectionné (on dit aussi pointé). Le pointeur se présente sous la forme d'un petit triangle sur la gauche (ici entouré en rouge). Donc, Access ne peut utiliser que les infos '04/10/1994' , '9' et 'Poussin' ...du moins directement...
Pour accéder aux autres infos, il faut soit utiliser des fonctions soit utiliser la technique du recordset. Voilà le grand mot lâché...
Personnellement, j'utilise presque exclusivement la méthode DAO (voir premier opus). Elle est compatible Access 97
Un recordset est un ensemble d'enregistrements que vous allez reproduire en mémoire vive. Cet ensemble est défini par une instruction SQL. Je dis "Ensemble" car on n'est pas obligé de copier une table ou une requête entière dans un recordset. On peut très bien définir une clause WHERE dans l'instruction SQL.
Petite astuce en passant, vous n'êtes pas chevronné en langage SQL. Faites donc une requête, passez en mode construction SQL et récupérer le code par un copier-coller dans votre module
Comme tout le monde comprend mieux à partir d'un exemple concret, plantons le décor.
Nous créons une nouvelle base de données, dans laquelle nous initions des tables
- Créer une table T_Annees avec un champ Annee - type Numérique , entier avec les données : 2004, 2005
- Créer une table T_Collaborateurs avec un champ NomCollaborateur - type texte avec les données : John, Bill, Oscar
- Créer une table T_Projets avec un champ NomProjet - typeTexte avec les données Projet1, Projet2, Projet3
- Créer une table T_Globale avec 4 champs NomCollaborateur - type texte; NomAnnee - type numérique;NomProjet - type texte et NomMois - type texte
Déjà vous réalisez que le but de l'exercice sera de remplir la T_Globale en récupérant tour à tour les infos dans les autres tables et ceci pour les 12 mois de chaque année. Ce qui devrait conduire Access à ajouter 216 (3 collaborateurs * 3 Projets * 24 mois) enregistrements dans T_Globale
Notre but est maintenant connu, nous allons alors progresser par étapes (inutile de tenter d'atteindre le but directement, on s'y perdrait)
1ère étape, je crée la boucle pour récupérer les années
Sub Commande1_Click()
'Déclarations obligatoires et préalables
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
'Variable locale
Dim MonAnnee As Integer
'Variables qui placent le recordset en mémoire vive
Set db = Application.CurrentDb
Set rs1 = db.OpenRecordset("Select * from T_Annees")
'Logiquement Access doit commencer par traiter le 1er enregistrement
'Mais il est préférable de s'en assurer
rs1.MoveFirst
'Ici, débute la boucle
Do
'On injecte le contenu du champ dans une variable
MonAnnee = rs1("Annee")
'Pour vérifier le fonctionnement de notre procédure
MsgBox MonAnnee
'On passe à l'enregistrement suivant
rs1.MoveNext
'Et ceci jusqu'à la fin du recordset
Loop Until rs1.EOF = True
End Sub
ça marche ! J'obtiens tour à tour les messages suivants
2ème étape, pour traiter les collaborateurs, j'imbrique une seconde boucle dans la première et cela devient ceci
Sub Commande1_Click()
'Déclarations obligatoires et préalables. En pourpre, les lignes ajoutées
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
'Variable locale
Dim MonAnnee As Integer, MonCollaborateur As String
'Variables qui placent leS recordsetS en mémoire vive
Set db = Application.CurrentDb
'J ai cette fois 2 recordsets en mémoire
Set rs1 = db.OpenRecordset("Select * from T_Annees")
Set rs2 = db.OpenRecordset("Select * from T_Collaborateurs")
rs1.MoveFirst
Do
MonAnnee = rs1("Annee")
MsgBox MonAnnee
'Si on compare avec la procédure précédente, on constate que c'est le même mécanisme
rs2.MoveFirst
Do
MonCollaborateur = rs2("NomCollaborateur")
MsgBox MonCollaborateur MsgBox MonAnnee & " " & MonCollaborateur
rs2.MoveNext
Loop Until rs2.EOF = True
'C'est avant l'instruction MoveNext que je dois insérer la nouvelle boucle
'Il faudra agir de la sorte pour chaque recordset à parcourir
rs1.MoveNext
Loop Until rs1.EOF = True
End Sub
3ème étape, bin je recommence pour la T_Projets et ça donne..
Sub Commande1_Click()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim MonAnnee As Integer, MonCollaborateur As String, MonProjet As String
Set db = Application.CurrentDb
Set rs1 = db.OpenRecordset("Select * from T_Annees")
Set rs2 = db.OpenRecordset("Select * from T_Collaborateurs")
Set rs3 = db.OpenRecordset("Select * from T_Projets")
rs1.MoveFirst
Do
MonAnnee = rs1("Annee")
MsgBox MonAnnee
rs2.MoveFirst
Do
MonCollaborateur = rs2("NomCollaborateur")
MsgBox MonCollaborateur
MsgBox MonAnnee & " " & MonCollaborateur
rs3.MoveFirst
Do
MonProjet = rs3("NomProjet")
MsgBox MonProjet
MsgBox MonAnnee & " " & MonCollaborateur & " " & MonProjet
rs3.MoveNext
Loop Until rs3.EOF = True
'C'est bien juste avant le MoveNext que j'ai inclus ma 3ème boucle
rs2.MoveNext
Loop Until rs2.EOF = True
rs1.MoveNext
Loop Until rs1.EOF = True
End Sub
4ème étape, on s'occupe maintenant des mois; mais ici, ces infos ne sont pas dans une table, nous allons les produire grâce à une instruction DateSerial
Sub Commande1_Click()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim MonAnnee As Integer, MonCollaborateur As String, MonProjet As String
Dim i As Integer, MonMois As String
Set db = Application.CurrentDb
Set rs1 = db.OpenRecordset("Select * from T_Annees")
Set rs2 = db.OpenRecordset("Select * from T_Collaborateurs")
Set rs3 = db.OpenRecordset("Select * from T_Projets")
rs1.MoveFirst
Do
MonAnnee = rs1("Annee")
MsgBox MonAnnee
rs2.MoveFirst
Do
MonCollaborateur = rs2("NomCollaborateur")
MsgBox MonCollaborateur
MsgBox MonAnnee & " " & MonCollaborateur
rs3.MoveFirst
Do
MonProjet = rs3("NomProjet")
MsgBox MonProjet
MsgBox MonAnnee & " " & MonCollaborateur & " " & MonProjet
'Production des mois
For i = 1 To 12
MonMois = Format(DateSerial(1, i, 1), "mmmm")
MsgBox MonMois
MsgBox MonAnnee & " " & MonCollaborateur & " " & MonProjet & " " & MonMois
Next i
rs3.MoveNext
Loop Until rs3.EOF = True
rs2.MoveNext
Loop Until rs2.EOF = True
rs1.MoveNext
Loop Until rs1.EOF = True
End Sub
Ultime étape, ajouter le contenu des variables vers la T_Globale (dans les 4 champs NomAnnee - NomCollaborateur - NomProjet - NomMois) et j'imbrique alors la commande AddNew , le nettoyage de la mémoire et je neutralise les Msgbox qui m'ont permis de visualiser ma progression
Sub Commande1_Click()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rs3 As DAO.Recordset
Dim rs4 As DAO.Recordset
Dim MonAnnee As Integer, MonCollaborateur As String, MonProjet As String
Dim i As Integer, MonMois As String
Set db = Application.CurrentDb
Set rs1 = db.OpenRecordset("Select * from T_Annees")
Set rs2 = db.OpenRecordset("Select * from T_Collaborateurs")
Set rs3 = db.OpenRecordset("Select * from T_Projets")
Set rs4 = db.OpenRecordset("Select * from T_Globale")
rs1.MoveFirst
Do
MonAnnee = rs1("Annee")
'MsgBox MonAnnee
rs2.MoveFirst
Do
MonCollaborateur = rs2("NomCollaborateur")
'MsgBox MonCollaborateur
'MsgBox MonAnnee & " " & MonCollaborateur
rs3.MoveFirst
Do
MonProjet = rs3("NomProjet")
'MsgBox MonProjet
'MsgBox MonAnnee & " " & MonCollaborateur & " " & MonProjet
For i = 1 To 12
MonMois = Format(DateSerial(1, i, 1), "mmmm")
'MsgBox MonMois
'MsgBox MonAnnee & " " & MonCollaborateur & " " & MonProjet & " " & MonMois
'On AJOUTE les données dans la T_Globale
With rs4
.AddNew
!NomAnnee = MonAnnee
!NomCollaborateur = MonCollaborateur
!NomProjet = MonProjet
!NomMois = MonMois
.Update
End With
Next i
rs3.MoveNext
Loop Until rs3.EOF = True
rs2.MoveNext
Loop Until rs2.EOF = True
rs1.MoveNext
Loop Until rs1.EOF = True
'Instruction pour nettoyer la mémoire des recordsets inutiles;
'il fallait normalement le réaliser dans les autres procédures aussi
'mais j'ai préféré les mettre uniquement dans la procédure finale pour ne pas embrouiller les esprits
rs1.Close
rs2.Close
rs3.Close
rs4.Close
Set rs1 = Nothing
Set rs2 = Nothing
Set rs3 = Nothing
Set rs4 = Nothing
Set db = Nothing
End Sub
Bien sûr, il faudrait aussi créer une boucle dans rs4 si T_Globale n'était pas vide pour vérifier si les données que l'on veut ajouter n'existent pas déjà, il suffit pour cela d'utiliser un IF..THEN avant la commande AddNew
Cliquez ici pour télécharger le fichier exemple AjoutEnregistrementsII