Parcourir des enregistrements

Retour vers Access

Dès que nous voulons développer une application de base de données un peu évoluée, nous sommes très vite confrontés à un problème épineux : comment récupérer la valeur des enregistrements précédents pour nous permettre de les manipuler à loisir dans des fonctions de comparaison, ou d'opérations mathématiques (addition, soustraction, multiplication, division) ou autres fantaisies.

Nous allons tenter d'apporter une réponse. Je dis bien tenter car de ma faible expérience, j'ai remarqué certaines anomalies dans la politique VBA chez microsoft : en effet, vous devez savoir que la plupart des procédures, méthodes, fonctions principales sont contenues dans les fameux .DLL dont nos ordinateurs regorgent. Ces fichiers sont comme des boîtes qui contiennent des mécanismes dont on a du mal à découvrir les fonctions exactes tant la documentation est rare. On ne sait ce qu'ils contiennent exactement, nous n'avons aucune emprise sur leur code...Bref, ceci pour en venir à quoi ? Simplement que chez MS, ils font évoluer ces .DLL et qu'il réécrivent certaines d'entres elles en modifiant la syntaxe et parfois même les paramètres que l'on doit leur transmettre...Si bien que j'ai remarqué que d'une configuration à l'autre, sur des MS Access de même génération, on n'obtient pas le même résultat et ce jusqu'à faire planter l'application.

On peut déterminer quelle .DLL on veut employer, car certaines versions peuvent très bien cohabiter, mais il faut savoir que certaines d'entre elles s'excluent. Bref, un casse tête pour les néophytes, y compris votre serviteur...Où peut-on tenter de régler cela ? et bien par tâtonnement ou par une documentation trouvée au gré des lectures...et dans Access, lorsque vous êtes dans VBE, allez sur le menu Outils - Références et cochez les cases adéquates comme ceci :

Celles qui vont nous intéresser surtout sont les ActiveX Data Objects et les DAO Objet Library, car c'est avec celles-là que nous allons dialoguer...rassurez-vous de manière transparente... mais il est bon de connaître leur existence car si vous n'obtenez pas le même résultat que moi dans l''exercice qui va nous occuper , c'est peut être dans cette direction qu'il faut chercher

Anecdotes personnelles :

  1. Travaillant sous NT4 dans une base de données partagée sur le réseau d'entreprise, j'implémente une fonction faisant appel à une API pour récupérer le nom de l'utilisateur connecté (UserName NT), j'obtiens le code sur différents sites...sur ma machine, ce code fonctionne. Tout heureux, je remets l'application en service. Hélas, je devais déchanter, des utilisateurs généraient des erreurs à l'exécution. Après étude, je remarque que ces machines étaient déjà sous Service Pack 6 pour NT, or mon ordi était encore sous Service Pack 4, j'upgrade ma machine...bardaf ! le code plante chez moi maintenant... Aie, aie !, bon !, recherche et travail m'ont finalement permis de trouver une syntaxe qui fonctionne...
  2. Idem pour le code ci-dessous, sous Access XP, la première solution a fonctionné de suite, par contre il a fallu que je découvre qu'il fallait déclarer dans quel mode (ADO ou DAO) j'abordais les recordsets pour que la seconde solution soit acceptée. Pire, avant cela, je déactivais les ActiveX Data Objet, je lance l'exécution de la méthode DAO, sans la déclaration spécifique, ça marche...par contre la méthode ADO plante, bien sûr... je réactive les ADO, je teste..et bien la méthode DAO fonctionne maintenant (même sans déclaration spécifique) alors qu'elle avait refusé jusqu'à présent, grrrr...!!! Bon, ne prenons plus de risque et travaillons en déclarant complètement nos objets

Et maintenant, l'exercice ...
Scénario : Un débit de boisson,on sert les client, et on manipule une caisse enregistreuse pour calculer l'addition. Voici ce que je veux obtenir...

Lorsque j'appuie sur un des boutons, la consommation s’inscrit dans le sous-formulaire comme un nouvel enregistrement, je fournis simplement la quantité de verres - paramètre que l'on ne peut pas prévoir. Le prix par type et l'addition totale se calculent. Et SEULEMENT AINSI, n'inscrivez pas vous-même le nom de la boisson dans le F_DetailCommande

Bien sûr, à partir de là, on peut imaginer la gestion complète d'un établissement, les stocks, les employés, la comptabilité , etc...etc...mais nous nous limiterons simplement à notre scénario même si dans les explications, vous pourrez entrevoir la puissante de l'application. Un peu comme la base de donnée fournie en exemple : Les Comptoirs. Mon but ici est d'isoler la manière de parcourir les enregistrements, pour pouvoir la calquer ensuite très facilement à d'autres applications, car c'est un problème récurrent

Nous commençons par créer quelques tables toutes simples

Sur lesquelles, nous bâtissons des requêtes

un formulaire et un sous formulaire

Enfin, un module dont nous verrons l'utilité et le code tout à l'heure

Nous aurions pu ajouter un Etat qui aurait pu simuler le ticket de caisse, mais cela n'apporte pas grand chose de neuf
L'activité principale se concentre sur les événements "clic" des différents boutons, voici le code pour le 3ème bouton "Pelforth Brune". Cette procédure sera reproduite et adaptée pour chaque bouton (on pourrait créer un module vers lequel on enverrait des paramètres comme le nom du produit etc... pour se rapprocher d'une programmation de puriste et ne pas faire de copier-coller, mais je pense que l'on peut envisager d'abord les choses simplement...Apprenons à marcher, nous courrons plus tard

Première méthode: ADO

Private Sub Commande27_Click()
'On Error GoTo Err_Commande27_Click
   '1ère sous routine on récupère le prix de vente de T_GestionProduit
Dim rs1 As New ADODB.Recordset
Dim rsPrixVente As Currency
Dim rsQuantite As Integer
rs1.Open "T_GestionProduit", CurrentProject.Connection, adOpenDynamic
    rs1.Find "Produit = 'Pelforth Brune'"
    rsPrixVente = rs1("PrixVente")
rs1.Close
Set rs1 = Nothing

rsQuantite = InputBox("Quelle quantité ?", "Combien...")


'2ème sous routine on remplit le détail de la commande
Dim rs2 As New ADODB.Recordset
Dim rsNom As String
Dim rsPrix As Currency
rs2.Open "T_DetailsCommande", CurrentProject.Connection, adOpenDynamic, adLockOptimistic
  rs2.AddNew
  rs2("RefCommande") = Me.RefCommande
  rs2("Produit") = "Pelforth Brune"
  rs2("Prix") = rsPrixVente
  rs2("Quantite") = rsQuantite
  rs2("Total") = rs2("Prix") * rsQuantite
  rs2.Update
rs2.Close
Set rs2 = Nothing
Call CalculAddition
Me.Refresh
Exit_Commande27_Click:
    Exit Sub

Err_Commande27_Click:
    MsgBox Err.Description
    Resume Exit_Commande27_Click
    
End Sub

On remarque qu'en fin de code, il y a un appel vers une autre procédure. Celle-ci est contenue dans un module. car on peut y faire appel sur d'autres événements, pour permettre un rafraîchissement du montant de l'addition, au cas où l'on supprime des enregistrements, ou lorsque l'on change d'enregistrement, etc..

Option Compare Database
Option Explicit

Sub CalculAddition()
'3ère sous routine on récupère le prix de vente de T_GestionProduit
Dim rs3 As New ADODB.Recordset
Dim rs3Addition As Currency

rs3.Open "T_DetailsCommande", CurrentProject.Connection, adOpenDynamic
    rs3Addition = 0
    rs3.MoveFirst
Do
    If rs3("RefCommande") = Form_F_Commandes.RefCommande Then
    rs3Addition = rs3("Total") + rs3Addition
    End If
    rs3.MoveNext
Loop Until rs3.EOF
    Form_F_Commandes.Addition = rs3Addition
    
rs3.Close
Set rs3 = Nothing
  Form_F_Commandes.Refresh

End Sub

Voilà ! c'est une des méthodes qui permet de parcourir les enregistrements pour retrouver certaines valeurs (Prix de vente) et qui permet de réaliser un calcul sur une "colonne" (Addition)...

Seconde méthode: DAO

Seconde méthode qui fonctionne sur Access 97. Le code sera tout à fait différent et un peu plus universel dans les environnements Access (97 - 2000 - 2002)

Private Sub Commande28_Click()
On Error GoTo Err_Commande28_Click
'1er procédure on retrouve le prix de vente
    Dim db As DAO.Database, rs1 As DAO.Recordset, rs2 As DAO.Recordset
    Dim strSQL1 As String, strSQL2 As String
    Dim Prix As Currency, Addition As Currency, Com As Integer
    Set db = CurrentDb
    strSQL1 = "SELECT * FROM T_GestionProduit"
    Set rs1 = db.OpenRecordset(strSQL1)
    Set rs2 = db.OpenRecordset("T_DetailsCommande", dbOpenTable)
    Com = Me.RefCommande
    rs1.MoveFirst
    Do
        If rs1("Produit") = "Get 27" Then
        Prix = rs1("PrixVente")
        End If
    rs1.MoveNext
    Loop Until rs1.EOF = True
    With rs2
       .AddNew
    !RefCommande = Com
    !Produit = "Get 27"
    !Prix = Prix
    !Quantite = InputBox("Quelle quantité ?", "Combien...")
    !Total = Prix * !Quantite
        .Update
    End With
    rs1.Close
    rs2.Close
    Set db = Nothing
    Me.Refresh
    Call CalculAddition
Exit_Commande28_Click:
    Exit Sub
Err_Commande28_Click:
    MsgBox Err.Description: Resume Exit_Commande28_Click
End Sub

En fushia, la déclaration qui m'a tant fait défaut dans les premières heures...En vert, les lignes sur lesquelles le code butait et deux manières d'instancier les recordsets

Cliquez ici pour télécharger le fichier zip RestoAccess2000

Fin