logo Pierre AULAS
Visual Basic 6 - ADO (connexion aux bdd)
 Parcours  |   Réalisations  |   Cours  |   Chroniques  |   Divers
Se connecter à la base
Créer les objets adéquats
L'objet Connection
L'objet Command
L'objet Recordset
Se déplacer entre les enregistrements
Enregistrer, insérer, supprimer
Quitter
Effacer
Nouveau
Enregistrer
Trier

Problèmes d'ADO

ADO (pour Active X Data Object) est l'interface d'OLEDB pour l'accès aux bases de données via un fournisseur (autrement dit ADO est là pour permettre de se connecter à à peu près n'importe quelle base ce qui la distingue de DAO). Elle permet de créer des applications client-serveur aussi bien en local que via le réseau.

Le principe est de se connecter à l'aide du code VB à la base biblio.mdb qui se trouve dans le répertoire Program Files / Microsoft Visual Studio / VB98 et de réaliser une interface qui mettent en oeuvre les 4 manipulations de donnée standard à savoir: affichage, insertion, modification et suppression.

Pour un utilisateur c'est le minimum. Pour nous vous allez voir que c'est un petit peu plus complexe.

Vous pouvez récupérer ici l'exécutable exADO.exe. Pour voir comment cela fonctionne le fichier biblio.mdb doit se trouver dans le même répertoire que l'exécutable (comme il pèse 3 Mo, je vous laisse le soin de le retrouver sur votre machine). Sinon en désespoir de cause tentez votre chance ici.

Les 4 zones de texte doivent afficher certaines infos concernant les éditeurs (on travaille uniquement sur la table Publishers) de la base de donnée biblio.mdb et en permettre la modification.

Attention: la liste des propriétés est plus longue que d'habitude, regardez bien la capture d'écran avant de vous lancer et faites attention à bien distinguer les groupes de contrôles.

 

Objet  Propriété  Valeur
Form1  Name  frmADO
 Caption  Exercice - ADO
Label1  Name  lblChamp
 Caption  ID:
 Index  0
Label2  Name  lblChamp
 Caption  Nom::
 Index  1
Label3  Name  lblChamp
 Caption  Ville:
 Index  2
Label4  Name  lblChamp
 Caption  Etat:
 Index  3
Label5  Name  lblNom
 Caption  rien
Text1  Name  txtID
 Locked  True
 BackColor Gris
Text2  Name  txtNom
Text3  Name  txtVille
Text4  Name  txtEtat
Frame1  Name  fraTri
 Caption  Tri
Frame2  Name  fraFiltre
 Caption  Filtre
Option1  Name  optTri
 Caption  Aucun
 Index  0
Option1  Name  optTri
 Caption  Nom
 Index  1
Option1  Name  optTri
 Caption  Ville, décroissant
 Index  2
Option2  Name  optFiltre
 Caption  Sans
 Index  0
Option2  Name  optFiltre
 Caption  Nom avec 'A'
 Index  1
Option2  Name  optFiltre
 Caption  Ville de New York
 Index  2
Commande1  Name  cmdMove
 Caption  | <
 Index  0
Commande1  Name  cmdMove
 Caption  <
 Index  1
Commande1  Name  cmdMove
 Caption  >
 Index  2
Commande1  Name  cmdMove
 Caption  > |
 Index  3
Commande2  Name  cmdRequete
 Caption  &Effacer
 Index  0
Commande2  Name  cmdRequete
 Caption  &Nouveau
 Index  1
Commande2  Name  cmdRequete
 Caption  &Enregistrer
 Index  2
Commande2  Name  cmdRequete
 Caption  &Quitter
 Index  3

A l'arrivée cela devrait ressembler à cela:

Vérifiez que le premier champ ID est affiché mais ne peut être modifié (c'est la clef primaire de l'enregistrement). Sa propriété Locked est définie à True et sa couleur grisée le distingue des autres.

Si vraiment vous êtes dans la panade, vous pouvez toujours récupérer ici le formulaire prérempli et l'insérer dans votre projet.

Se connecter à la base

Toutes les connections ADO reposent sur des bibliothèques d'objets spécialement concu pour se connecter aux BDD.
La bibliothèque que nous allons utiliser s'appelle Microsoft ActiveX Data Object 2.0 Library. Il en existe des versions plus récentes que d'autres mais vous devriez disposer au moins celle-là.
Elles fonctionnent de toute manière toutes sur le même principe: connexion, requête, manipulation des résultats.
Si vous avez bien suivi le cours de PHP cela devrait vous rappeler quelque chose (genre mysql_connect, mysql_query et mysql_fetch_qc).

La première étape consiste à relier la bibliothèque ADO au projet à l'aide du menu Projet > Références puis de la librairie Microsoft ActiveX Data Object 2.0 Library (où plus récent si ca vous chante).

Ensuite ça se passe dans le code où on va créer trois objets fournis par la nouvelle bibliothèque:
  - Connection (pour la connexion)
  - Command (pour les requêtes)
  - Recordset (pour l'affichage)
Le tout dans l'en-tête du module car ces trois objets vont nous servir dans les différentes procédures du module (elles doivent donc avoir une portée module).

NB: Si vous voulez en savoir plus, vous pouvez d'ores et déjà jeter un coup d'oeil à la librairie ADODB (oui, le nom est sauvage, mais c'est ce qui correspond au composant que vous venez de rajouter) dans l'explorateur d'objet.

Déclarer et créer nos objets

Pour gagner du temps on peut créer ces objets en même temps qu'on les déclare de la manière suivante:

Option Explicit
Dim cnnADO As New ADODB.Connection
Dim cmdADO As New ADODB.Command
Dim rsADO As New ADODB.RecordSet

Il est important de préciser que ces objets relèvent de la bibliothèque ADODB (ActiveX Data Object) car il existe d'autres objets Connection ce qui peut entraîner des confusions. C'est pourquoi on écrit ADODB.Connection plutôt que Connection tout court.

L'objet Connection

La source de donnée est définie au démarrage de l'application, c'est-à-dire dans la procédure événementielle Form_Load.
La connexion ne sera interrompue qu'à la fermeture de l'application.

La connection à la source de donnée se fait par la définition des propriétés Provider et ConnectionString de cnnADO.
La propriété Provider permet de définir, parmi tous les fournisseurs installés sur votre machine, celui que vous allez choisir pour vous connecter.

Un des principaux intérêts de la connexion ADO est de permettre le choix de Provider très différents  :

Comme nous allons travailler avec une base Access, vous allez appeler le provider Jet qui est commun aux bases de données Microsoft de la manière suivante  :

cnnADO.Provider = "Microsoft.Jet.OLEDB.3.51"

Reste ensuite à définir avec quelle base de donnée vous voulez travailler. Si vous placez celle-ci dans le même répertoire que votre projet VB, vous pourrez y faire référence de la manière suivante:

cnnADO.ConnectionString = App.Path & "\BIBLIO.MDB"

La syntaxe App.Path renvoie le chemin du répertoire où se trouve votre projet VB. Le & "\BIBLIO.MDB" permet de concaténer le chemin du répertoire où se trouve votre projet avec le nom de la base de donnée.

Il ne reste plus alors qu'à appeler la méthode Open pour établir la connexion selon la syntaxe:

cnnADO.open

Testez votre application à cette étape avant d'aller plus loin. Si aucun message d'erreur n'apparaît, c'est que la connexion s'est bien déroulée.

L'objet Command

La propriété ActiveConnection de l'objet Command va permettre de le relier à la connexion ouverte. Un fois le lien fait on peut alors exécuter une requête SQL via sa propriété CommandText (si cela vous rappelle quelque chose comme mysql_query(requete, connexion) c'est bon signe).

Private Sub Form_Load()
  'Ici on s'occupe de paramétrer l'objet connection
  cnnADO.Provider = "Microsoft.Jet.OLEDB.3.51" 'On choisit le provider
  cnnADO.ConnectionString = App.Path & "\BIBLIO.MDB" 'On indique la base
  cnnADO.Open 'On ouvre la connexion

  'Ici on s'occupe de paramétrer l'objet command
  cmdADO.ActiveConnection = cnnADO 'On créé le lien
  cmdADO.CommandText = "SELECT PubID, [Company Name], City, State FROM Publishers"
  'Lorsque vous tombez sur un champ dont l'intitulé tient en plusieurs mots
  'vous êtes obligé d'y faire référence [entre crochet]
End Sub

Reste alors à définir la nature du RecordSet qui va recevoir le résultat de la requête.

La propriétés CursorType permet de définir la manière dont le RecordSet va pourvoir accéder aux enregistements. Certains curseurs n'autorisent que la lecture des enregistrements (adOpenStatic) et parfois uniquement en avant (adOpenForwardOnly). Plus les options de ces curseurs sont limitées, plus ceux-ci sont rapides. À vous de voir selon l'usage (lecture uniquement ou écriture auquel cas vous recourerez au adOpenDynamic).

La propriété LockType permet de gérer les problèmes de transaction de manière plus ou moins optimiste: adLockOptimistic (lecture/écriture à plusieurs, en croisant les doigts pour qu'il n'y ait pas mise à jour simultanée d'un même enregistrement), adLockPessimistic (lecture/écriture limité à un seul) et adLockReadOnly (uniquement en lecture).

L'objet RecordSet

Une fois toutes ces propriétés définies, il ne reste plus qu'à charger le résultat de la requête cmdADO dans le RecordSet à l'aide de la propriété Open comme suit:

  rsADO.CursorLocation = adUseClient
  rsADO.CursorType = adOpenDynamic
  rsADO.LockType = adLockPessimistic
  rsADO.Open cmdADO

Lorsqu'on récupère un jeu d'enregistements, l'objet RecordSet est toujours positionné sur le premier enregistement.
Reste à écrire une procédure LireEnregistrement pour envoyer le contenu des champs vers les zones de texte.

La syntaxe pour récupérer le champ d'un enregistrement est soit:

txtID.text = rsADO("PubID").Value

qui renvoie la valeur, soit:

txtID.text = rsADO!PubID

qui renvoie un objet Field. La plupart du temps celui-ci contient une chaîne de caractère mais il se peut qu'il contienne une valeur NULL non supportée par les chaînes. Aussi faut-il créer une fonction qui convertit les valeurs NULL retournées en chaîne vide.

Il nous faut donc une petite fonction qui fait appel à la fonction système IsNull (qui comme son nom l'indique, permet de détecter si un champs contient une valeur nulle), du genre  :

Private Function SansNull(fld As Field) As String
  If IsNull (fld) Then
    SansNull = ""
  Else
    SansNull = fld
  End If
End Function

qu'on appelle par son nom:

txtID.text = SansNull(rsADO!PubID)
txtNom.text = SansNull(rsADO![Company Name])
txtVille.text = SansNull(rsADO!City)
txtEtat.text = SansNull(rsADO!State)

Attention: remarquez la syntaxe [Company Name]. Lorsqu'un champ comporte plusieurs termes, ceux-ci sont regroupés entre crochets.
Cependant, lorsque vous concevez une bdd, prenez l'habitude de nommer vos champs par une chaîne de caratère unique.

Reste à gérer l'affichage de la chaîne "Enregistrement 1 de 727" dans l'étiquette lblNom en recourant aux méthodes AbsolutePosition et RecordCount de l'objet rsADO.

Pensez enfin à refermer la connexion lorsque l'application se ferme avec l'événement Form_Unload et la méthode Close :

Private Sub Form_Unload(Cancel As Integer)
  cnnADO.Close
End Sub

Si vous lancez maintenant votre application, le premier enregistrement de la table Publishers de la base biblio.MDB devrait maintenant s'afficher comme suit:

Se déplacer entre les enregistrements

Il s'agit maintenant de réaliser la procédure qui gère les déplacements entre les différents enregistrements.
C'est la procédure événementielle _Click associée au groupe de contrôles cmdMove qui va devoir s'en charger.

L'objet RecordSet rsADO possède plusieurs méthodes qui répondent à cette problématique  : MoveFirst, MovePrevious, MoveNext, et MoveLast qui permettent de déplacer le curseur à l'intérieur du RecordSet.

Pour vérifier si le curseur ne sort pas de la plage des enregistrements disponibles, RecordSet dispose des méthodes BOF (Begin Of File) et EOF (End Of File) qui indiquent si l'on atteint respectivement le début ou la fin des enregistrements.

À vous d'écrire la procédure (avec un petit Select Case).

Désormais vous pouvez visualiser tous les enregistrements de la table en passant de l'un à l'autre.

Pour l'instant nous nous sommes contentés d'afficher le contenu de la table, maîtrisant ainsi la première étape des manipulation de données.
Restent à voir: l'insertion, la modification, la suppression, que gère, précisement, le groupe de contrôles cmdRequete.

Haut de page

Effacer, Insérer et Modifier

Là encore les méthodes de l'objet RecordSet font le travail à votre place: Delete, AddNew, UpData, pour ne citer que les indispensables.

Quitter

Commençons par le plus facile: le bouton Quitter qui se contente de faire un Unload Me.

Effacer

Puis occupons nous du bouton Effacer qui supprime l'enregistrement courant et repositionne sur l'enregistrement précédent ou suivant (attention à ne pas omettre cette seconde étape qui consiste à faire ce que fait le deuxième élément du groupe de contrôle cmdMove).

Autrement dit quelque chose du genre:

rsADO.Delete 'Qui supprime l'enregistrement courant
cmdMove_Click 2 'Qui appelle la procédure cmdMove_Click en lui passant pour valeur d'Index 2

Il se peut que la commande Effacer génère des erreurs car la table Publishers est liée à d'autres sur certains enregistrements.
Si cela vous paraît indécent, vous pouvez toujours coller une rustine du type On error resume next sur la ligne qui précède le Delete (c'est-à-dire: en cas d'erreur, aller voir plus loin).

Nouveau

Le bouton Nouveau se contente de créer un nouvel enregistrement à l'aide de la méthode AddNew du RecordSet et de présenter un formulaire vide (à l'aide de la procédure LireEnregistrement).

C'est dans un second seulement, lorsque l'utilisateur appuyera sur Enregistrer que le formulaire affiché sera enregistré.

Dans un premier temps donc, on créé un nouvel enregistrement et on l'affiche, ce qui en VB nous donne quelque chose comme:

rsADO.addNew
LireEnregistrement

Enregistrer

Pour Enregistrer, on va utiliser la méthode UpDate.
Le principe consiste à affecter à l'enregistrement courant le contenu des trois champs txtNom, txtVille et txtEtat.

On garde alors en mémoire la position de l'enregistrement en testant la propriété Bookmark (qui renvoie la position du curseur dans le RecordSet), on fait la mise à jour en appelant la méthode .Update, on renouvelle la requête à l'aide de la méthode Requery (donc on reçoit un RecordSet tout neuf qui prend en compte les modifications apportées) et on définit la propriété Bookmark à sa valeur antérieure pour voir apparaître avant de faire appel à la procédure LireEnregistrement qui va nous afficher le nouvel enregistrement tout neuf..

Enfin on affiche l'enregistement suite à la mise à jour à l'aide de la procédure LireEnregistrement.
Ce qui nous donne au bout du compte:

rsADO![Company Name] = AvecNull(txtNom.text)
rsADO!City = AvecNull(txtVille.text)
rsADO!State = AvecNull(txtEtat.text)

vntSignet = rsADO.Bookmark
rsADO.UpDate
rsADO.Requery
LireEnregistrement

avec la fonction AvecNull qui est le pendant de SansNull:

Private Function AvecNull(fld As Field) As String
  If IsNull (fld) Then
    AvecNull = ""
  Else
    AvecNull = fld
  End If
End Function

Si à cette étape vous faites des tests un peu soigneux, vous constaterez que l'usage des boutons du groupe de commande cmdMove et les boutons Effacer et Nouveau immédiatement après l'affichage d'un nouveau formulaire provoque un bug.
Cela est du au fait qu'il n'est pas possible de naviguer dans un RecordSet tant que celui-ci possède un enregistrement vide en attente.

A vous de placer aux bons endroits les quelques tests du type:

If txtID.text = "" Then Exit Sub
'Oui parce que si le champ ID est vide c'est qu'un AddNew vient d'être exécuté.

Haut de page

Tris et filtres

Le plus dur est fait: il ne nous reste plus qu'à gérer les options de tri et d'affichage.

Là encore ce sont des méthodes de l'objet RecordSet qui vont faire le boulot: sort et filter (qui trouvent bien sûr leur équivalent avec les syntaxes SQL ORDER BY et WHERE).

Pour Sort la syntaxe est la suivante:

rsADO.sort = "" 'Pour éliminer un tri
rsADO.sort = "[Company Name]" 'Pour effectuer un tri sur le champ Nom
rsADO.sort = "[Company Name] DESC" 'Pour effectuer un tri inverse sur le champ Nom

N'oubliez pas que pour que votre tri soit pris en compte, il faut relancer la requête:

rsAdo.requery

Pour Filter la syntaxe est la suivante:

rsADO.Filter = "" 'Pour supprimer un filtre
rsADO.Filter = "[Company Name] LIKE 'A*'" 'Pour n'afficher que les compagnies dont le nom commence par 'A'
rsADO.Filter = "City = 'New York'" 'Pour n'afficher que les enregistrements concernant New York

SI vous avez des problèmes, vous pouvez toujours télécharger les sources de l'exercice ici.

Haut de page
Plan du site  |  Mentions légales  |  Crédits  |  Aide