Vous êtes sur la page 1sur 92

Définition et manipulation de données avec DAO

Par Christophe WARIN

Date de publication : 9 mai 2005

Dernière mise à jour : 30 juillet 2009

Ce support constitue un cours d'introduction à l'accés aux données dans une base
Access via DAO (Data Access Object). Il ne nécessite pas de connaissance pointue en
programmation hormis les bases du langage VBA.

Commentez
Définition et manipulation de données avec DAO par Christophe WARIN

1 - Introduction & Téléchargement..............................................................................................................................7


1.1 - Téléchargement............................................................................................................................................. 7
1.2 - Introduction.................................................................................................................................................... 7
2 - La hiérarchie du modèle DAO............................................................................................................................... 8
2.1 - Le modèle objet.............................................................................................................................................8
2.2 - Quelques rappels sur les collections.............................................................................................................9
2.2.1 - Accéder à un élément d'une collection.................................................................................................9
2.2.2 - Compter les éléments........................................................................................................................... 9
2.2.3 - Parcourir les éléments d'une collection................................................................................................ 9
2.2.4 - Ajouter un élément.............................................................................................................................. 10
2.2.5 - Supprimer un élément.........................................................................................................................10
3 - Accèder à une base de données........................................................................................................................ 11
3.1 - L'objet DBEngine......................................................................................................................................... 11
3.1.1 - Généralités.......................................................................................................................................... 11
3.1.2 - Liste des propriétés.............................................................................................................................11
3.1.2.1 - DefaultPassword......................................................................................................................... 11
3.1.2.2 - DelfaultType................................................................................................................................ 11
3.1.2.3 - DefaultUser................................................................................................................................. 11
3.1.2.4 - Errors...........................................................................................................................................11
3.1.2.5 - Inipath..........................................................................................................................................12
3.1.2.7 - Properties.................................................................................................................................... 12
3.1.2.8 - SystemDB................................................................................................................................... 12
3.1.2.9 - Version........................................................................................................................................ 12
3.1.2.10 - Workspaces...............................................................................................................................13
3.1.3 - Liste des méthodes............................................................................................................................. 13
3.1.3.1 - BeginTrans.................................................................................................................................. 13
3.1.3.2 - CommitTrans............................................................................................................................... 13
3.1.3.3 - CompactDatabase.......................................................................................................................13
3.1.3.4 - CreateDatabase.......................................................................................................................... 13
3.1.3.5 - CreateWorkspace........................................................................................................................14
3.1.3.6 - Idle...............................................................................................................................................14
3.1.3.7 - OpenDatabase............................................................................................................................ 14
3.1.3.8 - RepairDatabase.......................................................................................................................... 15
3.1.3.9 - Rollback.......................................................................................................................................15
3.2 - L'objet Workspace....................................................................................................................................... 15
3.2.1 - Généralités.......................................................................................................................................... 15
3.2.2 - Liste des propriétés.............................................................................................................................16
3.2.2.1 - Databases................................................................................................................................... 16
3.2.2.2 - IsolateODBCTrans...................................................................................................................... 16
3.2.2.3 - Name...........................................................................................................................................16
3.2.2.4 - Properties.................................................................................................................................... 16
3.2.2.5 - Type.............................................................................................................................................17
3.2.3 - Liste des méthodes............................................................................................................................. 17
3.2.3.1 - BeginTrans.................................................................................................................................. 17
3.2.3.2 - Close........................................................................................................................................... 17
3.2.3.3 - CommitTrans............................................................................................................................... 17
3.2.3.4 - CreateDatabase.......................................................................................................................... 18
3.2.3.5 - OpenDatabase............................................................................................................................ 18
3.2.3.6 - Rollback.......................................................................................................................................18
3.2.4 - Accéder à un groupe de travail spécifique......................................................................................... 19
3.3 - L'objet Database.......................................................................................................................................... 21
3.3.1 - Généralités.......................................................................................................................................... 21
3.3.1.1 - La méthode CurrentDb............................................................................................................... 22
3.3.1.2 - La méthode CodeDb...................................................................................................................22
3.3.2 - Liste des propriétés.............................................................................................................................23
3.3.2.1 - CollatingOrder............................................................................................................................. 23
3.3.2.2 - Connect....................................................................................................................................... 23
3.3.2.3 - Containers................................................................................................................................... 23

-2-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.3.2.4 - Name...........................................................................................................................................24
3.3.2.5 - Properties.................................................................................................................................... 24
3.3.2.6 - QueryDefs................................................................................................................................... 24
3.3.2.7 - RecordsAffected.......................................................................................................................... 24
3.3.2.8 - Recordsets.................................................................................................................................. 25
3.3.2.9 - Relations..................................................................................................................................... 25
3.3.2.10 - TableDefs.................................................................................................................................. 25
3.3.2.11 - Transactions.............................................................................................................................. 25
3.3.2.12 - Updatable.................................................................................................................................. 25
3.3.2.13 - Version...................................................................................................................................... 26
3.3.3 - Liste des méthodes............................................................................................................................. 26
3.3.3.1 - Close........................................................................................................................................... 26
3.3.3.2 - CreateProperty............................................................................................................................ 26
3.3.3.3 - CreateQueryDef.......................................................................................................................... 26
3.3.3.4 - CreateRelation............................................................................................................................ 26
3.3.3.5 - CreateTableDef........................................................................................................................... 27
3.3.3.6 - Execute....................................................................................................................................... 27
3.3.3.7 - NewPassword............................................................................................................................. 27
3.3.3.8 - OpenRecordset........................................................................................................................... 27
4 - DAO et la structure d'une base de données....................................................................................................... 28
4.1 - Généralités...................................................................................................................................................28
4.2 - Les propriétés spécifiques...........................................................................................................................28
4.2.1 - Définitions............................................................................................................................................ 28
4.2.2 - Liste des propriétés d'un objet Property............................................................................................. 29
4.2.2.1 - Inherited...................................................................................................................................... 29
4.2.2.2 - Name...........................................................................................................................................30
4.2.2.3 - Type.............................................................................................................................................30
4.2.2.4 - Value........................................................................................................................................... 30
4.2.3 - Accéder à une propriété..................................................................................................................... 30
4.2.4 - Modifier la valeur d'une propriété....................................................................................................... 31
4.2.5 - Création d'une nouvelle propriété....................................................................................................... 33
4.3 - L'objet TableDef........................................................................................................................................... 34
4.3.1 - Définitions............................................................................................................................................ 34
4.3.2 - Liste des propriétés.............................................................................................................................34
4.3.2.1 - Attributes..................................................................................................................................... 34
4.3.2.2 - Connect....................................................................................................................................... 34
4.3.2.3 - DataCreated................................................................................................................................ 35
4.3.2.4 - Fields...........................................................................................................................................35
4.3.2.5 - Indexes........................................................................................................................................35
4.3.2.6 - LastUpdated................................................................................................................................ 35
4.3.2.7 - Name...........................................................................................................................................35
4.3.2.8 - Properties.................................................................................................................................... 35
4.3.2.9 - RecordCount............................................................................................................................... 36
4.3.2.10 - SourceTableName.....................................................................................................................36
4.3.2.11 - Updatable.................................................................................................................................. 36
4.3.2.12 - ValidationRule........................................................................................................................... 36
4.3.2.13 - ValidationText............................................................................................................................ 36
4.3.3 - Liste des méthodes............................................................................................................................. 36
4.3.3.1 - CreateField..................................................................................................................................36
4.3.3.2 - CreateIndex.................................................................................................................................37
4.3.3.3 - CreateProperty............................................................................................................................ 37
4.3.3.4 - OpenRecordset........................................................................................................................... 37
4.3.3.5 - RefreshLink................................................................................................................................. 37
4.3.4 - Opérations sur les tables d'une base de données............................................................................. 37
4.3.4.1 - Lister les tables d'une base de données....................................................................................37
4.3.4.2 - Renommer une table.................................................................................................................. 38
4.3.4.3 - Supprimer une table................................................................................................................... 39
4.3.4.4 - Créer une nouvelle table............................................................................................................ 40

-3-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.4 - L'objet Field..................................................................................................................................................41


4.4.1 - Définition..............................................................................................................................................41
4.4.2 - Liste des propriétés.............................................................................................................................41
4.4.2.1 - AllowZeroLength......................................................................................................................... 41
4.4.2.2 - Attributes..................................................................................................................................... 41
4.4.2.3 - CollatingOrder............................................................................................................................. 42
4.4.2.4 - DataUpdatable............................................................................................................................ 43
4.4.2.5 - DefaultValue................................................................................................................................ 43
4.4.2.6 - FieldSize......................................................................................................................................43
4.4.2.7 - ForeignName...............................................................................................................................43
4.4.2.8 - Name...........................................................................................................................................43
4.4.2.9 - OrdinalPosition............................................................................................................................ 43
4.4.2.10 - Properties.................................................................................................................................. 44
4.4.2.11 - Required.................................................................................................................................... 44
4.4.2.12 - Size........................................................................................................................................... 44
4.4.2.13 - SourceField............................................................................................................................... 44
4.4.2.14 - SourceTable.............................................................................................................................. 45
4.4.2.15 - Type...........................................................................................................................................45
4.4.2.16 - ValidationRule........................................................................................................................... 46
4.4.2.17 - ValidationText............................................................................................................................ 46
4.4.2.18 - Value......................................................................................................................................... 46
4.4.2.19 - VisibleValue............................................................................................................................... 46
4.4.3 - Liste des méthodes............................................................................................................................. 47
4.4.3.1 - AppendChunk..............................................................................................................................47
4.4.3.2 - CreateProperty............................................................................................................................ 47
4.4.3.3 - GetChunk.................................................................................................................................... 47
4.4.4 - Opérations sur les champs d'un objet TableDef................................................................................. 47
4.4.4.1 - Renommer un champ................................................................................................................. 47
4.4.4.2 - Supprimer un champ.................................................................................................................. 48
4.4.4.3 - Créer un champ.......................................................................................................................... 50
4.4.4.4 - Dupliquer un champ....................................................................................................................51
4.5 - L'objet Index.................................................................................................................................................51
4.5.1 - Définitions............................................................................................................................................ 52
4.5.2 - Liste des propriétés.............................................................................................................................52
4.5.2.1 - DistinctCount............................................................................................................................... 52
4.5.2.2 - Fields...........................................................................................................................................52
4.5.2.3 - Foreign........................................................................................................................................ 52
4.5.2.4 - IgnoreNulls.................................................................................................................................. 52
4.5.2.5 - Name...........................................................................................................................................52
4.5.2.6 - Properties.................................................................................................................................... 53
4.5.2.7 - Required......................................................................................................................................53
4.5.2.8 - Unique......................................................................................................................................... 53
4.5.3 - Liste des méthodes............................................................................................................................. 53
4.5.3.1 - CreateField..................................................................................................................................53
4.5.3.2 - CreateProperty............................................................................................................................ 53
4.5.4 - Opérations sur les Index.....................................................................................................................54
4.5.4.1 - Créer un index............................................................................................................................ 54
4.5.4.2 - Supprimer une clé primaire........................................................................................................ 54
4.6 - L'objet Relation............................................................................................................................................ 55
4.6.1 - Définitions............................................................................................................................................ 55
4.6.2 - Liste des propriétés.............................................................................................................................55
4.6.2.1 - Attributes..................................................................................................................................... 55
4.6.2.2 - Fields...........................................................................................................................................55
4.6.2.3 - ForeignTable................................................................................................................................55
4.6.2.4 - Name...........................................................................................................................................56
4.6.2.6 - Properties.................................................................................................................................... 56
4.6.2.7 - Table............................................................................................................................................56
4.6.3 - Liste des méthodes............................................................................................................................. 56

-4-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.6.4 - Exemple de définition des propriétés..................................................................................................56


4.6.5 - Opérations sur les relations................................................................................................................ 57
4.6.5.1 - Créer une relation....................................................................................................................... 57
4.6.5.2 - Compter les relations utilisant un champ donné........................................................................ 58
4.6.5.3 - Supprimer les relations autour d'une table................................................................................. 59
4.7 - L'objet QueryDef.......................................................................................................................................... 60
4.7.1 - Définitions............................................................................................................................................ 60
4.7.2 - Liste des propriétés.............................................................................................................................61
4.7.2.1 - Connect....................................................................................................................................... 61
4.7.2.2 - DateCreated................................................................................................................................ 61
4.7.2.3 - Fields...........................................................................................................................................61
4.7.2.4 - LastUpdated................................................................................................................................ 62
4.7.2.5 - MaxRecords................................................................................................................................ 62
4.7.2.6 - Name...........................................................................................................................................62
4.7.2.7 - Parameters..................................................................................................................................62
4.7.2.8 - Properties.................................................................................................................................... 62
4.7.2.9 - RecordsAffected.......................................................................................................................... 62
4.7.2.10 - ReturnsRecords........................................................................................................................ 63
4.7.2.11 - SQL........................................................................................................................................... 63
4.7.2.12 - Type...........................................................................................................................................63
4.7.2.13 - Updatable.................................................................................................................................. 63
4.7.3 - Liste des méthodes............................................................................................................................. 64
4.7.3.1 - CreateProperty............................................................................................................................ 64
4.7.3.2 - Execute....................................................................................................................................... 64
4.7.3.3 - OpenRecordset........................................................................................................................... 64
4.7.4 - Opérations sur les requêtes................................................................................................................65
4.7.4.1 - Création d'une requête............................................................................................................... 65
4.7.4.2 - Modifier le code d'une requête................................................................................................... 65
4.7.4.3 - Lister les requêtes...................................................................................................................... 66
5 - Accès aux données............................................................................................................................................. 67
5.1 - Définition...................................................................................................................................................... 67
5.1.1 - Les différents types de Recordset...................................................................................................... 67
5.2 - Ouvrir et fermer un recordset......................................................................................................................68
5.2.1 - Depuis un objet Database.................................................................................................................. 68
5.2.2 - Depuis un objet QueryDef.................................................................................................................. 70
5.2.3 - Depuis un formulaire Access.............................................................................................................. 70
5.2-4 - Fermer un Recordset.......................................................................................................................... 71
5.3 - Positions et déplacements...........................................................................................................................71
5.3.1 - Se déplacer dans un Recordset......................................................................................................... 71
5.3.2 - Trouver un enregistrement.................................................................................................................. 72
5.3.3 - Mémoriser une position.......................................................................................................................73
5.4 - Manipulation des données...........................................................................................................................73
5.4.1 - Lire un enregistrement........................................................................................................................ 73
5.4.2 - Modifier un enregistrement................................................................................................................. 73
5.4.3 - Ajouter un enregistrement...................................................................................................................74
5.4.4 - Supprimer un enregistrement..............................................................................................................76
5.4.5 - Compter les enregistrements.............................................................................................................. 76
5.4.6 - Filtrer les données...............................................................................................................................77
5.5 - Lecture par bloc...........................................................................................................................................78
5.5.1 - Généralités.......................................................................................................................................... 78
5.5.2 - Exemple...............................................................................................................................................79
5.6 - Liste des propriétés..................................................................................................................................... 81
5.6.1 - AbsolutePosition.................................................................................................................................. 81
5.6.2 - BOF..................................................................................................................................................... 81
5.6.3 - Bookmark.............................................................................................................................................81
5.6.4 - Bookmarkable......................................................................................................................................82
5.6.5 - CacheSize........................................................................................................................................... 82
5.6.6 - CacheStart...........................................................................................................................................82

-5-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.6.7 - Connection...........................................................................................................................................82
5.6.8 - DataCreated........................................................................................................................................ 83
5.6.9 - EditMode..............................................................................................................................................83
5.6.10 - EOF................................................................................................................................................... 83
5.6.11 - Fields................................................................................................................................................. 84
5.6.12 - Filter...................................................................................................................................................84
5.6.13 - Index.................................................................................................................................................. 84
5.6.14 - LastModified...................................................................................................................................... 84
5.6.15 - LastUpdated...................................................................................................................................... 85
5.6.16 - LockEdits........................................................................................................................................... 85
5.6.17 - Name................................................................................................................................................. 85
5.6.18 - NoMatch............................................................................................................................................ 85
5.6.19 - PercentPosition..................................................................................................................................85
5.6.20 - Properties.......................................................................................................................................... 86
5.6.21 - RecordCount......................................................................................................................................86
5.6.22 - Restartable........................................................................................................................................ 86
5.6.23 - Sort.................................................................................................................................................... 86
5.6.24 - StillExecuting..................................................................................................................................... 87
5.6.25 - Transactions...................................................................................................................................... 87
5.6.26 - Type................................................................................................................................................... 88
5.6.27 - Updatable.......................................................................................................................................... 88
5.6.28 - UpdateOptions...................................................................................................................................88
5.6.29 - ValidationRule.................................................................................................................................... 88
5.6.30 - ValidationText.....................................................................................................................................88
5.7 - Liste des méthodes..................................................................................................................................... 89
5.7.1 - AddNew............................................................................................................................................... 89
5.7.2 - CancelUpdate...................................................................................................................................... 89
5.7.3 - Clone................................................................................................................................................... 89
5.7.4 - Close....................................................................................................................................................90
5.7.5 - CreateQueryDef...................................................................................................................................90
5.7.6 - Delete.................................................................................................................................................. 90
5.7.7 - Edit.......................................................................................................................................................90
5.7.8 - FindFirst, FindLast, FindNext, FindPrevious....................................................................................... 90
5.7.9 - GetRows.............................................................................................................................................. 91
5.7.10 - Move, MoveFirst, MoveLast, MoveNext, MovePrevious................................................................... 91
5.7.11 - OpenRecordset.................................................................................................................................. 91
5.7.12 - Requery............................................................................................................................................. 91
5.7.13 - Update............................................................................................................................................... 91
6 - Conclusion............................................................................................................................................................92

-6-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

1 - Introduction & Téléchargement

1.1 - Téléchargement

Français Télécharger la version PDF de ce


tutoriel 96 pages - 547 Ko
FTP (Recommandé) : Télécharger
HTTP (Secours) : Télécharger
Arabe Télécharger la traduction de ce tutoriel
au format PDF 116 pages - 940 Ko par
MED ALAOUI SOSSE
FTP (Recommandé) : Télécharger
HTTP (Secours) : Télécharger

1.2 - Introduction

DAO (Data Access Objects) est une bibliothèque regroupant un ensemble d'objets permettant d'accéder à une base
de données. L'utilisation de ces objets permet à la fois de travailler la structure de la base mais aussi de manipuler
ses données.

Ce cours a pour objectif de vous enseigner les innombrables possibilités offertes par cette bibliothèque, que ce soit
aussi bien au niveau de la structure que des données. Via plusieurs exemples, vous allez ainsi découvrir comment
il est possible de créer une table, modifier ses champs, définir des relations, construire des requêtes, manipuler les
données d'un formulaire, ajouter de nouveaux enregistrements, ...

Vous pourrez aussi retrouver chacune des propriétés et des méthodes propres à chaque objet dans un listing en fin
de section. Bien entendu, cette liste ne prétend pas se substituer à l'aide Access qui, je vous le rappelle, reste la
plus grande mine d'informations.

Certaines parties ne sont pas détaillées dans ce document car elles ne répondent pas à une
utilisation classique de DAO avec le moteur Jet. Afin d'alleger ce cours, vous ne trouverez
donc pas d'informations concernant :

• L'acccès aux données dans un environnement ODBC Direct


• La replication
• Les objets DAO ne concernant pas l'accès aux données (Sécurité, Utilisateur, Conteneur ....)

Avant de commencer :

L'ensemble des méthodes et des objets permettant l'accès aux données via DAO sont regroupés au sein d'une même
librairie. Afin d'utiliser ces fonctionnalités, il vous faut donc ajouter la référence suivante à votre projet :

Microsoft DA0 3.5 Object Library pour Access 97.


Microsoft DA0 3.6 Object Library pour les versions utltérieures.
Microsoft Office 12.0 (14.0) Access Database Engine Object pour travailler avec des bases de données Access
2007 ou Access 2010.

Comment ajouter une référence ?


Depuis le menu Outils de l'éditeur Visual Basic, sélectionnez l'option Références. Cochez
ensuite la case correspondante à la référence à ajouter.

-7-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

2 - La hiérarchie du modèle DAO

2.1 - Le modèle objet

Voici une représentation du modèle objet DAO :

Comme vous pouvez le remarquer, le modèle objet DAO possède une structure hiérarchisée dont la racine est un
objet DBEngine. Les relations de descendance sont de type un à plusieurs. Cela signifie que chaque objet parent
possède une collection de chaque type d'objet enfant dont le nom est normalisé ainsi :

Nom de la collection = Type de l'objet enfant + "s"

Par exemple, l'objet DBEngine possède une collection d'objet Workspace. Cette collection est nommée
Workspaces.

Précisons aussi que ce schéma a été réduit uniquement à la partie définition de données (en bleu) et à la partie
manipulation de données (en vert). De plus, chaque branche a été réduite pour améliorer la lisibilité. Comme tout autre
objet, un objet DAO possède un ensemble de propriétés (property). Celles ci sont regroupées dans une collection
nommée properties propre à chaque objet. Voici un exemple du schéma réel à appliquer aux objets TableDef.

L'utilisation de DAO implique de nombreuses déclarations de variables. Ceci demande


beaucoup de rigueur. Aussi je vous invite à consulter le tutoriel sur les conventions
de nommage Visual Basic écrit par Jean-Philippe AMBROSINO : Les conventions
typographiques en VBA (illustrées sur Access)

-8-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

2.2 - Quelques rappels sur les collections

Etant donné que DAO est un modèle objet et qu'il utilise de nombreuses collections, je vous propose quelques rappels
sur le traitement des collections d'objets sous Visual Basic.

2.2.1 - Accéder à un élément d'une collection

Il existe deux techniques afin d'accéder à un objet d'une collection :

Accès via l'index : Il s'agit d'utiliser la position de l'élément dans la collection en sachant que le premier possède
l'index zéro.

Syntaxe :

MaCollection.Item(2)

Accès via la clé : Il s'agit d'utiliser le nom de l'élement lorsque celui-ci est connu.

Syntaxe :

MaCollection.Item ("MonItem")

La propriété Item est le membre par défaut des objets de type Collection. Vous pouvez donc
utiliser indifféremment :

Syntaxe :

MaCollection.Item ("MonItem")

Ou :

Syntaxe :

MaCollection.("MonItem")

2.2.2 - Compter les éléments

Sous Visual Basic, les collections proposent la propriété Count qui renvoie le nombre d'objets dans la collection.

Syntaxe :

MaCollection.Count

Etant donné que le premier élément a pour index 0, on en conclut aisément que le dernier
élément de la collection possède l'index : Count - 1

2.2.3 - Parcourir les éléments d'une collection

Une nouvelle fois, il est possible d'utiliser deux méthodes. La première consiste en une boucle sur l'index de la
collection jusqu'au dernier élément.

-9-
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Voici un exemple :

Dim i As Integer, nbMax As Integer


'Récupère le nombre de Workspace
nbMax = DBEngine.Workspaces.Count - 1
'Boucle sur l'index
For i = 0 To nbMax
'Affiche le nom de l'objet
MsgBox DBEngine.Workspaces(i).Name
Next i

La seconde méthode utilise une boucle For Each … In … Next pour parcourir un à un les objets de la collection.

Ainsi :

Dim oWks As DAO.Workspace


For Each oWks In DBEngine.Workspaces
'Affiche le nom de l'objet
MsgBox oWks.Name
Next oWks

Peut être traduit par :

Pour chaque objet Workspace de la collection Workspaces du DBEngine


Afficher le nom de l'objet
Fin Pour

Cette dernière méthode possède un avantage dans le cas de collections hétérogènes. Imaginons une collection
d'objets O1 et O2. Pour parcourir uniquement les éléments de type O1, nous aurions par exemple :

Dim oTmpObjet as TypeO1


For Each oTmpObjet In MaCollection
'Traitement à effectuer
Next oTmpObjet

2.2.4 - Ajouter un élément

Les collections DAO sont munies de la méthode Append qui permet d'ajouter un élément. Sa syntaxe est la suivante :

MaCollection.Append MonObjet

Notons tout de même que pour être ajouté, l'objet doit être instancié auparavant, sans quoi il sera impossible de
l'ajouter. De même, il est impossible d'ajouter un objet si un autre objet présent dans la collection possède le même
nom. Vous trouverez de nombreux exemples de la méthode Append dans la suite de ce document.

2.2.5 - Supprimer un élément

La méthode Delete appliquée aux collections DAO permet de supprimer l'élément dont le nom est passé en
paramètre. La syntaxe de cette méthode est la suivante :

MaCollection.Delete "MonItem"

- 10 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3 - Accèder à une base de données

Ce chapitre est entièrement consacré à l'ouverture d'une base de données. Il vous fournira une liste de l'ensemble
des propriétés et des méthodes de chaque objet utilisé ainsi que plusieurs exemples d'utilisation sous Visual Basic.

3.1 - L'objet DBEngine

3.1.1 - Généralités

L'objet DBEngine correspond au moteur de base de données. Il s'agit d'un composant logiciel qui interprète les
requêtes que vous lui transmettez et interroge le fichier de base de données. Dans la plupart des cas, vous n'aurez
jamais à l'instancier ni même à le contrôler puisque l'objet Access.Application possède une propriété DBEngine
renvoyant le moteur de base de données actuellement utilisé. L'objet DBEngine propose dans ses propriétés la liste
des espaces de travail (collection Workspaces) ainsi que d'autres propriétés relatives à la gestion des utilisateurs.
Ces propriétés n'ont que peu d'intérêt dans le cas d'une utilisation normale sans gestion de sécurité. Toutefois, le
moteur de base de données n'est pas à oublier puisque c'est lui qui encapsule les méthodes de transactions ainsi
que les méthodes de réparation et de compactage de la base de données.

3.1.2 - Liste des propriétés

Vous trouverez ci-dessous l'ensemble des propriétés de l'objet DBEngine.

3.1.2.1 - DefaultPassword

Type : String

Il s'agit du mot de passe par défaut qui sera utilisé lors de la création d'un nouvel objet Workspace.

3.1.2.2 - DelfaultType

Type : Long

Cette propriété correspond au type par défaut des futurs objets Workspace. Les valeurs possibles sont dbUseJet
dans le cas d'une utilisation Jet et dbUseODBC dans le cas d'une liaison ODBC direct. Notons que dans ce dernier
cas, l'objet Database est remplacé par un objet de type Connection.

3.1.2.3 - DefaultUser

Type : String

Il s'agit du nom d'utilisateur qui sera utilisé par défaut lors de la création d'un nouvel objet Workspace. Cette propriété
est généralement utilisée en même temps que DefaultPassword.

3.1.2.4 - Errors

Type : Collection

Cette collection regroupe l'ensemble des erreurs levées par le moteur de base de données. Une erreur DAO est
identifiée par un numéro d'erreur et possède une description correspondant au message d'erreur. A chaque fois
qu'une opération DAO échoue,un ou plusieurs objets Error sont créés et ajoutés à la collections Errors. Une fois

- 11 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

que tous ces objets sont créés, une erreur d'exécution est levée par VBA. Cette erreur correspond à l'objet Error
possédant le numéro d'erreur le plus élevé. Sous Access, lors d'une erreur DAO, un seul objet Error est créé pour
réprésenter l'erreur. L'erreur levée par VBA est donc la même que celle du moteur de base de données. Toutefois, si
vous tentez par exemple de vous connecter à une base de données Oracle via votre application, il se peut qu'Oracle
lève plusieurs objets Error reprénsentant la même erreur. Vous trouverez donc dans la collection DBEngine.Errors :

• L'ensemble des erreurs Oracle


• Une erreur Odbc

Mais une seule erreur sera levée par VBA. Le parcours de la collection Errors peut donc vous permettre d'affiner
vos routines de gestion d'erreur.

3.1.2.5 - Inipath

Type : String

La propriété Inipath correspond au chemin du fichier d'initialisation du moteur de base de données. Il s'agit
généralement d'une entrée dans la base des registres :
HKLM\Software\microsoft\Office\10.0\Access\Jet\4.0
C'est ici que figure de nombreuses options internes au moteur Jet, comme par exemple le chemin du fichier de
groupe de travail utilisé.

Bien qu'importante au moteur de base de données, cette propriété représente trés peu
d'intérêt pour le développeur hormis de localiser le chemin où est stocké le fichier de groupe
de travail.

3.1.2.7 - Properties

Type : Collection

Collection regroupant l'ensemble des propriétés (Property) de l'objet DBEngine.

Pour plus d'informations sur la collection Properties, je vous renvoie vers la section 4.2 Les
propriétés spécifiques.

3.1.2.8 - SystemDB

Type : String

Il s'agit du chemin d'accès au fichier mdw (fichier de groupe de travail) à utiliser. Le fichier utilisé par défaut est celui
contenu dans l'entrée du fichier ini ou de la base de registre spécifiée dans la propriété IniPath.

3.1.2.9 - Version

Lecture seule.

Type : String

La propriété Version correspond à la version du moteur Jet. Par exemple : 3.6.

- 12 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.1.2.10 - Workspaces

Type : Collection

Collection regroupant l'ensemble des espaces de travail (Worspaces(0) étant l'espace de travail par défaut).

Pour de plus amples informations, veuillez consulter le chapitre suivant : L'objet Workspace.

3.1.3 - Liste des méthodes

Je vous propose la liste des méthodes applicables aux objets de la classe DBEngine.

3.1.3.1 - BeginTrans

La méthode BeginTrans commence une transaction.

Exemple :

DBEngine.BeginTrans

3.1.3.2 - CommitTrans

La méthode CommitTrans stoppe la transaction tout en enregistrant les données.

Exemple :

DBEngine.CommitTrans

3.1.3.3 - CompactDatabase

La méthode CompactDatabase copie et compacte une base de données. Notons que la base de données doit être
fermée pour réaliser cette opération.

Syntaxe :

DBEngine.CompactDatabase olddb, newdb, [locale], [options], [password]

olddb correspond au fichier source et newdb au fichier de destination (différent de olddb). Les autres options
concernent essentiellement la langue, la version et le codage utilisé. Il s'agit de constantes disponibles dans l'aide
Access.

Exemple :

DBEngine.CompactDatabase "c:\bd1.mdb", "c:\bd2.mdb"

3.1.3.4 - CreateDatabase

La méthode CreateDatabase permet de créer une nouvelle base de données. Elle renvoie un objet de type
DAO.Database.

- 13 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Syntaxe :

Set database = DBEngine.CreateDatabase (name, locale, [options])

L'argument name correspond au nom complet de la base de données.


locale est une constante représentant l'ordre de tri à appliquer (dbLangGeneral pour la France). Le dernier argument
est facultatif et permet de spécifier le codage et la version de la base de données.

Exemple :

Set db = DBEngine.CreateDatabase("c:\mabase.mdb", dbLangGeneral)

3.1.3.5 - CreateWorkspace

Cette méthode permet de créer un nouvel objet WorkSpace (Espace de travail) et retourne l'objet créé.

Syntaxe :

Set workspace = DBEngine.CreateWorkspace(name, user, password, [type])

Name correspond au nom de l'espace de travail. Il permettra de l'identifier de manière unique dans la collection
Workspaces.
User correspond au nom de l'utilisateur dans cet espace et password à son mot de passe (14 caractères au
maximum). Ce couple d'authentification doit obligatoirement figurer dans le fichier mdw spécifié dans la propriété
SystemDB, sans quoi une erreur sera levée par le moteur de base de données.
Le dernier argument est facultatif et correspond au type d'espace à créer. S'il n'est pas mentionné, ce sera le type
figurant dans la propriété DefaultType qui sera utilisé.

Exemple :

Set Wks = DBEngine.CreateWorkspace("MonEspace", "Toto", "mdp#@#!mJ")

3.1.3.6 - Idle

La méthode Idle donne la possibilité au moteur JET de traiter ses tâches en attente. Notons que cette méthode
possède un argument facultatif. Si ce dernier est égal à dbRefreshCache, la mémoire est réactualisée avec
uniquement les données les plus récentes en provenance du fichier de base de données.

Exemple :

DBEngine.Idle

3.1.3.7 - OpenDatabase

Comme son nom l'indique, cette méthode ouvre une base de données. Elle renvoie un objet de type DAO.Database.

Syntaxe :

Set database = workspace.OpenDatabase (dbname, options, read-only, connect)

Dbname correspond au chemin d'accès de la base de données à ouvrir. Cet argument peut aussi être le nom d'une
source ODBC. Si cette chaîne est nulle, et que la variable connect est égale à "ODBC;", une boite de dialogue de
sélection de source de données est affichée.

- 14 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

L'argument option permet de spécifier si la base de données doit être ouverte en mode exclusif (True) ou pas (False).
De plus l'argument read-only ouvre la base de données en lecture seule lorsqu'il est égal à True.

Enfin, l'argument connect est utilisé à la fois pour spécifier le type de base de données et le mot de passe système
à utiliser pour ouvrir le fichier.

L'objet Database créé est ajouté automatiquement à l'espace de travail Workspaces(0).

Exemple :

Set db = DBEngine.OpenDatabase("c:\bd1.mdb", False, False, _


"MS Access;PWD=mdp#@#!e)

3.1.3.8 - RepairDatabase

La méthode RepairDatabase répare la base de données. Notons qu'elle n'est plus utilisée et
est réservée pour assurer la compatibilité avec les anciennes versions.

Il est recommandé d'utiliser la méthode CompactDatabase en remplacement.

3.1.3.9 - Rollback

Cette méthode met fin à une transaction démarrée avec BeginTrans.

Exemple :

DBEngine.RollBack

3.2 - L'objet Workspace

3.2.1 - Généralités

Deux types d'espaces de travail sont à distinguer :

Espace de travail Jet : Zone de travail utilisant le moteur de base de données Microsoft Jet pour accéder à une
source de données. Cette source de données peut prendre la forme d'un fichier de base de données Microsoft Jet
(.mdb), ODBC, Paradox ou ISAM.

Espace de travail ODBC Direct : Il s'agit d'une technique d'accés aux données à une source ODBC sans passer
par le moteur de base de données Jet.

Seul l'espace de travail Jet sera abordé ici.

Un objet Workspace représente un espace de travail au sein du moteur de base de données (DBEngine). Il
s'agit en fait d'une session du DBEngine dédiée à un utilisateur donné. Hormis le cas où vous voulez gérer vous-
même l'ouverture de la base de données dans un environnement sécurisé, l'utilisation de l'objet Workspace sous
Access a peu d'intérêt. En effet, l'objet Workspaces(0) du DBEngine est l'espace de travail par défaut. Il est
instancié automatiquement par Access lors d'un appel à un objet DAO. Ainsi, en général, vous utiliserez une

- 15 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

référence implicite à celui ci, notamment lorsque que vous utiliserez les méthodes CodeDB ou CurrentDB de l'objet
Access.Application.

Toutefois, tout comme l'objet DBEngine, le Workspace est capable d'exécuter des méthodes de transaction, et
permet en plus de paramétrer la gestion des curseurs du moteur Jet (Recordset). Son utilisation peut devenir alors
primordiale lorsque l'on souhaite paramétrer d'avantage l'accès aux données.

Comme il a été précisé dans le chapitre précédent, c'est à partir de l'objet DBEngine qu'est créé chaque objet
Workspace à l'aide de la méthode CreateWorkspace.

La méthode CreateWorkspace demande un identifiant unique pour l'objet créé. De plus, la


création de tels objets est très rare dans le temps. Aussi, il est possible d'utiliser une variable
qui contiendra la date de création de l'objet comme nom de l'objet Workspace à instancier.

Voici un exemple de création d'un objet Workspace :

Dim oWks As DAO.Workspace


Set oWks = DBEngine.CreateWorkspace(Format(Now(), _
"yyyymmddhhnnss"), "Utilisateur1", "mpd#ç#", dbUseJet)

3.2.2 - Liste des propriétés

Vous trouverez ci-dessous la liste des propriétés applicables à un objet de la classe Workspace.

3.2.2.1 - Databases

Type : Collection

Collection regroupant l'ensemble des objets Database ouverts dans l'objet Workspace correspondant.

3.2.2.2 - IsolateODBCTrans

Type : Boolean

Si cette propriété est égale à False (valeur par défaut), il est possible d'effectuer plusieurs transactions simultanées
sur la même connexion ODBC. Toutefois, les bases de données SQL Server n'acceptent pas ce mode de
fonctionnement, aussi dans le cas de connexion ODBC avec ce type de base de base de données, il vous faudra
fixer cette propriété à True.

3.2.2.3 - Name

Lecture seule.

Type : String

La propriété Name correspond au nom de l'objet Workspace concerné. Ce nom est unique au sein de la collection
DBEngine.Workspaces.

3.2.2.4 - Properties

Comme tout autre objet DAO, l'objet Workspace possède cette collection qui regroupe l'ensemble des propriétés
(Property) de cet objet.

- 16 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

De plus amples informations sur la collection Properties sont disponibles dans le chapitre
Les propriétés spécifiques.

3.2.2.5 - Type

Lecture seule.

Type : Long

Il s'agit du type de l'espace de travail. Sa valeur est celle que vous avez spécifié à la méthode CreateWorkspace du
DBEngine. Si vous n'avez pas mentionné cette valeur lors de la création de l'espace de travail, il s'agit de la valeur de
la propriété DefaultType du moteur de base de données. L'objet Workspaces(0) étant instancié automatiquement
par Access lors d'un appel à un objet DAO, la propriété Workspaces(0).Type est donc égale à dbUseJet.
L'autre valeur disponible est dbUseODBC.

3.2.3 - Liste des méthodes

Voici la liste des méthodes proposées par la classe Workspace. Bon nombre de ces méthodes sont communes à
la classe DBEngine.

3.2.3.1 - BeginTrans

La méthode BeginTrans commence une transaction.

Exemple :

DBEngine.Workspaces(0).BeginTrans

3.2.3.2 - Close

La méthode Close ferme l'espace de travail correspondant. Notez que si vous fermez un objet Workspace, ses
transactions en attentes sont détruite. De même si cet objet Workspace possède des objets Database ou Connection,
ces objets sont aussi fermés, ce qui a pour effet de fermer leurs objets recordsets associés.

La fermeture d'un objet Workspace doit donc être une action réfléchie car elle peut entrainer
la perte irrémédiable de données.

Exemple :

DBEngine.Workspaces(0).BeginTrans

3.2.3.3 - CommitTrans

Cette méthode stoppe une transaction démarée avec BeginTrans tout en enregistrant les données.

Exemple :

DBEngine.Workspaces(0).CommitTrans

- 17 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.2.3.4 - CreateDatabase

La méthode CreateDatabase permet de créer une nouvelle base de données. Elle renvoie un objet de type
DAO.Database.

Syntaxe :

Set database = Workspace.CreateDatabase (name, locale, [options])

L'argument name correspond au nom complet de la base de données.


locale est une constante représentant le tri à appliquer (dbLangGeneral pour la France). Le dernier argument est
facultatif et permet de spécifier le codage et la version de la base de données.

Exemple :

Set db = DBEngine.Workspaces(0).CreateDatabase("c:\mabase.mdb", dbLangGeneral)

3.2.3.5 - OpenDatabase

Comme son nom l'indique, la méthode OpenDatabase ouvre une base de données. Elle renvoie un objet de type
DAO.Database.

Syntaxe :

Set database = workspace.OpenDatabase (dbname, options, read-only, connect)

Dbname correspond au chemin d'accès de la base de données à ouvrir. Cet argument peut aussi être le nom d'une
source ODBC. Si cette chaîne est nulle, et que la variable connect vaut "ODBC;", une boite de dialogue de sélection
de source de données est affichée.

L'argument option permet de spécifier si la base de données doit être ouverte en mode exclusif (True) ou pas (False).
De plus l'argument read-only ouvre la base de données en lecture seule lorsqu'il vaut True.

Enfin, l'argument connect est utilisé à la fois pour spécifier le type de base de données et le mot de passe pour
ouvrir le fichier.

L'objet database créé est automatiquement ajouté à la collection Databases de l'objet


Workspace aprés sa création.

Exemple :

Set db = DBEngine.Workspaces(0).OpenDatabase("c:\bd1.mdb", False, False, _


"MS Access;PWD=mdp#@#!e")

3.2.3.6 - Rollback

La méthode Rollback met fin à une transaction démarrée avec BeginTrans.

Exemple :

DBEngine.Workspaces(0).RollBack

- 18 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.2.4 - Accéder à un groupe de travail spécifique

Comme il a été précisé plus haut, l'objet Workspace prend de l'importance lorsqu'il s'agit d'ouvrir une base de
données sécurisée. En effet, lorsque que vous ouvrez un fichier mdb avec Access, vous êtes authentifié au sein d'un
fichier de groupe de travail. Cela peut être le fichier System.mdw par défaut si vous n'avez pas implémenté de gestion
de sécurité ou bien un fichier de votre création rassemblant les informations nécessaires à la protection de votre base
de données. Or, il se peut que vous ayez besoin d'accéder à une autre base de données via DAO nécessitant d'utiliser
un autre fichier mdw pour se connecter. Dans ce cas, il vous faut instancier un autre objet de type DAO.DBEngine
et spécifier le chemin du fichier de groupe de travail à utiliser dans la propriété DBEngine.SystemDB.

Toutefois, cette méthode possède un inconvénient majeur. En effet, si vous essayez d'instancier un nouvel objet
DBEngine alors que vous avez déjà utilisé des méthodes DAO auparavant dans votre code, il vous sera impossible
de modifier la propriété SystemDB du nouvel objet DBEngine créé. Celle-ci conservera pour valeur celle de
Application.DBEngine.SystemDB bien qu'aucune erreur ne soit levée lorsque vous tenterez de la modifier.

Il est donc impératif que l'instanciation de nouveaux objets DBEngine ait lieu avant tout autre
appel DAO y compris les méthodes CodeDb et CurrentDb.

Je vous propose la création d'une interface permettant d'ouvrir une base de données Access en spécifiant le fichier
mdw à utiliser.

Soit le formulaire suivant :

Il est composé de haut en bas :

• Une zone de texte TFichier


• Une liste modifiable ListeSecu
• Une zone de texte TAdmin
• Une zone de texte TUser
• Une zone de texte TMDP

Voici le code correspondant :

Code du bouton Valider :

Private Sub Commande10_Click()


'Ouvre le fichier avec la sécurité choisie
On Error GoTo err
Dim strfichier As String

- 19 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Dim oVDb As DAO.Database


Dim chaine As String
Dim oVWk As DAO.Workspace
Dim oDbe As DBEngine
Dim strFichierMDW As String
If Len(TFichier) <> 0 Then

strfichier = TFichier
'prépare l'espace de travail
If ListeSecu.ListIndex = 0 Or ListeSecu.ListIndex = 2 Then
Set oVWk = Workspaces(0)
Else
strFichierMDW = OuvrirUnFichier(Me.HWnd, _
"Selectionner un fichier de groupe de travail", 1, _
"Fichier mdw", "mdw")
If strFichierMDW = "" Then
Exit Sub
Else
Set oDbe = New DBEngine
oDbe.SystemDB = strFichierMDW
Set oVWk = oDbe.CreateWorkspace(Format(Now(), _
"yyyymmddhhnnss"), TUtilisateur, TMDP, dbUseJet)
End If
End If
'Ouvre la base de données
If ListeSecu.ListIndex = 2 Or ListeSecu.ListIndex = 3 Then
Set oVDb = oVWk.OpenDatabase(strfichier, False, False, _
"MS Access;PWD=" & TAdmin)
Else
Set oVDb = oVWk.OpenDatabase(strfichier)
End If
Else
MsgBox "Vous devez sélectionner un fichier", _
vbExclamation, "Saisie du fichier"
End If
Exit Sub
err:
MsgBox "Impossible de se connecter à la base de données. " & _
"Vérifier le chemin d'accès et les informations " & _
"d'authentification", vbCritical, "Erreur"
End Sub

Code d'ouverture du formulaire :

Private Sub Form_Load()


'Vide les controles
Dim ctlT As Control
For Each ctlT In Me.Controls
If TypeOf ctlT Is TextBox Then
ctlT.Value = ""
If ctlT.Name <> "TFichier" Then ctlT.Enabled = False
End If
Next ctlT
ListeSecu = "Aucune"
End Sub

Code du bouton parcourir

Private Sub Commande3_Click()


Dim strChemin As String
strChemin = OuvrirUnFichier(Me.Hwnd, _
"Selectionner une base de données Access", _
1, "Fichiers Access", "mdb")
If strChemin <> "" Then
Me.TFichier = strChemin
End If
End Sub

- 20 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La fonction OuvrirUnFichier est disponible dans la FAQ Access. Elle permet d'afficher une boîte de dialogue de
sélection de fichier.

La base de données ainsi ouverte est disponible via l'objet : VDB de la procédure du bouton Valider.

Cette interface permet à la fois de s'authentifier au sein d'un fichier de groupe de travail et de saisir le mot de passe
système pour l'ouverture de l'objet Database.

Le choix du fichier de groupe de travail se réalise ici :

Set oDbe = New DBEngine


oDbe.SystemDB = strFichierMDW
Set VWK = oDbe.CreateWorkspace(Format(Now(), _
"yyyymmddhhnnss"), TUtilisateur, TMDP, dbUseJet)

La première ligne permet d'instancier le nouveau moteur de base de données auquel nous spécifions ensuite le
fichier mdw à ouvrir. Puis nous créons enfin le l'espace de travail à l'aide de la méthode CreateWorkspace.

Une des raisons majeures pour lesquelles la création de l'espace de travail lève une erreur est que le couple utilisateur
- mot de passe est invalide dans le fichier mdw sélectionné. Il se peut aussi que l'affectation de la propriété SystemDB
ait échouée, ce qui signifie que le code de votre projet utilise des méthodes DAO avant ce bloc d'instructions. Un
moyen simple de le vérifier :

MsgBox oDbe.SystemDB
oDbe.SystemDB = FichierMDW
MsgBox oDbe.SystemDB

Si les deux MsgBox affichent le même résultat, cela indique que votre code utilise des instructions DAO avant cette
procédure.

3.3 - L'objet Database

3.3.1 - Généralités

Comme vous avez pu le remarquer dans la fenêtre de base de données de l'application Access, un fichier mdb peut
être décomposé en deux parties :

- La partie applicative. Elle regroupe à la fois les formulaires, les états, les modules et les macros.

- La partie données. Cette partie se retrouve dans l'ensemble des SGBD (Système de Gestion de Base de Données). Il
s'agit des tables et des requêtes. Access étant un SGBDR (SGBD Relationnel), cette partie regroupe aussi l'ensemble
des relations entre les différentes tables.

Le modèle objet DAO donne accès à la partie données via son objet Database. Cet objet est à la racine du DDL
(Langage de définition de données) et du DML (Langage de manipulation de données) sous DAO. C'est à partir de
ce même objet Database que l'on va créer les tables, les requêtes, les relations et manipuler les données (Insert,
Update, Delete).

Comme il a été écrit plus haut, un objet database peut être instancié depuis un moteur de base de données
(DBEngine) ou depuis un espace de travail (Workspace) à l'aide des méthodes CreateDatabase et OpenDatabase.
Ceci peut être fait de manière explicite :

Dim oDb As DAO.Database


Set oDb=DBEngine.CreateDatabase (…)

- 21 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Ou de manière implicite :

Dim oDb As DAO.Database


Set oDb=CreateDatabase(…)

Toutefois, dans la majorité des cas, vous souhaitez utiliser la base de données courante ouverte dans Access. Il vous
suffit alors d'utiliser les méthodes Application.CurrentDb ou Application.CodeDb.

3.3.1.1 - La méthode CurrentDb

Cette méthode fournie par l'objet Access.Application retourne une variable de type Database correspondant à la
base de données actuellement ouverte dans le logiciel Microsoft Access. La méthode Currentdb crée une nouvelle
instance de la base de données à chaque appel. Aussi, vous devez récupérer son résultat dans une variable objet
de type Database pour pouvoir l'exploiter.

Voici ce qu'il ne faut pas utiliser :

Dim Tbl As DAO.TableDef, Tbl2 As DAO.TableDef


Set Tbl = CurrentDb.TableDefs("Table1")
Set Tbl2 = CurrentDb.TableDefs("Table2")

En effet, ce code fait un double appel à Currentdb ce qui provoque une double instanciation de la base de données
courante.

Dim Tbl As DAO.TableDef, Tbl2 As DAO.TableDef


Dim Db as DAO.Database
Set Db=CurrentDb
Set Tbl = Db.TableDefs("Table1")
Set Tbl2 = Db.TableDefs("Table2")

Ici, une seule instance de l'objet database est utilisée.

La propriété DBEngine.Workspaces(0).Databases(0) représente aussi la base de données ouverte. Toutefois, cette


méthode est déconseillée car elle ne crée pas une nouvelle instance de l'objet Database. Au contraire, son résultat
peut être considéré comme un pointeur vers la base de données. Aussi, dans un environnement multi-utilisateurs,
ceci peut engendrer des conflits d'accès aux données. Privilégiez donc la méthode CurrentDb.

3.3.1.2 - La méthode CodeDb

Contrairement à la méthode CurrentDb qui renvoie la base de données active, cette méthode retourne un objet
Database correspondant à la base de données qui contient le code en cours d'exécution .
CodeDb est à utiliser lors de la création de compléments ou de base de données bibliothèques. En effet la base Add-
in ne sera pas la base active. La méthode CurrentDb ne retournera donc pas le bon objet Database. Tout comme
CurrentDb, Codedb retourne une nouvelle instance de l'objet Database. Vous devez donc récupérer son résultat
dans un objet Database pour pouvoir l'exploiter.

Dim Tbl As DAO.TableDef, Tbl2 As DAO.TableDef


Dim Db as DAO.Database
Set Db=CodeDb
Set Tbl = Db.TableDefs("Table1")
Set Tbl2 = Db.TableDefs("Table2")

- 22 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.3.2 - Liste des propriétés

3.3.2.1 - CollatingOrder

Type : Long

Il s'agit de la méthode utilisée par le moteur pour comparer les données de type texte.

Les valeurs possibles sont :

Constante Signification
dbSortGeneral Général (Français, anglais ...)
dbSortArabic Arabe
dbSortChineseSimplified Chinois simplifié
dbSortChineseTraditional Chinois traditionnel
dbSortCyrillic Russe
dbSortCzech Tchèque
dbSortDutch Néerlandais
dbSortGreek Grec
dbSortHebrew Hébreu
dbSortHungarian Hongrois
dbSortIcelandic Islandais
dbSortJapanese Japonais
dbSortKorean Coréen
dbSortNeutral Neutre
dbSortNorwDan Norvégien et danois
dbSortPDXIntl Paradox International
dbSortPDXNor Paradox norvégien ou danois
dbSortPDXSwe Paradox suédois ou finnois
dbSortPolish Polonais
dbSortSlovenian Slovène
dbSortSpanish Espagnol
dbSortSwedFin Suédois ou finnois
dbSortThai Thaï
dbSortTurkish Turc
dbSortUndefined Indéfini

3.3.2.2 - Connect

Lecture Seule.

Type : String

La propriété Connect représente la chaîne de connexion utilisée à l'ouverture de l'objet Database. Lorsque que vous
utilisez cette propriété sur une base au format Access, cette propriété est égale à "".

3.3.2.3 - Containers

Type : Collection

- 23 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Cette collection regroupe l'ensemble des objets de type container contenu dans la base de données. Il s'agit de
l'ensemble des objets enregistrés dans la base de données. Vous y touverez par exemple des informations sur les
formulaires, les états ...

Cette propriété vous est founie à titre d'information, en effet, un tutoriel entier pourrait lui être
consacré.

3.3.2.4 - Name

Lecture Seule.

Type : String

La propriété Name d'un objet Database retourne le nom de la base de données. Pour une base de données Access,
il s'agit du nom du fichier mdb ainsi que le chemin d'accès complet vers ce fichier.

3.3.2.5 - Properties

Type : Collection

Collection regroupant l'ensemble des objets Property de l'objet Database.

3.3.2.6 - QueryDefs

Type : Collection

Cette collection regroupe l'ensemble des requêtes enregistrées dans la base de données.

Cette partie sera largement détaillée dans la section 4.7 L'objet QueryDef.

3.3.2.7 - RecordsAffected

Lecture Seule.

Type : Long

La propriété RecordsAffected retourne le nombre d'enregistrements qui ont été affectés par le dernier ordre SQL
de la méthode Execute. Cela permet de connaitre, par exemple, le nombre de lignes supprimées lors d'une requête
Delete.

Exemple d'utilisation :

Dim Requete As String


Dim DB As DAO.Database
Requete = "DELETE FROM MaTable WHERE ChampID>20"
Set DB = CurrentDb
DB.Execute Requete
MsgBox DB.RecordsAffected

- 24 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.3.2.8 - Recordsets

Lecture Seule.

Type : Collection

Cette collection regroupe l'ensemble des objets recordset ouverts dans la base de données.

Cette partie sera largement détaillée dans le chapitre 5 Accès aux données.

3.3.2.9 - Relations

Type : Collection

La propriété Relations est une collection regroupant l'ensemble des relations présentes dans la base de données.
Cette collection n'est utile que pour les SGBDR.

Cette partie sera largement détaillée dans la section 4.6 L'objet Relation.

3.3.2.10 - TableDefs

Type : Collection

Cette collection regroupe l'ensemble des tables enregistrées dans la base de données. Dans le cas d'une base de
données incluant des tables liées, il existe aussi un objet TableDef pour chaque table attachée.

Cette partie sera largement détaillée dans la section : 4.3 L'objet TableDef.

3.3.2.11 - Transactions

Lecture Seule.

Type : Boolean

La propriété Transactions d'un objet Database indique si l'objet database supporte les transactions. Si oui, la valeur
de la propriété est égale à True.
Dans le cas d'une base de données Access, cette valeur est fixée à True et les transactions sont disponibles via
les objets Recordset Dynaset et Table.

3.3.2.12 - Updatable

Lecture Seule.

Type : Boolean

Si cette propriété est égale à False, la base de données est protégée en écriture et vous ne pouvez modifier ni les
données, ni la structure.

- 25 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

3.3.2.13 - Version

Lecture Seule.

Type : String

Cette propriété retourne la version du moteur Jet utilisé pour créer la base de données. Dans le cas, d'une base de
données Access au format 2000 ou ultérieur, cette propriété est égale à 4.0.

3.3.3 - Liste des méthodes

3.3.3.1 - Close

La méthode Close ferme la base de données. Toutefois, cela ne libère pas la mémoire alloué à l'objet database. Pour
libérer la mémoire, vous devez affecter Nothing à la variable.

3.3.3.2 - CreateProperty

La méthode CreateProperty crée et retourne un objet Property.

Syntaxe :

Set property = object.CreateProperty (name, type, value, DDL)

Nous reviendrons plus en détails sur les objets property dans le chapitre suivant.

3.3.3.3 - CreateQueryDef

La méthode CreateQueryDef crée une nouvelle requête et retourne l'objet QueryDef correspondant. L'objet créé est
automatiquement ajouté à la collection Database.QueryDefs.

Syntaxe :

Set querydef = Database.CreateQueryDef (name, sqltext)

L'argument name correspond au nom de la requête à créer. Celui ci doit être unique au sein de la collection
QueryDefs. En affectant une chaine vide ("") à ce paramètre, vous créez un objet QueryDef temporaire qui ne sera
pas ajouté à la collection QueryDefs. Dans ce cas, l'objet sera détruit à la fin de la procédure.

L'argument SQL est une chaîne de caractères contenant l'instruction SQL de la requête à créer. Il peut s'agir de
requête de sélection, de mise à jour, de supression, etc ...

Le fonctionnement de l'objet QueryDef est illustré dans le chapitre intitulé : L'objet QueryDef

3.3.3.4 - CreateRelation

La méthode CreateRelation crée et retourne un objet Relation.

Syntaxe :

- 26 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Set relation = database.CreateRelation (name, table, foreigntable, attributes)

Nous reviendrons plus en détails sur les objets Relation dans le chapitre suivant.

3.3.3.5 - CreateTableDef

La méthode CreateTableDef crée et retourne un objet Tabledef. A ce stade, l'objet est seulement créé et n'est pas
encore intégré à la base de données. Pour l'ajouter aux autres tables, vous devrez invoquer la méthode Append
de la collection TableDefs.

Syntaxe :

Set tabledef = database.CreateTableDef (name, attributes, source, connect)

La création de table sera abordée en détails dans le chapitre suivant à la section 4.3 L'objet
TableDef

3.3.3.6 - Execute

Cette méthode execute un ordre SQL. Cette ordre SQL doit être une requête action (Insert, Update, Delete). Les
requêtes de sélection sont déléguées aux objets Recordset. Une fois l'ordre SQL exécuté, il est possible de connaitre
le nombre d'enregistrements qui ont été affectés par cet ordre grâce à la propriété RecordsAffected.

Exemple :

Dim Db as DAO.Database
Set Db=CurrentDb
Db.Execute ("DELETE FROM MaTable")

3.3.3.7 - NewPassword

La méthode NewPassword permet de modifier le mot de passe système de la base de données.

Ne pas confondre le mot de passe système et le mot de passe utilisateur utilisé dans un
groupe de travail. Le mot de passe système est celui définit dans le menu Outils/Sécurité/
Définir le mot de passe de la base de données.

Exemple :

Dim Db as DAO.Database
Set Db=CurrentDb
Db.NewPassword "mdpancien","mdpnouveau"

3.3.3.8 - OpenRecordset

La méthode OpenRecordset ouvre et retourne un objet Recordset (Curseur) permettant d'accéder aux données.
L'objet ainsi créé est automatiquement ajouté à la collection Recordsets.

Vous retrouverez cette méthode dans le chapitre 5 Accès aux données.

- 27 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4 - DAO et la structure d'une base de données

4.1 - Généralités

Nous abordons là un point fort de DAO à savoir la définition des données (DDL). En effet, l'objet Database donne
accès à l'ensemble des tables, des requêtes et des relations d'une base de données Access. Non seulement il est
possible de consulter les différents objets mais il est aussi possible de les modifier, d'en ajouter et d'en supprimer. Vous
pouvez donc, via votre code VBA, travailler sur la structure de votre fichier comme vous le feriez en mode création
dans l'application Access. L'intérêt est bien entendu de pouvoir modifier cette structure sans aucune intervention de
l'utilisateur. (Laisser l'utilisateur agir sur les tables directement constitue un réel danger pour votre application). Pour
cela, les autres SGBD utilisent généralement le langage SQL (avec des instructions Create, Alter, Drop …). Access ne
dispose pas de tant de possibilités avec son langage SQL. Le recours à la programmation VBA devient donc impératif
pour réaliser certaines opérations. Nous allons donc voir plus loin dans ce chapitre comment travailler sur les tables,
les requêtes et les relations. Mais, dans un premier temps, nous allons aborder le thème des propriétés spécifiques.

4.2 - Les propriétés spécifiques

4.2.1 - Définitions

DAO est un modèle objet. Aussi chaque objet qui le compose possède une liste de propriétés dont chacune d'elles
correspond à un objet Property. Vous vous demandez alors quel est l'intérêt de la collection Properties puisque ces
propriétés sont disponibles sous VBA avec la syntaxe : Objet.Propriété. Certes Visual Basic liste certaines propriétés
mais il ne les propose pas toutes. Ainsi par exemple, les objets TableDef possèdent une propriété Description qui
correspond à la description de la table. Cette propriété n'est pas listée dans le récapitulatif des propriétés des objets
TableDef, le seul moyen de l'atteindre est d'utiliser la collection TableDef.Properties.

Pourquoi certaines propriétés ne figurent que dans la collection properties ?

Tout d'abord, bon nombre de propriétés de la collection Properties ne sont pas créées jusqu'à ce qu'une valeur ne
leur soit affectée. Ainsi, la propriété description de l'objet TableDef n'existe pas si vous n'avez pas encore saisi la
description de la table sous Access.

- 28 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

De plus vous pouvez créer vos propres propriétés et les ajouter à la collection Properties de l'objet de votre choix.
Il devient donc impossible de réaliser une liste exhaustive de l'ensemble des propriétés d'un objet DAO.

4.2.2 - Liste des propriétés d'un objet Property

Chaque objet Property possède lui aussi un ensemble de propriétés.

4.2.2.1 - Inherited

Lecture seule.

Lorsque cette propriété est égale à True, cela signifie que la propriété ne fait pas partie de l'objet même mais qu'elle
est héritée d'un autre objet.
Imaginons un objet QueryDef Q1 auquel nous ajoutons une propriété personalisée P1. P1 a été créée pour Q1 donc,
la propriété P1.Inherited est égale à False. Si par la suite nous ouvrons un recordset R1 sur Q1, la propriété P1 se
retrouvera dans la collection Properties de R1. P1 sera alors héritée et P1.Inherited sera égale à True.

Dans ce cas, ces deux expressions seront vérifiées :

Q1.Properties("P1").Inherited=False

Et :

R1.Properties("P1").Inherited=True

- 29 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.2.2.2 - Name

Cette propriété correspond au nom de la propriété. Celui-ci doit être unique au sein de la collection Properties
de l'objet concerné, sans quoi une erreur sera levée lorsque vous tenterez d'ajouter le nouvel objet Property à la
collection Properties.

Utilisez des noms précis et en relation avec ce que la propriété modélise. De même éviter
d'utiliser des mots réservés par Visual Basic. Ainsi, si la propriété représente une date de
vérification, nommez la DateVerification et non pas simplement Date.

4.2.2.3 - Type

Il s'agit du type de la propriété. Sa valeur doit être une des constantes suivantes :

Constante Valeur Type


dbBigInt 16 Numérique (haute
précision)
dbBinary 9 Binaire de longueur fixe
(255 octets maxi)
dbBoolean 1 Booléen
dbByte 2 Octet
dbChar 18 Chaîne de caractère de
longueur fixe
dbCurrency 5 Monétaire
dbDate 8 Date/Heure
dbDecimal 20 Décimal
dbDouble 7 Double
dbFloat 21 Réel à virgule flottante
dbGUID 15 Identifiant GUID
dbInteger 3 Entier
dbLong 4 Entier long
dbLongBinary 11 Binaire à longueur
variable. (OLE)
dbMemo 12 Mémo
dbNumeric 19 Numérique
dbSingle 6 Réel Simple
dbText 10 Texte à longueur fixe
dbTime 22 Heure
dbTimeStamp 23 TimeStamp
dbVarBinary 17 Binaire à longueur
variable (255 octets maxi)

4.2.2.4 - Value

Cette propriété correspond à la valeur de l'objet Property. Cette valeur doit être compatible avec le type spécifié
dans la propriété Type.

4.2.3 - Accéder à une propriété

La collection Properties fonctionne comme toute autre collection DAO. Toutefois, ne connaissant pas le contenu de
la collection, il paraît difficile d'accéder à un élément via son index dans la collection. Il nous faut donc spécifier le
nom de l'élément à rechercher. Il se pose alors un autre problème qui est que nous ne savons pas si l'objet Property

- 30 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

à rechercher existe. En effet, comme nous l'avons vu, par exemple plus haut avec la propriété description des objets
Tabledef, celle-ci n'existe que si elle a été initialisée auparavant. Dés lors, nous devons vérifier l'existence de la
propriété avant d'y accéder.

Deux méthodes peuvent alors être utilisées. La première consiste à parcourir chacun des objets Property de la
collection est de retourner un booléen si l'élément a été trouvé.

Public Function ExistProperty(ColTProperties As DAO.Properties, _


strTNom As String) As Boolean
Dim oTmpPrp As DAO.Property
For Each oTmpPrp In ColTProperties
If oTmpPrp.Name = strTNom Then
ExistProperty = True
Exit For
End If
Next oTmpPrp
End Function

Exemple d'utilisation :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
MsgBox ExistProperty(oTbl.Properties, "description")

La seconde méthode consiste à tenter d'accéder à la propriété via son nom et de traiter l'erreur si celle-ci n'existe pas.

Public Function ExistProperty(ColTProperties As DAO.Properties, _


strTNom As String) As Boolean
On Error GoTo err
Dim oTmpPrp As DAO.Property
Set oTmpPrp = ColTProperties(strTNom)
ExistProperty = True
err:
End Function

L'utilisation de la fonction reste la même que celle de la précédente. Toutefois, la seconde méthode est plus rapide
du fait qu'elle n'utilise pas de boucle.

Dans le cas où vous n'utiliseriez pas une de ses fonctions et que la propriété n'est pas trouvée dans la collection
Properties, l'erreur d'exécution 3270 (Propriété non trouvée) sera levée.

Une fois la propriété trouvée, il est possible de connaître sa valeur à l'aide de la propriété value.

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
If ExistProperty(oTbl.Properties, "description") Then
MsgBox oTbl.Properties("description").Value
Else
MsgBox "Cette propriété n'existe pas"
End If
oDb.Close
Set oDb=Nothing
Set oTbl=Nothing

4.2.4 - Modifier la valeur d'une propriété

Pour modifier la valeur d'un objet Property, il faut tout d'abord que celui ci existe. Nous pouvons donc réutiliser
une des fonctions citées plus haut. Ensuite, il suffit de modifier la valeur de l'objet Property en utilisant la propriété

- 31 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Value. Cependant, certaines propriétés sont en lecture seule. Aussi, l'implémentation d'une gestion d'erreur devient
impérative.

Voici un exemple de fonction utilisable pour modifier une propriété spécifique d'un objet DAO :

Public Function ModifProperty(colTProperties As DAO.Properties, _


strTNom As String, strTValeur As Variant) As Boolean
On Error GoTo err
Dim oTmpPrp As DAO.Property
'Recherche l'élément
Set oTmpPrp = colTProperties(strTNom)
'Modifie la valeur
oTmpPrp.Value = strTValeur
'Rafraichit la collection
colTProperties.Refresh
'L'opération est terminée, renvoyer True
ModifProperty = True
Exit Function
'Gestion des erreurs
err:
Select Case err.Number
Case 3270
MsgBox "Propriété non trouvée"
Case 3421
MsgBox "Type de propriété incompatible"
Case Else
MsgBox "La propriété est en lecture seule"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
ModifProperty oTbl.Properties, "description", "essai"

Quelques remarques sur cette fonction :

TValeur correspond à la nouvelle valeur de la propriété. Le type de cet argument est Variant, pour s'adapter à
l'ensemble des types possibles. Toutefois, si vous ne souhaitez modifier des propriétés exclusivement de type String,
vous pouvez remplacer le type Variant par String.

La méthode Refresh appliquée à la collection Properties permet de mettre à jour immédiatement la propriété. Si
cette méthode n'est pas employée, les modifications ne seront effectives qu'après avoir redémarré votre application.

La fonction renvoie false en cas d'échec de la modification de la propriété.

Il est inutile d'utiliser cette fonction pour les propriétés non spécifiques. En effet, les propriétés
proposées par l'explorateur d'objets (F2) sont des propriétés intégrées que vous pouvez
modifier avec la syntaxe habituelle Objet.Propriété.

Exemple :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
oTbl.name= "essai"

- 32 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.2.5 - Création d'une nouvelle propriété

Pour créer une nouvelle propriété, vous devez d'abord vérifier que celle-ci n'existe pas. Ensuite, il suffit d'appliquer la
méthode CreateProperty de l'objet concerné pour instancier un nouvel objet Property. A ce stade, la propriété est
seulement créée, elle n'est pas encore ajoutée à la liste des propriétés de l'objet. Pour l'ajouter, vous devez utilisez
la méthode Append de la collection Properties.

Voici un exemple qui ajoute une propriété nommée "test" de type Integer à la table commande.

Sub ajout()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Dim oPrp As DAO.Property
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
'verifie que la propriété n'existe pas
If Not ExistProperty(oTbl.Properties, "test") Then
'Crée la nouvelle propriété
Set oPrp = oTbl.CreateProperty("test", dbInteger, 0)
'ajoute la propriété
oTbl.Properties.Append oPrp
'Rafraichit la liste des propriétés
oTbl.Properties.Refresh
End If
'Libération des objets
oDb.Close
Set oTbl=Nothing
Set oDb=Nothing
MsgBox "Propriété ajoutée"
End Sub

La méthode CreateProperty renvoyant un objet de type Property, ce code peut être simplifié par :

Sub ajout()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = Db.TableDefs("Commande")
'Vérifie que la propriété n'existe pas
If Not ExistProperty(oTbl.Properties, "Test") Then
'Crée et ajoute la nouvelle propriété
oTbl.Properties.Append oTbl.CreateProperty("test", dbInteger, 0)
'Rafraîchit la liste des propriétés
oTbl.Properties.Refresh
End If
'Libération des objets
oDb.Close
Set oTbl=Nothing
Set oDb=Nothing
MsgBox "Propriété ajoutée"
End Sub

De même, plutôt que de tester l'existence de la propriété, il est possible de tenter de l'ajouter et de gérer l'erreur si
une autre propriété portant le même nom existe déjà.

Sub ajout()
On Error GoTo err
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Commande")
'Crée et ajoute la nouvelle propriété
oTbl.Properties.Append oTbl.CreateProperty("test", dbText, 0)
'Rafraîchit la liste des propriétés
oTbl.Properties.Refresh
MsgBox "Propriété ajoutée"

- 33 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Exit Sub
'Gère les erreurs
err:
Select Case err.Number
Case 3367: MsgBox "La propriété existe déjà"
Case Else: MsgBox "Une erreur inconnue est survenue"
End Select
End Sub

4.3 - L'objet TableDef

4.3.1 - Définitions

La collection TableDefs de l'objet Database regroupe l'ensemble des tables de la base de données. Cette collection
inclue aussi les tables systèmes et les tables liées. Chaque objet TableDef qui la compose possède une collection
d'objets Field (Champ) et une autre d'objets Index. Ces deux autres types d'objet seront étudiés plus loin dans ce
chapitre.

Tout comme c'est le cas en mode création dans l'application Access, il est impossible de
modifier la structure d'une table liée en utilisant DAO.

4.3.2 - Liste des propriétés

Ci-dessous figure la liste des propriétés appliquables aux objets TableDef.

Certaines de ces propriétés ne sont disponibles en écriture uniquement pour les objets qui
n'ont pas encore été ajoutés à la collections Database.TableDefs.

4.3.2.1 - Attributes

Type : Long

La propriété Attributes caractérise la table correspondante. Il s'agit d'une (ou une combinaison) des constantes
suivantes :

Constante Signification
dbAttachExclusive Utilisable uniquement sur une table liée.
Cette valeur indique que la table liée est
ouverte en mode exclusif.
dbAttachSavePWD Utilisable uniquement sur une table liée.
Avec cette constante, les informations
de Login utilisées pour lier la table sont
sauvegardées.
dbSystemObject Indique une table système.
dbHiddenObject Indique une table cachée.
dbAttachedTable Indique une table liée via le moteur Jet.
dbAttachedODBC Indique une table liée via ODBC.

4.3.2.2 - Connect

Type : String

- 34 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Il s'agit de la chaîne de connexion utilisée pour une table liée. Sa valeur est nulle pour une table non liée. Cette chaine
de connexion prend en compte plusieurs paramètres comme par exemple le nom de l'utilisateur, son mot de passe,
etc ... Vous pouvez la consulter visualisant les propriétés de votre table en mode création.

Cette propriété est en lecture seule pour les objets TableDef présents dans la collection
Database.TableDefs

4.3.2.3 - DataCreated

Lecture seule.

Type : Date

La propriété DataCreated renvoie la date de création de la table.

4.3.2.4 - Fields

Type : Collection

Cette collection regroupe l'ensemble des champs de la table. Vous pouvez les modifier, en ajouter et en supprimer.

4.3.2.5 - Indexes

Type : Collection

Collection regroupant l'ensemble des index de la table. Vous pouvez les modifier, en ajouter et en supprimer.

4.3.2.6 - LastUpdated

Lecture seule.

Type : Date

La propriété LastUpdated retourne la date et l'heure de la dernière modification apportée à la structure de la table
concernée.

4.3.2.7 - Name

Type : String

La prorpiété Name correspond au nom de la table. Ce nom doit être unique au sein de la collection TableDefs de
l'objet Database.

Vous trouverez plus loin dans ce chapitre (section 4.3.4.2) un exemple montrant comment renommer une table dans
une base de données.

4.3.2.8 - Properties

Type : Collection

- 35 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La prorpiété Properties est une collection qui regroupe l'ensemble des objets Property de l'objet TableDef.

4.3.2.9 - RecordCount

Lecture seule.

Type : Long

La propriété RecordCount renvoie le nombre d'enregistrements de la table.

4.3.2.10 - SourceTableName

Type : String

Il s'agit du nom d'origine de la table liée. Si l'objet TableDef n'est pas une table liée, cette propriété est en lecture
seule et sa valeur est égale à "".

4.3.2.11 - Updatable

Lecture seule.

Type : Boolean

La propriété de Updatable définit si les données provenant de la table peuvent être modifiées.

4.3.2.12 - ValidationRule

Type : String

La propriété ValidationRule définit la règle de validation qui sera utilisée pour valider les données lors d'une mise
à jour (Insert compris).

Ainsi, pour obliger l'utilisateur a remplir le champ MonChamp lorsque que le champ Booleen MaCase est coché,
nous aurions la règle suivante :

([MonChamp] IS NOT NULL AND [MaCase]) OR NOT ([MaCase])

4.3.2.13 - ValidationText

Type : String

La propriété ValidationText correspond au message qui sera affiché lors d'une mise à jour si les données ne vérifient
pas la règle spécifiée dans ValidationRule.

4.3.3 - Liste des méthodes

4.3.3.1 - CreateField

La méthode CreateField crée et retourne un nouvel objet Field qui sera à ajouter par la suite à la collection
Database.Tabledefs.

- 36 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Syntaxe :

Set field = TableDef.CreateField (name, type, size)

Cette méthode sera traitée plus en détail dans la sous partie dédiée aux objets Field.

4.3.3.2 - CreateIndex

La méthode CreateIndex crée un nouvel Index dans la table. Cet Index devra ensuite être ajouté à la collection
Indexes de l'objet TableDef pour prendre effet.

Syntaxe :

Set index = tabledef.CreateIndex (name)

4.3.3.3 - CreateProperty

La méthode CreateProperty crée et retourne un nouvel objet Property qu'il vous faudra ensuite ajouter à la collection
Properties de l'objet TableDef.

La syntaxe de la méthode est celle illustrée dans la partie : Les propriétés spécifiques.

4.3.3.4 - OpenRecordset

La méthode OpenRecordset ouvre un recordset contenant l'ensemble des enregistrements de la table.

Syntaxe :

Set recordset = object.OpenRecordset (type, options, lockedits)

4.3.3.5 - RefreshLink

La méthode RefreshLink n'est utilisable que sur des tables liées. Elle permet, aprés avoir modifié la propriété
Connect, de rafraîchir les informations de connexion entre la table attachée et la source de données.

Syntaxe :

tabledef.RefreshLink

4.3.4 - Opérations sur les tables d'une base de données

4.3.4.1 - Lister les tables d'une base de données

Je vous propose quelques codes utiles pour lister l'ensemble des tables d'une base de données. Nous ferons la
distinction entre les tables systèmes et les tables liées. En effet, la propriété Attributes est un masque binaire.
L'opérateur AND entre une constante recherchée et la valeur de la propriété effectue une opération binaire renvoyant
un nombre égal à 0 si la constante n'est pas utilisée dans la propriété. Ainsi, pour savoir si une table est une table
système, il est possible d'utiliser :

If monObjet.Attributes AND dbSystemObjet then .....

- 37 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Pour lister, l'ensemble des tables systèmes, il suffit donc de parcourir un à un les éléments de la collection TableDefs
et de de vérifier si l'expression booléene est vraie ou non.

Sub Lister()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
'Pour chaque table
For Each oTbl In oDb.TableDefs
'Si la table est système alors afficher son nom
If oTbl.Attributes And dbSystemObject Then MsgBox oTbl.Name
Next oTbl
End Sub

Si nous souhaitons lister les tables liées, nous aurons :

Sub Lister()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
'Pour chaque table
For Each oTbl In oDb.TableDefs
'Si la table est liée alors afficher son nom
If oTbl.Attributes And dbAttachedTable Then MsgBox oTbl.Name
Next oTbl
End Sub

Pour réunir les deux listes, il suffit d'utiliser l'opérateur logique OR (Ou). Ainsi, le code suivant affichera les tables
systèmes ainsi que les tables liées.

Sub Lister()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
'Pour chaque table
For Each oTbl In oDb.TableDefs
'Si la table est liée ou système alors afficher son nom
If oTbl.Attributes And (dbAttachedTable Or dbSystemObject) Then MsgBox oTbl.Name
Next oTbl
End Sub

Ce code n'est pas à confondre avec :

Sub Lister()
Dim oDb As DAO.Database
Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
'Pour chaque table
For Each oTbl In oDb.TableDefs
'Si la table est liée et système alors afficher son nom
If oTbl.Attributes And (dbAttachedTable And dbSystemObject) Then MsgBox oTbl.Name
Next oTbl
End Sub

En effet ce dernier liste les tables qui sont à la fois systèmes et liées.

4.3.4.2 - Renommer une table

Renommer une table est une opération extrémement simple. Toutefois, il ne faut pas oublier que le nom de la table
doit être unique. Aussi, il faudra implémenter une gestion d'erreur lors d'une telle opération.

- 38 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Les objets Relations dépendants de la table renommées sont automatiquement mis à jour
par le moteur Jet.

Private Function RenommerTable(oBaseDeDonnees As DAO.Database, strAncienNom As String, _


strNouveauNom As String) As Boolean
On Error GoTo err
Dim oTbl As DAO.TableDef
'Cherche la table à modifier
Set oTbl = oBaseDeDonnees.TableDefs(strAncienNom)
'Renomme la table
oTbl.Name = strNouveauNom
'Rafraîchit la collection
oBaseDeDonnees.TableDefs.Refresh
'Renvoie true
RenommerTable = True
Exit Function
err:
Select Case err.Number
Case 3265: MsgBox "Impossible de trouver la table à renommer"
Case 3010: MsgBox "La table " & strNouveauNom & " existe déjà"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
If RenommerTable(oDb, "Commande", "Commande_Archive") Then
MsgBox "Table renommée avec succès"
End if

4.3.4.3 - Supprimer une table

La suppression d'une table nécessite quelques précautions. Hormis le fait que la table doit exister pour être supprimer,
il ne faut pas perdre de vue que la suppression d'une table engendre la suppression des relations qui en dépendent.
Aussi dans le cas d'une mauvaise manipulation, vous risquez de supprimer des objets Relations sans vous en rendre
compte. Dans ce cas, je préconise d'envoyer un message à l'utilisateur lui demandant confirmation. Il nous faut donc
savoir si la table fait partie d'un objet relation ou non. Pour cela, nous utiliserons la fonction ExistRelation suivante :

Private Function ExistRelation(oBaseDeDonnees As DAO.Database, _


strNomTable As String) As Integer
Dim oRlt As DAO.Relation
'Pour chaque objet relation
For Each oRlt In oBaseDeDonnees.Relations
'Si la table est présente dans la relation
If oRlt.Table = strNomTable Or oRlt.ForeignTable = strNomTable Then _
ExistRelation = ExistRelation + 1
Next oRlt
End Function

Cette fonction renvoie le nombre de relations dépendantes de la table passée en paramètre.

Nous pouvons donc écrire la fonction de suppression de table suivante :

Private Function SupprimerTable(oBaseDeDonnee As DAO.Database, _


strNomTable As String)
On Error GoTo err
Dim intNbRlt As Integer
'Compte le nombre de relations dépendantes
intNbRlt = ExistRelation(oBaseDeDonnee, strNomTable)
'Si la table est présente dans au moins une relation

- 39 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

If NbRlt <> 0 Then


'si l'utilisateur ne souhaite pas continuer, sortir de la fonction
If MsgBox("La table " & strNomTable & " est utilisée dans " & _
intNbRlt & " relation(s)." & vbCrLf & "La suppression de cette table entrainera la" & _
" suppression de cette(ces) relation(s)." & vbCrLf & vbCrLf & "Voulez vous continuer ?", _
vbQuestion + vbYesNo, "Suppression de table") = vbNo Then Exit Function
End If
'Supprime la table
oBaseDeDonnee.TableDefs.Delete (strNomTable)
'Rafraichit la collection
oBaseDeDonnee.TableDefs.Refresh
'Renvoie true
SupprimerTable = True
Exit Function
err:
'Gére les erreurs
Select Case err.Number
Case 3265: MsgBox "Impossible de trouver la table à supprimer"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Set oDb = CurrentDb
If SupprimerTable(oDb, "Commande") Then
MsgBox "Table supprimée"
End If

4.3.4.4 - Créer une nouvelle table

La création d'une table n'ayant que peu d'intéret sans la création de champs, je vous propose d'aborder avant les
parties concernant les champs et les index puis de revenir ensuite sur cet exemple.

Dans cet exemple, nous allons créer une table nommée Client possédant trois champs :

• IDClient Clé primaire. Type : Long, numéro automatique


• NomClient Type : Texte. Longueur : 15
• PrenomClient Type : Texte. Longueur : 25

Voici le code correspondant :

Sub CreerTable()
Dim oDb As DAO.Database
Dim oNouvelleTable As DAO.TableDef
Dim oChamp As DAO.Field
Dim oIndex As DAO.Index
'Instancie la base de données
Set oDb = CurrentDb
'Crée la nouvelle table
Set oNouvelleTable = oDb.CreateTableDef("Clients")
'Crée le champ IDClient
Set oChamp = oNouvelleTable.CreateField("IDClient", dbLong)
'Définit le champ en numero_auto
oChamp.Attributes = dbAutoIncrField
'Ajoute le champ à la table
oNouvelleTable.Fields.Append oChamp
'Crée le champ nomClient et l'ajoute
oNouvelleTable.Fields.Append oNouvelleTable.CreateField("NomClient", _
dbText, 15)
'Crée le champ PrenomClient et l'ajoute
oNouvelleTable.Fields.Append oNouvelleTable.CreateField("PrenomClient", _
dbText, 25)

- 40 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

'définit la clé primaire sur l'IDClient


Set oIndex = oNouvelleTable.CreateIndex("PK_IDClient")
oIndex.Primary = True
oIndex.Fields.Append oIndex.CreateField("IdClient")
'Ajoute l'index à la table
oNouvelleTable.Indexes.Append oIndex
'Ajoute la table à la base de données
oDb.TableDefs.Append oNouvelleTable

'Libère les variables


oDb.Close
Set oIndex = Nothing
Set oChamp = Nothing
Set oNouvelleTable = Nothing
Set oDb = Nothing
End Sub

4.4 - L'objet Field

4.4.1 - Définition

Un objet Field représente un champ d'une table ou d'une requête dans une base de données. DAO offre de
nombreuses possibilités concernant les objets Field. Il est ainsi possible de créer des champs, d'en supprimer et
de les modifier aussi simplement que vous le feriez dans le mode création d'Access. En effet, il existe une réelle
analogie entre la liste des propriétés des objets Field et la fenêtre de modification de la structure d'une table. Chaque
zone de texte de cette fenêtre correspond à une propriété de l'objet Field.

Je vous propose tout d'abord d'effectuer un tour d'horizon de l'ensemble des propriétés et des méthodes de cet objet,
avant de revenir sur des exemples plus spécifiques.

4.4.2 - Liste des propriétés

Vous retrouverez ci-dessous l'ensemble des propriétés des objets Field dans la liste suivante.

Certaines de ces propriétés ne sont disponibles en écriture uniquement pour les objets qui
n'ont pas encore été ajoutés à la collections TableDef.Fields.

4.4.2.1 - AllowZeroLength

Type : Boolean

La propriété AllowZeroLength indique si un champ texte accepte les chaines vides. Si la valeur de cette propriété
est égale à True, ces valeurs sont acceptées. Dans le cas échéant, une erreur sera levée lorsque que vous tenterez
de mettre à jour les données.

4.4.2.2 - Attributes

Type : Long

La propriété Attributes définit les options du champ. Il s'agit d'une une (ou une combinaison) des constantes
suivantes :

- 41 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Constante Signification
dbAutoIncrField Correspond à un champ de type
Numéro Auto. A n'utiliser que sur les
champs de type numérique.
dbDescending Dans le cas où le champ fait parti d'un
index, cette valeur permet d'inverser
l'ordre de tri.
dbFixedField Champ de taille fixe. Valeur par défaut
des champs de type numérique.
dbHyperlinkField Gère les liens hypertext dans un
champs mémo.
dbSystemField Le champ stocke des informations de
duplication pour les duplicatas.
Un tel champ ne peut être supprimé.
dbUpdatableField Le valeur du champ peut être modifiée.
dbVariableField Le champ peut être modifié. A n'utiliser
que sur les champs de type texte.

4.4.2.3 - CollatingOrder

Type : Long

Il s'agit de la méthode utilisée par le moteur pour comparer les valeurs du champ si celui-ci est de type texte.

Les valeurs possibles sont :

Constante Signification
dbSortGeneral Général (Français, anglais ...)
dbSortArabic Arabe
dbSortChineseSimplified Chinois simplifié
dbSortChineseTraditional Chinois traditionnel
dbSortCyrillic Russe
dbSortCzech Tchèque
dbSortDutch Néerlandais
dbSortGreek Grec
dbSortHebrew Hébreu
dbSortHungarian Hongrois
dbSortIcelandic Islandais
dbSortJapanese Japonais
dbSortKorean Coréen
dbSortNeutral Neutre
dbSortNorwDan Norvégien et danois
dbSortPDXIntl Paradox International
dbSortPDXNor Paradox norvégien ou danois
dbSortPDXSwe Paradox suédois ou finnois
dbSortPolish Polonais
dbSortSlovenian Slovène
dbSortSpanish Espagnol
dbSortSwedFin Suédois ou finnois
dbSortThai Thaï
dbSortTurkish Turc
dbSortUndefined Indéfini

- 42 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.4.2.4 - DataUpdatable

Lecture seule.

Type : Boolean

Lorsque la propriété DataUpdatable est égale à False, il vous est impossible de modifier les valeurs de ce champ.
C'est notamment le cas d'un champ auto-incrémenté.

4.4.2.5 - DefaultValue

Type : Variant

Cette propriété correspond à la valeur par défaut du champ. Elle est en lecture/écriture pour les champs issus de
TableDef et en lecture seule pour ceux issus de QueryDef et Recordset. Elle n'est pas prise en charge par les objets
Fields des collections Database.Indexes et Database.Relations.

Pour un champ de type Long vous pouvez attribuer à cette propriété la valeur :
GenUniqueID(). Ainsi à chaque nouvel enregistrement ajouté, le moteur Jet attribue une
valeur unique et aléatoire au nouvel enregistrement. Cette valeur reproduit le comportement
d'une numérotation automatique aléatoire.

4.4.2.6 - FieldSize

Lecture seule.

Type : Long

La propriété FieldSize, correspond à la taille utilisée dans la base par un champ de type binaire ou mémo.
Cette valeur est exprimée en nombre de caractères pour un champ mémo et en nombre d'octet pour un champ de
type binaire.

4.4.2.7 - ForeignName

Type : String

La propriété ForeignName n'est à utiliser que pour les champs d'un objet de type Relation. Elle définit le nom du
champ dans la table externe de la relation (clé étrangère). Cette propriété est en lecture/écriture dans le cas d'objets
Relation non ajoutés à la collection Database.Relations et en lecture seule pour les objets déjà présents au sein
de cette même collection.

4.4.2.8 - Name

Type : String

Il s'agit du nom du champ. Le nom d'un champ doit être unique au sein d'une table.

4.4.2.9 - OrdinalPosition

Type : Integer

- 43 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La propriété OrdinalPosition permet de définir la position du champ dans la collection Fields de l'objet TableDef. Le
premier élément possède la position 0. Cette position conditionne l'ordre d'apparition des champs dans une requête
SELECT * FROM ... Notons que si deux champs possèdent la même valeur pour la propriété OrdinalPosition, ces
champs sont alors classés par ordre alphabétique.
Cette propriété est en lecture seule pour les objets QueryDef.

4.4.2.10 - Properties

Type : Collection

Collection regroupant l'ensemble des objets Property de l'objet Field.

4.4.2.11 - Required

Type : Boolean

La propriété Required indique si le champs accepte les valeurs nulles. Si cette propriété est égale à True, une erreur
sera levée si vous tentez d'affecter une valeur nulle à ce champ.

4.4.2.12 - Size

Type : Integer

La propriété Size définit la taille du champ comme vous pouvez le faire en mode création. Cette propriété n'est en
lecture écriture que pour les objets Field qui n'ont pas encore été ajoutés à la collection Fields.

4.4.2.13 - SourceField

Lecture seule.

Type : String

Cette propriété en lecture seule indique dans un objet QueryDef le nom d'un champ et non son alias. Soit une requête
nommée R01 :

SELECT NomClient as LeNom FROM Client

Le code suivant affichera LeNom :

Dim oDb As DAO.Database


Dim oQR As DAO.QueryDef
Set oDb = CurrentDb
Set oQR = oDb.QueryDefs("R01")
MsgBox oQR.Fields(0).Name

Cet autre code affichera NomClient :

Dim oDb As DAO.Database


Dim oQR As DAO.QueryDef
Set oDb = CurrentDb
Set oQR = oDb.QueryDefs("R01")
MsgBox oQR.Fields(0).SourceField

Nous pouvons donc écrire la fonction suivante qui retourne le nom d'un champ en fonction de son alias :

- 44 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Function NomChamp(oBaseDeDonnee As DAO.Database, strRequete As String,


strAlias As String) As String
On Error GoTo err
Dim Qdf As DAO.QueryDef
Set Qdf = oBaseDeDonnee.QueryDefs(strRequete)
NomChamp = Qdf.Fields(strAlias).SourceField
Exit Function
'Gère les erreurs
err:
Select Case err.Number
Case 3265
'Si qdf est vide alors la requete n'existe pas
If Qdf Is Nothing Then
MsgBox "Impossible de trouver la requête " & strRequete
Else

MsgBox "Impossible de trouver le champ " & strAlias & " dans la requete " & _
strRequete
End If
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Set oDb = CurrentDb
MsgBox NomChamp(oDb, "R01", "LeClient")

4.4.2.14 - SourceTable

Lecture seule.

Type : String

Cette propriété repose sur le même principe que la précédente. Elle permet de savoir de quelle table provient un
champ d'une requête.

Ainsi, avec l'exemple précédent, voici comment connaître la table d'origine du champ LeClient :

Dim oDb As DAO.Database


Dim oQR As DAO.QueryDef
Set oDb = CurrentDb
Set oQR = oDb.QueryDefs("R01")
MsgBox oQR.Fields(0).SourceTable

4.4.2.15 - Type

Type : Integer

Cette propriété définit le type du champ. Il s'agit d'une des constantes suivantes :

- 45 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Constante Valeur Type


dbBigInt 16 Numérique (haute
précision)
dbBinary 9 Binaire de longueur fixe
(255 octets maxi)
dbBoolean 1 Booléen
dbByte 2 Octet
dbChar 18 Chaîne de caractère de
longueur fixe
dbCurrency 5 Monétaire
dbDate 8 Date/Heure
dbDecimal 20 Décimal
dbDouble 7 Double
dbFloat 21 Réel à virgule flottante
dbGUID 15 Identifiant GUID
dbInteger 3 Entier
dbLong 4 Entier long
dbLongBinary 11 Binaire à longueur
variable. (OLE)
dbMemo 12 Mémo
dbNumeric 19 Numérique
dbSingle 6 Réel Simple
dbText 10 Texte à longueur fixe
dbTime 22 Heure
dbTimeStamp 23 TimeStamp
dbVarBinary 17 Binaire à longueur
variable (255 octets maxi)

4.4.2.16 - ValidationRule

Type : String

La propriété ValidationRule définit la règle de validation qui sera utilisée pour valider les données lors d'une mise
à jour (Insert compris).

4.4.2.17 - ValidationText

Type : String

La propriété ValidationText correspond au message qui sera affiché lors d'une mise à jour si les données ne vérifient
pas la règle spécifiée dans ValidationRule.

4.4.2.18 - Value

Type : Variant

Pour un objet Recordset, la propriété Value retourne la valeur du champ pour l'enregistrement courant.

4.4.2.19 - VisibleValue

Type : Variant

- 46 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Cette propriété est utilisable uniquement dans un environnement ODBCDirect. Elle renvoit la valeur actuelle
d'un champ lors d'un traitement par lot. Cette valeur est donc plus récente que celle retournée par la propriété
OriginalValue

4.4.3 - Liste des méthodes

4.4.3.1 - AppendChunk

La méthode AppendChuk permet d'ajouter des données à la fin d'un champ de type mémo ou binaire. (Collection
Recordsets exclusivement) Elle évite notamment de lire le début du champ, de concaténer et de renvoyer la nouvelle
valeur. En utilisant la méthode AppendChunk, vous limiter donc le traffic d'informations entre la base de données
et le moteur Jet.

Syntaxe :

field.AppendChunk source

L'argument source est de type Variant.

4.4.3.2 - CreateProperty

La méthode CreateProperty crée et retourne un nouvel objet Property qu'il vous faudra ensuite ajouter à la collection
Properties de l'objet Field.

La syntaxe de la méthode est celle illustrée dans la partie : Les propriétés spécifiques.

4.4.3.3 - GetChunk

La méthode GetChunk s'applique aux champs des objets Recordset. Elle renvoie le contenu (ou une partie) d'un
champ mémo ou binaire dans une variable de type String.

Syntaxe :

Set variable = field.GetChunk (offset, numbytes)

Le paramètre offset de type Long correspond à la position du caractère (ou de l'octet) à partir duquel doit commencer
la lecture.

L'argument numbytes détermine le nombre de caractères (ou d'octet) à lire.

4.4.4 - Opérations sur les champs d'un objet TableDef

Seul l'objet TableDef permet de modifier les éléments de sa collection Field. Je vous propose plusieurs exemples
afin d'illustrer l'étendue des possibilités qu'offre DAO.

4.4.4.1 - Renommer un champ

Tout comme c'était déjà le cas avec les tables, cette opération nécessite que le nouveau nom soit unique dans la
collection Fields de l'objet TableDef.

- 47 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Les objets Relation et Index utilisant ce champ sont automatiquement mis à jour par le moteur
Jet.

Private Function RenommerChamp(oBaseDeDonnees As DAO.Database, strNomTable As String, _


strAncienNomChamp As String, strNouveauNomChamp As String) As Boolean

On Error GoTo err


Dim Tbl As DAO.TableDef
'Récupère la table
Set Tbl = oBaseDeDonnees.TableDefs(strNomTable)
'Renomme le champ
Tbl.Fields(strAncienNomChamp).Name = strNouveauNomChamp
'Renvoie True
RenommerChamp = True
'Gère les erreurs
Exit Function
err:
Select Case err.Number
'Si impossible de trouver l'élément dans la collection
Case 3265
'Si tbl=nothing alors tbl est la cause de l'erreur
If Tbl Is Nothing Then
MsgBox "Impossible de trouver la table : " & strNomTable
Else
MsgBox "Impossible de trouver le champ : " & strAncienNomChamp
End If
Case 3010, 3191: MsgBox "Le champ " & strNouveauNomChamp & " existe déjà"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Set oDb = CurrentDb
If RenommerChamp (oDb, "Commande", "Reference", "Nouvelle_Reference") then
msgbox "Opération terminée"
End if

4.4.4.2 - Supprimer un champ

La suppression d'un champ est trés délicate. En effet, plusieurs erreurs peuvent être levées au cours de cette
opération :

• 3265 : Le champ n'existe pas


• 3280 : Le champ est utilisé par un index
• 3303 : Le champ est utilisé dans une ou plusieurs relations

L'erreur 3303 est difficile à maitriser car même si l'erreur est levée, le champ est quand même supprimé. Toutefois
les relations sont toujours présentes et si vous rajoutez par la suite le champ supprimé, la relation va "renaître", ce
qui provoque un comportement inattendu.

Il nous faut donc savoir si le champ est l'objet de relations.

Private Function ChampDansRelation(oBaseDeDonnees As DAO.Database, _


strNomTable As String, strNomChamp As String) As Integer
On Error GoTo err
Dim bolUtilise As Boolean
Dim oRlt As DAO.Relation
Dim oFld As DAO.Field
'Parcours les relations
For Each oRlt In oBaseDeDonnees.Relations
bolUtilise = False

- 48 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

If oRlt.Table = strNomTable Then


'Pour chaque champ, contrôle le nom du champ
For Each oFld In oRlt.Fields
If oFld.Name = strNomChamp Then bolUtilise = True
Next oFld
ElseIf oRlt.ForeignTable = strNomTable Then
'pour chaque champ, contrôle le nom étranger
For Each oFld In oRlt.Fields
If oFld.ForeignName = strNomChamp Then bolUtilise = True
Next oFld
End If
'Si la relation utilise le champ, on incremente le resultat
If bolUtilise Then ChampDansRelation = ChampDansRelation + 1
Next oRlt
Exit Function
err:
ChampDansRelation = -1
End Function

Cette fonction renvoie le nombre de relations qui utilisent le champ passé en paramètre.

Utilisation :

Dim oDb as DAO.Database


Set oDb=CurrentDB
MsgBox ChampDansRelation(oDb, "Commande", "Reference")

Cet exemple affichera le nombre de relations utilisant le champ Reference de la table Commande.

La fonction retourne -1 si une erreur est survenue.

Nous pouvons donc écrire la fonction de suppression suivante :

Private Function SupprimerChamp(oBaseDeDonnees As DAO.Database, strNomTable As String, _


strNomChampASupprimer As String) As Boolean

On Error GoTo err


Dim oTbl As DAO.TableDef
'Verifie que le champ ne fait pas partie d'une relation
If ChampDansRelation(oBaseDeDonnees, strNomTable, strNomChampASupprimer) = 0 Then
'Récupère la table
Set oTbl = oBaseDeDonnees.TableDefs(strNomTable)
'Supprime le champ
oTbl.Fields.Delete (strNomChampASupprimer)
'Renvoie True
SupprimerChamp = True
Else
MsgBox "Impossible de supprimer le champ, il est utilisé par une ou plusieurs relations"
End If
Exit Function
err:
Select Case err.Number
'Si impossible de trouver l'élément dans la collection
Case 3265
'Si tbl=nothing alors tbl est la cause de l'erreur
If Tbl Is Nothing Then
MsgBox "Impossible de trouver la table : " & strNomTable
Else
MsgBox "Impossible de trouver le champ : " & strNomChampASupprimer
End If
Case 3280: MsgBox "Impossible de supprimer un champ utilisé par un index"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

- 49 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Utilisation :

SupprimerChamp oDb, "Commande", "Reference"

4.4.4.3 - Créer un champ

La création d'un champ se décompose en trois étapes :

Un exemple sera certainement plus parlant que de longues phrases, je vous propose de créer un champ
AdresseClient dans une table nommée Client.
Ce champ aura pour cractéristiques :

• Type : Texte
• Longueur : 120 caractères
• Chaine vide autorisée : Non
• Null interdit : Oui

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Dim oFld As DAO.Field
Set oDb = CurrentDb
Set oTbl = oDb.TableDefs("Client")
'Etape 1 : Créer le champ
Set oFld = oTbl.CreateField("AdresseClient", dbText, 120)
'Etape 2 : Définit les propriétés
oFld.AllowZeroLength = False 'Chaine vide autorisée : Non
oFld.Required = True 'Null interdit : Oui
'Etape 3 : Ajout du champ à la table
oTbl.Fields.Append Fld
'Rafraichit la collection
oTbl.Fields.Refresh

Il est important de respecter l'ordre de chaque étape. Si vous ajouter le champ à la collection Fields avant de lui avoir
affecter l'ensemble de ses propriétés, vous vous apercevrez que certaines de ces propriétés ne sont plus accessibles
en écriture.

Nous n'avons pas traité ici la gestion d'erreur. Celle ci exactement la même que pour la
fonction qui renomme un champ. En effet, le plus grand risque pour ce programme est d'utiliser
un nom de champ qui existe déjà.

- 50 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.4.4.4 - Dupliquer un champ

Je vous propose ici un code qui peut s'avérer utile lorsque vous souhaiter créer un champ identique à un autre. Le
principe est simple, nous partons de deux objets Field. Le premier sera utilisé comme source du clonage. Nous allons
donc parcourir chaque propriété (exceptée la propriété Name) du champ source et les réécrire dans le champ de
destination.

Certaines de ces propriétés risquent d'être en lecture seule. Il nous faut donc déleguer la
lecture et l'écriture des propriétés à une autre procédure afin de ne pas faire stopper le
programme à la première erreur rencontrée.

Public Sub CloneChamp(oFldSource As DAO.Field, oTableDestination As DAO.TableDef, _


strNouveauNom As String)
On Error GoTo err
Dim oFld As DAO.Field
Dim oPrp As DAO.Property
'Crée le champ
Set oFld = oTableDestination.CreateField(strNouveauNom)
'Pour chaque propriete
For Each oPrp In oFldSource.Properties
'copier la propriété s'il ne s'agit pas du nom
If oPrp.Name <> "Name" Then _
EcrirePropriete oPrp, oFld
Next oPrp
'Ajoute le champ
oTableDestination.Fields.Append oFld
Exit Sub
err:
Select Case err.Number
Case 3010, 3191: MsgBox "Le champ " & strNouveauNom & " existe déjà"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Sub

Private Sub EcrirePropriete(oPropriete As DAO.Property, _


oChampDestination As DAO.Field)
On Error GoTo err
'Copie la propriété
With oChampDestination.Properties
.Item(oPropriete.Name) = oPropriete.Value
.Refresh
End With
'On ne traite pas les erreurs
err:
End Sub

Pour dupliquer le champ AdresseClient de la table Client dans la table SauvegardeClient nous utiliserons :

Dim oDb As DAO.Database


Dim oTblSource As DAO.TableDef, oTblDestination As DAO.TableDef
Dim oFld As DAO.Field
Set oDb = CurrentDb
'Stocke les deux tables
Set oTblSource = oDb.TableDefs("Client")
Set oTblDestination = oDb.TableDefs("SauvegardeClient")
'Stocke le champ
Set oFld = oTblSource.Fields("AdresseClient")
'Clone le champ
CloneChamp oFld, oTblDestination, "AdresseClient2"

4.5 - L'objet Index

- 51 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.5.1 - Définitions

Nous n'allons pas reprendre ici la définition d'un index. Je vous renvoie pour cela vers d'autres tutoriels de ce site.
Toutefois, rappelons sommairement qu'un index permet de faciliter l'accès aux données dans une table lors d'une
recherche et qu'il permet aussi de poser des contraintes sur les données (Notion de clé primaire et de doublons).

Un index peut être composé d'un ou plusieurs champs, il possède donc une collection Fields recensant ces champs.

4.5.2 - Liste des propriétés

4.5.2.1 - DistinctCount

Lecture seule.

Type : Long

La propriété DistinctCount renvoie le nombre de valeurs uniques présentes dans la table. Dans le cas d'un index
mono-champ, il s'agit du nombre de valeurs distinctes dans ce champ (équivalent d'une requête SELECT DISTINCT
MonChamp ...). Dans le cas d'un index composé de plusieurs champs, cette valeur correspond au nombre de
combinaisons distinctes des valeurs de ces champs au sein de la table (équivalent d'une requête SELECT DISTINCT
MonChamp1,MonChamp2 ...).

4.5.2.2 - Fields

Type : Collection

Cette collection regroupe l'ensemble des champs composant l'index. Chaque objet Field de cette collection doit
posséder le même nom qu'un objet Field de la table concernée.

4.5.2.3 - Foreign

Lecture seule.

Type : Boolean

Lorsque la propriété Foreign d'un index est égale à True, cela signifie que l'index est une clé étrangère. C'est
notamment le cas pour les index ajoutés automatiquement par Access lorsque vous créez des relations entre les
tables.

4.5.2.4 - IgnoreNulls

Type : Boolean

Si vous définissez la propriété IgnoreNulls à True, les valeurs nulles ne seront pas indéxées. Cela peut être utile si
vous prévoyer d'enregistrer un grand nombre de valeur nulles.

4.5.2.5 - Name

Type : String

- 52 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Cette propriété correspond au nom de l'index. Ce nom doit être unique dans la collection Indexes de l'objet TableDef
correspondant.

Prévoyez des noms d'index aussi clairs que possible. Aussi certains préfixent le nom de leurs
index par les initiales de leur rôle. Ainsi, une clé primaire sera notée PK_MonChamp (PK =
Primary Key).

4.5.2.6 - Properties

Type : Collection

Collection regroupant l'ensemble des objets Property de l'objet Index.

4.5.2.7 - Required

Type : Boolean

Si la propriété Required est égale à True, cela signifie que les champs de l'index doivent tous recevoir une valeur,
sans quoi, lors des mises à jour, une erreur sera levée.

4.5.2.8 - Unique

Type : Boolean

Lorsque la propriété Unique est égale à True, les doublons sont interdits dans les champs de l'index.

Dans un index multi-colonnes, les valeurs A A et A B ne sont pas des doublons.

4.5.3 - Liste des méthodes

Comme vous allez le remarquer, l'objet Index dispose de trés peu de méthodes. Qui plus est, ces méthodes ont
déjà été traitées plus haut.

4.5.3.1 - CreateField

Cette méthode est la même que celle appliquée aux objets TableDef, à la différence prés quelle ne propose qu'un
seul paramètre : le nom du champ. Ce nom doit être identique à celui du champ de la table sur lequel repose l'index.

Syntaxe :

Set field = index.CreateField (name)

4.5.3.2 - CreateProperty

Cette méthode n'est plus à présenter, et pour cause, nous la retrouvons à chaque chapitre de ce tutoriel. Aussi, je
vous renvoie vers le chapitre des 4.2.5 Propriétés spécifiques.

- 53 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.5.4 - Opérations sur les Index

Je vous propose deux petits exemples afin de mettre en pratique les notions abordées dans cette partie.

4.5.4.1 - Créer un index

Soit une table Client possédant plusieurs champs dont NumeroClient. Nous allons créer une clé primaire sur ce
champ.

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
Dim oFld As DAO.Field
Dim oInd As DAO.Index
'Instancie la base
Set oDb = CurrentDb
'Instancie la table
Set oTbl = oDb.TableDefs("Client")
'Crée l'index en le nommant PK_Client
Set oInd = oTbl.CreateIndex("PK_Client")
'Cree le champs dans l'index
Set oFld = oInd.CreateField("NumeroClient")
'Ajoute le champ à la collection Fields
oInd.Fields.Append oFld
'Définit la clé primaire
oInd.Primary = True
'Ajoute l'index à la table
oTbl.Indexes.Append oInd
'Rafraichit la collection
oTbl.Indexes.Refresh

4.5.4.2 - Supprimer une clé primaire

Afin d'illustrer la suppression d'un index je vous propose de traiter le cas, où nous souhaitons supprimer la clé primaire
de la table. Il nous faut donc parcourir l'ensemble des index de l'objet TableDef et les supprimer si leur propriété
Primary est égale à True.

Private Sub SupprimerClePrimaire(oTbl As DAO.TableDef)


On Error GoTo err
Dim oInd As DAO.Index
'Parcours les index
For Each oInd In oTbl.Indexes
'S'il s'agit d'une clé primaire, alors le supprimer
If oInd.Primary Then
oTbl.Indexes.Delete (oInd.Name)
End If
Next oInd
Exit Sub
err:
MsgBox "Une erreur inattendue est survenue"
End Sub

Utilisation :

Dim oDb As DAO.Database


Dim oTbl As DAO.TableDef
'Instancie la base
Set oDb = CurrentDb
'Instancie la table
Set oTbl = oDb.TableDefs("Client")
'Supprime la clé primaire
SupprimerClePrimaire oTbl

- 54 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.6 - L'objet Relation

4.6.1 - Définitions

Certaines applications sont jugées sur leur performance ou leur ergonomie. Lorsqu'il s'agit d'une base de données,
les critères de sélection ne sont plus les mêmes. Le rôle principal d'un SGBD est de stocker des données et ce
stockage doit être réalisé dans les meilleures conditions. Il serait dramatique que certaines données soient perdues
fréquemment. Une application Access doit donc garantir la cohérence et l'intégrité des données. Imaginons une table
Commande et une table Client, il serait illogique d'affecter une commande à un client non recensé dans la table
Client. Afin d'éviter ce risque , le moteur Jet permet de créer des contraintes d'intégrités par le biais de ses objets
Relations qui obligeront à saisir un client valide dans la table des commandes.

4.6.2 - Liste des propriétés

4.6.2.1 - Attributes

Type : Long

La propriété Attributes correspond au type de la contrainte représentée par l'objet Relation. La valeur de cette
propriété doit être une (ou une combinaison) des constantes suivantes :

Constante Signification
dbRelationUnique Relation de type un à un.
dbRelationDontEnforce L'intégrité référentielle n'est pas
appliquée.
dbRelationUpdateCascade Les mises à jours sont répercutées
en cascade.
dbRelationDeleteCascade Les suppressions sont répercutées
en cascade.
dbRelationLeft Les jointures seront de type Left
par défaut.
dbRelationRight Les jointures seront de type Rigth
par défaut.

4.6.2.2 - Fields

Type : Collection

Cette collection regroupe l'ensemble des champs utilisés par la relation. Vous devez utiliser la méthode
Relation.CreateField pour créer de nouveaux champs dans la relation et les ajouter à la collection Fields à l'aide
de la méthode Append.

Chaque objet Field de la relation doit posséder le nom du champ concerné dans la table
spécifiée dans la propriété Table. Ce champ aura comme propriété ForeignName, le nom
d'un champ de la table spécifiée dans la propriété ForeignTable.

4.6.2.3 - ForeignTable

Type : String

- 55 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La propriété ForeignTable correspond au nom de la table externe de la relation. Ce nom doit être celui d'un objet
TableDef présent dans la collection TableDefs de l'objet Database.

4.6.2.4 - Name

Type : String

La propriété Name représente le nom de la relation. Il doit être unique au sein de la collection Database.Relations.

L'utilisation de nom précis facilitera les opérations de maintenance sur la base de


données. Ainsi, une relation entre une table commande et une table client sera nommée
Rlt_CommandeClient. Evitez d'appeler vos objets Relation1, Table1, Requete1...

4.6.2.6 - Properties

Type : Collection

La collection Properties regroupe l'ensemble des propriétés de l'objet Relation.

4.6.2.7 - Table

Type : String

La propriété Table correspond au nom de la table principale sur laquelle porte la relation. Il s'agit de la table possédant
la clé primaire utilisée dans la relation. A contrario, la propriété ForeignName correspond à la table possédant la clé
étrangère de la relation.

4.6.3 - Liste des méthodes

Les objets de type Relation ne possède qu'une seule méthode : CreateField. Celle ci permet de créer un champ à
ajouter à la relation.

Syntaxe :

Set field = relation.CreateField (name)

Name correspond au nom du champ de la clé primaire utilisée dans la relation.

4.6.4 - Exemple de définition des propriétés

Considérons deux tables et la relation suivante :

- 56 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Paramètres de la relation :

Les propriétés d'une telle relation seront définies ainsi :

• Attributes : dbRelationUpdateCascade
• Fields : Un objet Field nommé "NumClient" et ayant comme propriété ForeignName : "IDClient"
• ForeignTable : "Commande"
• Name : "Rlt_CommandeClient"
• PartialReplica : False (Non utilisé)
• Table : "Client"

4.6.5 - Opérations sur les relations

Je vous propose une suite de quelques exemples de code VBA afin de manipuler les objets Relations

4.6.5.1 - Créer une relation

Reprenons l'exemple ci-dessus. Je vous livre le code correspondant à une telle relation.

La première méthode consiste à créer la relation et affecter à chacune des propriétés sa valeur correspondante.

- 57 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Dim oDb As DAO.Database


Dim oRlt As DAO.Relation
Dim oFld As DAO.Field
Set oDb = CurrentDb
'Crée la relation
Set oRlt = oDb.CreateRelation
'Définit les propriétés
oRlt.Attributes = dbRelationUpdateCascade
oRlt.ForeignTable = "Commande"
oRlt.Name = "Rlt_CommandeClient"
oRlt.Table = "Client"
'Crée le champ dans la relation
Set oFld = oRlt.CreateField("NumClient")
'Définit le nom de la clé externe
oFld.ForeignName = "IDClient"
'Ajoute le champ
oRlt.Fields.Append oFld
'Rafraîhit la collection Relations
oDb.Relations.Refresh
'Ajoute la relation
oDb.Relations.Append oRlt
'Rafraîhit la collection Relations
oDb.Relations.Refresh
'Ferme la base de données
oDb.Close
Set oDb = Nothing

La seconde méthode consite à utiliser l'ensemble des arguments de la méthode CreateProperty. En effet celle-ci
permet d'initialiser le nom de la relation, de la table, de la table externe ainsi que les attributs.

Syntaxe :

Set relation = database.CreateRelation (name, table, foreigntable, attributes)

Notre code devient alors :

Dim oDb As DAO.Database


Dim oRlt As DAO.Relation
Dim oFld As DAO.Field
Set oDb = CurrentDb
'Crée la relation
Set oRlt = oDb.CreateRelation("Rlt_CommandeClient", "Client", _
"Commande", dbRelationUpdateCascade)
'Crée le champ
Set oFld = oRlt.CreateField("NumClient")
'Définit le nom de la clé externe
oFld.ForeignName = "IDClient"
'Ajoute le champ
oRlt.Fields.Append oFld
'Rafraîhit la collection Relations
oDb.Relations.Refresh
'Ajoute la relation
oDb.Relations.Append oRlt
'Rafraîhit la collection Relations
oDb.Relations.Refresh
'Ferme la base de données
oDb.Close
Set oDb = Nothing

4.6.5.2 - Compter les relations utilisant un champ donné

Cette fonction a déjà été utilisé lors de l'opération qui consistait à supprimer un champ dans un objet TableDef.

Le principe est simple, un champ est utilisé par une relation si :

- 58 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

• La table dont il provient est présent dans la propriété Table de la relation et que le nom d'un champ de la
relation est égal au nom de ce champ.
• La table dont il provient est présent dans la propriété ForeignTable de la relation et qu'au moins un champ de
cette relation possède une propriété ForeignName égale au nom de ce champ.

Il nous suffit donc de boucler sur l'ensemble des objets Relation de la base de données.

Private Function ChampDansRelation(oBaseDeDonnees As DAO.Database, _


strNomTable As String, strNomChamp As String) As Integer
On Error GoTo err
Dim bolUtilise As Boolean
Dim oRlt As DAO.Relation
Dim oFld As DAO.Field
'Parcours les relations
For Each oRlt In oBaseDeDonnees.Relations
bolUtilise = False
If oRlt.Table = strNomTable Then
'Pour chaque champ, contrôle le nom du champ
For Each oFld In oRlt.Fields
If oFld.Name = strNomChamp Then bolUtilise = True
Next oFld
ElseIf oRlt.ForeignTable = strNomTable Then
'pour chaque champ, contrôle le nom étranger
For Each oFld In oRlt.Fields
If oFld.ForeignName = strNomChamp Then bolUtilise = True
Next oFld
End If
'Si la relation utilise le champ, on incremente le resultat
If bolUtilise Then ChampDansRelation = ChampDansRelation + 1
Next oRlt
Exit Function
err:
ChampDansRelation = -1
End Function

Il devient alors possible de connaître le nombre de relations utilisant le champ NumClient de la table Client.

Utilisation :

Dim oDb as DAO.Database


Set oDb=CurrentDB
MsgBox ChampDansRelation(oDb, "Client", "NumClient")

4.6.5.3 - Supprimer les relations autour d'une table

Il peut s'avérer par fois utile de supprimer les relations portant sur une table avant de pouvoir modifier la structure de
la table. Cette opération peut s'avérer fastidieuse et je vous suggère de créer une fonction automatisant cette tâche.

Public Function SupprimerRelationTable(oBaseDeDonnees As _


DAO.Database, strNomTable As String) As Integer
Dim oRlt As DAO.Relation
'Pour chaque relation,
For Each oRlt In oBaseDeDonnees.Relations
'si la table est utilisée
If oRlt.Table = strNomTable Or oRlt.ForeignTable = strNomTable Then
'Supprime la relation
oBaseDeDonnees.Relations.Delete oRlt.Name
oBaseDeDonnees.Relations.Refresh
'Incrémente le compteur
SupprimerRelationTable = SupprimerRelationTable + 1
End If
Next oRlt
End Function

- 59 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La fonction SupprimerRelationTable retourne le nombre de relations supprimées.

Utilisation :

Dim oDb As DAO.Database


Dim oRlt As DAO.Relation
Set oDb = CurrentDb
'Supprime les relations de la table Client
MsgBox SupprimerRelationTable(oDb, "Client")

4.7 - L'objet QueryDef

Nous sommes sur le point d'aborder le dernier objet de la partie DDL du modèle DAO. Cette partie commencera par
une rapide présentation de l'objet, suivie de la liste des propriétés et des méthodes puis enfin, quelques exemples
d'utilisation en VBA.

4.7.1 - Définitions

Access est un des rares SGBDR permettant de stocker des requêtes SQL dans la base de données sans qu'il ne
s'agissent de vues. Certes, une vue est le résultat de cette requête mais son contenu est statique. Pour visualiser
les modifications intervenues dans le jeu d'enregistrements entre deux instants, il est nécessaire de recréer la vue.
Une requête stockée dans une base de données Access est dynamique. Elle est réexecutée à chaque fois que vous
la réouvrez. De telles requêtes sont modélisées par l'objet QueryDef dans DAO.

Ces requêtes peuvent être de plusieurs types : sélection, union, insertion, mise à jour, suppression, analyse
croisée ...

Requêtes paramétrées :

DAO propose de gérer les paramètres des requêtes via la collection Parameters de l'objet QueryDef. Ces requêtes
sont trop souvent oubliées dans Microsoft Access et remplacées par des requêtes SQL codées directement dans
VBA. Pourtant, la manipulation de ces requêtes est trés simple :

PARAMETERS Param_Num Text ( 10 );


SELECT *
FROM Client
WHERE NumClient=Param_Num;

La clause PARAMETERS liste l'ensemble des paramètres avec leur type et (optionnellement) leur taille. La seconde
partie de la requête, est celle que vous auriez écrit sans paramètre.

Ainsi, pour ouvrir un Recordset sur le client possédant le numéro AF36, le code VBA serait :

Dim oDb As DAO.Database


Dim oQdf As DAO.QueryDef
Dim oRst As DAO.Recordset
Set oDb = CurrentDb
Set oQdf = oDb.QueryDefs("R01")
oQdf.Parameters("Num").Value = "AF36"
Set oRst = oQdf.OpenRecordset

Afin de comparer, voici le même code sans utiliser les requêtes paramétrées :

Dim oDb As DAO.Database


Dim oSQL As String
Dim oRst As DAO.Recordset

- 60 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Dim StrSQL As String


Set oDb = CurrentDb
StrSQL = "SELECT * FROM Client " & _
"WHERE NumClient=" & Chr(34) & "AF36" & Chr(34)
Set oRst = oDb.OpenRecordset(StrSQL)

L'utilisation des requêtes paramétrées apparait donc plus intuitive et évite de manipuler des fonctions de conversion
de chaîne. De plus, si demain, nous souhaitons modifier notre requête pour y ajouter une jointure, il nous suffit de
modifier le code SQL correspondant dans la requête paramétrée. Si au contraire nous n'utilisons pas ces requêtes,
il nous faut alors modifier notre code VBA aux différents endroit où la "requête" est mentionnée.

Si vous ouvrez un objet Database Db2 depuis la base de données Db1 et que vous éxecutez
un objet QueryDef de Db2, les données seront prélevées depuis Db2 et non dans Db1.
Chaque objet QueryDef travaille sur les données de l'objet Database qui le contient.

4.7.2 - Liste des propriétés

Vous trouverez ci-dessous la liste des propriétés disponibles pour les objets QueryDef.

La propriété Prepare n'est pas documentée dans ce tutoriel.

4.7.2.1 - Connect

Lecture seule.

Type : String

La propriété Connect renvoie la chaine de connexion utilisée par la requête lorsque celle ci provient d'une autre
base de données.

4.7.2.2 - DateCreated

Lecture seule.

Type : Date

Cette propriété renvoie la date à laquelle a été créé la requête.

4.7.2.3 - Fields

Lecture seule.

Type : Collection

Une nouvelle fois, nous rencontrons cette collection qui regroupe l'ensemble des champs retournés par la requête.

Notez que vous pouvez différencier le nom d'un champ et son alias en utilisant la propriété
SourceField de l'objet Field.

- 61 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.7.2.4 - LastUpdated

Lecture seule.

Type : Date

Cette propriété renvoie la date à laquelle a été modifiée la requête pour la dernière fois.

4.7.2.5 - MaxRecords

Type : Long

La propriété MaxRecords correspond au nombre d'enregistrements à renvoyer au maximum. Cette propriété peut
être utilisée lorsque le poste client ne dispose pas de ressources suffisantes afin de traiter l'ensemble des données.

Cette propriété est disponible uniquement pour les requêtes utilisant une source de données
ODBC.

4.7.2.6 - Name

Type : String

La propriété Name représente le nom de la requête. Il doit être unique au sein de la collection Database.QueryDefs.

Lorsque vous utilisez la méthode CreateQueryDef et que vous ne spécifiez pas l'argument
Name, la requête n'est pas sauvegardée dans la base de données à la fin du traitement.

4.7.2.7 - Parameters

Type : Collection

Cette collection regroupe l'ensemble des paramètres d'un objet QueryDef. Il est impossible d'ajouter ou de supprimer
des éléments de cette collection.

Un exemple d'utilisation de requête paramétrée est disponible dans les définitions des
QueryDefs ci-dessus.

4.7.2.8 - Properties

Type : Collection

La collection Properties regroupe l'ensemble des propriétés de l'objet QueryDef.

4.7.2.9 - RecordsAffected

Lecture seule.

Type : Long

- 62 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Dans le cas d'une requête action (Insert,Update,Delete), la propriété RecordsAffected retourne le nombre
d'enregistrements affectés par l'ordre SQL.

4.7.2.10 - ReturnsRecords

Type : Boolean

Cette propriété définit ou renvoie une valeur indiquant si une requête retourne des enregistrements.

La propriété ReturnsRecords est disponible uniquement pour les requêtes SQL directes.

4.7.2.11 - SQL

Type : String

La propriété SQL correspond au code SQL de la requête.

Cette propriété correspond à l'argument SQL de la méthode Database.CreateQueryDef.

4.7.2.12 - Type

Type : Long

La propriété Type renvoie le type de la requête. Cette propriété est définie automatiquement lorsque vous créez
l'objet QueryDef. Toutefois, elle peut vous permettre de recenser les objets QueryDef suivant leur rôle.

Les valeurs possibles sont :

Constante Signification
dbQAction Action
dbQAppend Ajout
dbQCompound Non documentée
dbQCrosstab Analyse croisée
dbQDDL Définition de données
dbQDelete Suppression
dbQMakeTable CreateTable
dbQProcedure Procédure stockée
dbQSelect Sélection
dbQSetOperation Union
dbQSPTBulk Requête ne renvoyant pas
d'enregistrement
dbQSQLPassThrough Requête SQL Directe
dbQUpdate Mise à jour

4.7.2.13 - Updatable

Lecture seule.

Type : Boolean

- 63 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Cette propriété renvoie True si les données de la requête ne peuvent être modifiées.

4.7.3 - Liste des méthodes

4.7.3.1 - CreateProperty

La méthode CreateProperty crée un nouvel objet Property. Plus de détails sont disponibles dans le chapitre 4.2.5
Propriétés spécifiques.

4.7.3.2 - Execute

La méthode Execute éxecute une requête Action. Une erreur sera levée si vous tentez d'exécuter une requête de
sélection.

Syntaxe :

querydef.Execute options

L'argument options doit être une (ou une combinaison) des constantes suivantes :

Constante Signification
dbDenyWrite Interdit l'accés en écriture pour les
autres utilisateurs
dbInconsistent (Valeur par défaut) Exécute des mises à
jour sans vérifier la cohérence (intégrité
réferentielle)
dbConsistent Exécute des mises à jour en vérifiant la
cohérence
dbSQLPassThrough Exécute une requête SQL Direct
dbFailOnError En cas d'erreur, les mises à jour sont
annulées
dbSeeChanges Génère une erreur d'exécution si un
autre utilisateur modifie les données que
vous êtes en train de modifier

Vous pouvez utiliser la propriété RecordsAffected pour connaître le nombre d'enregistrements


modifiés.

4.7.3.3 - OpenRecordset

La méthode OpenRecordset ouvre un jeu d'enregistrements sur le résultat de la requête.

Syntaxe :

Set recordset = object.OpenRecordset (type, options, lockedits)

Cette méthode sera largement abordée dans le chapitre suivant.

- 64 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

4.7.4 - Opérations sur les requêtes

4.7.4.1 - Création d'une requête

Dans notre exemple nous allons créer une requête de sélection complète de la table clients. Il s'agit d'une requête
simple et la méthode à appliquer est la même pour tout type de requête.

Sub CreerRequete()
On Error GoTo Err
Dim oDb As DAO.Database
Dim strCodeSql As String
'Instancie l'objet database
Set oDb = CurrentDb
'Stocke le code SQL dans une variable
strCodeSql = "SELECT * FROM Client"
'Crée la requête
oDb.CreateQueryDef "R01_SelectionClient", strCodeSql

Finally:
oDb.Close
Set oDb = Nothing

Err:
'Gére les erreurs
Select Case Err.Number
Case 3012: MsgBox "La requête existe déjà"
Case Else: MsgBox "Une erreur inconue est survenue"
End Select
Resume Finally
End Sub

4.7.4.2 - Modifier le code d'une requête

Afin de modifier le code SQL, il faut procéder en deux étapes :

• Récuperer l'objet QueryDef correspondant (S'il existe).


• Modifier la propriété SQL de l'objet.

Public Function ModifierSQL(oBaseDeDonnees As DAO.Database, _


strNomRequete As String, strCodeSQL As String) As Boolean
On Error GoTo Err
Dim oQdf As DAO.QueryDef
'Instancie l'objet QueryDef
Set oQdf = oBaseDeDonnees.QueryDefs(strNomRequete)
'Modifie le code SQL
oQdf.SQL = strCodeSQL
'Renvoie True
ModifierSQL = True
Exit Function
Err:
'Gere les erreurs
Select Case Err.Number
Case 3265: MsgBox "Impossible de trouver la requête à modifier"
Case Else: MsgBox "Une erreur inattendue est survenue"
End Select
End Function

Utilisation :

Dim oDb As DAO.Database


Set oDb = CurrentDb
If ModifierSQL(oDb, "R01_SelectionClient", "SELECT NumClient FROM Client") Then
MsgBox "Le code SQL de la requête a été modifié avec succés"

- 65 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

End If

4.7.4.3 - Lister les requêtes

La propriété Type retourne le type d'un objet QueryDef. Il est donc possible de lister l'ensemble des requêtes de
sélection.

Dim oDb As DAO.Database


Dim oQdf As DAO.QueryDef
'Instancie l'objet Database
Set oDb = CurrentDb
'Boucle sur les objets QueryDef
For Each oQdf In oDb.QueryDefs
'S'il s'agit d'une requête de sélection, alors afficher son nom
If oQdf.Type = dbQSelect Then MsgBox oQdf.Name, , "Sélection"
Next oQdf

- 66 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5 - Accès aux données

5.1 - Définition

Sous Visual Basic, une application est capable d'accèder aux données via un objet Recordset. Cet objet correspond
à un jeu d'enregistrements communément appelé curseur (de l'anglais CURSOR : CURrent Set Of Rows). Si vous
faites vos premiers pas dans le monde des Recordset, vous pouvez imaginer cela comme le tableau d'une requête
en mode feuille de données. Le Recordset est alors composé de plusieurs lignes (enregistrements) et de plusieurs
colonnes (champs). Lorsque vous accédez à la valeur d'un champ, vous le faîtes pour l'enregistrement courant dans
le Recordset. Il en est de même dans la feuille de données d'une requete. La ligne courante est alors matérialisée
par un triangle dans le sélecteur d'enregistrement. Celle ci pourrait se matérialiser par le sélecteur d'enregistrement
dans une feuille de données.

Les Recordset donnent donc la possibilité de récuperer le résultat d'une requête dans une variable, de l'analyser,
de le modifier, etc... tout comme vous le feriez manuellement dans une feuille de données ou un formulaire.

5.1.1 - Les différents types de Recordset

Il existe cinq types de Recordset :

1. Recordset de type Table :

Un Recordset de type Table permet d'accéder directement au contenu d'une table. Son contenu est dynamique,
ce qui signifie que les mises à jour sont directement répercutées dans le jeu d'enregistrement. La source d'un tel
Recordset est le nom d'une table.

Attention ce type est incompatible avec les tables liées (provenant d'une autre base de
données)

2. Recordset de type Dynaset :

Un Recordset de type Dynaset correspond au résultat d'une instruction SQL retournant des enregistrements. Son
contenu est dynamique et sa source peut être soit le nom d'une table, d'une requête ou bien une instruction SQL
valide.

3. Recordset de type Snapshot :

Un Recordset de type Snapshot correspond à une photographie des données à un instant donné (son ouverture).
Les modifications apportées dans la base de données aprés l'ouverture d'un tel curseur ne sont pas répercutées
dans le jeu d'enregistrements. Son contenu est donc statique et sa source est définit comme celle d'un Recordset
de type Dynaset.

4. Recordset de type ForwardOnly :

Il s'agit d'un Recordset de type Snapshot à la différence qu'il ne permet de se déplacer exclusivement vers l'avant. Il
est impossible de repartir au début du jeu d'enregistrement, ni même de reculer au cours de la lecture des données.

5. Recordset de type Dynamic :

- 67 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Ce type de Recordset est semblable au type Dynaset à la différence qu'il s'applique exclusivement aux sources
de données ODBC Direct.

5.2 - Ouvrir et fermer un recordset

Depuis Access et VBA, il est possible d'utiliser plusieurs méthodes afin d'ouvrir un jeu d'enregistrements.

5.2.1 - Depuis un objet Database

L'objet Database (et donc indirectement CurrentDB) est muni de la méthode OpenRecordset qui instancie un nouvel
objet Recordset et l'ajoute à la collection Database.Recordsets.

La syntaxe de cette méthode est la suivante :

Set recordset = Database.OpenRecordset (source, [type, options, lockedits])

source : Il s'agit de la source d'enregistrements du Recordset. Il peut s'agir du nom d'une table, d'une requête ou
d'une instruction SQL valide retournant des enregistrements (SELECT). Dans le cas d'un Recordset de type Table,
cet argument est restreint au nom d'une table.

Pour être valide, l'instruction SQL doit tenir compte des différents types de champ dans l'expression des critères.
Ainsi, si le champ NomClient est de type texte, la variable source sélectionnant le client nommé Dupont sera :

Source="SELECT * FROM Client WHERE NomClient=" & chr(34) & "Dupont" & chr(34)

La fonction Chr(34) permet d'encadrer un critère de type texte avec des guillemets. En effet, nous n'aurions pas pu
écrire :

Source="SELECT * FROM Client WHERE NomClient="Dupont""

En effet, dans ce cas, le " avant Dupont correspondrait à la fermeture de guillemet associée au premier caractère
" (avant SELECT). Une erreur serait donc levé par le compilateur. Une solution possible est donc d'utiliser le code
Ascii du caractère ". Le contenu de la variable utilisant la fonction Chr sera aprés concaténation :

SELECT * FROM Client WHERE NomClient="Dupont"

Toutefois, il reste encore un problème. Si dans la valeur recherchée figure un guillemet, le moteur Jet va l'interpréter
lui aussi comme une fin de chaine de caractère. La solution est de doubler les guillemets dans l'expression du critère :

Source="SELECT * FROM Client WHERE


NomClient=" & chr(34) & Replace(MaVariable,chr(34),chr(34) & chr(34)) & chr(34)

Ainsi, si MaVariable est égale à Monsieur "X", alors la fonction Replace retournera Monsieur ""X"". La source du
Recordset sera, aprés concaténation :

SELECT * FROM Client WHERE NomClient="Monsieur ""X"""

Le type Date est plus simple à traiter, il faut encadrer la valeur du critère par des #. Notons tout de même que les
dates doivent être en format américain : mm/jj/yyyy.

Un recordset sélectionnant les commandes du 10 décembre 2003 sera initialisé avec la source suivante :

Source="SELECT * FROM Commande WHERE DateCommande=#12/10/2003#"

- 68 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Type : Cet argument correspond au type du recordset à générer. Les constantes disponibles sont :

Constante Type de recordset


dbOpenTable Table
dbOpenDynamic Dynamique (ODBC
Direct)
dbOpenDynaset Feuille de réponse
dynamique
dbOpenSnapshot Instantané
dbOpenForwardOnly En avant seulement

Options : Ce paramètre définit les paramètres optionnels du Recordset. Il s'agit d'une (ou une combinaison) des
constantes suivantes :

Constante Effets
dbAppendOnly Permet aux utilisateurs d'ajouter de
nouveaux enregistrements à l'objet
Recordset, tout en leur interdisant
de modifier ou de supprimer les
enregistrements existants (objet
Recordset de type Feuille de réponses
dynamique Microsoft Jet (Dynaset)
uniquement).
dbSQLPassThrough Transmet une instruction SQL à une
source de données ODBC connectée
Microsoft Jet en vue de son traitement
(objet Recordset de type Instantané
Microsoft Jet (Snapshot) uniquement).
dbSeeChanges Génère une erreur d'exécution si un
utilisateur modifie les données en cours
de modification par un autre utilisateur
(objet Recordset de type Feuille de
réponses dynamique Microsoft Jet
(Dynaset) uniquement).
dbDenyWrite Interdit aux autres utilisateurs
de modifier ou d'ajouter des
enregistrements
dbDenyRead Interdit aux autres utilisateurs de lire les
données d'une table
dbInconsistent Autorise les mises à jour incohérentes
dbConsistent Autorise uniquement les mises à jour
cohérentes

Certaines constantes ont été volontairement oubliées dans cette liste du fait qu'elles sont soit
inapplicables sous Access, soit déconseillées.

LockEdits : Il s'agit du mode de verrouillage des données utilisé par le Recordset.


Les constantes disponibles sont :

Constante Verrouillage
dbReadOnly Interdit aux utilisateurs d'apporter des
modifications à l'objet Recordset
dbPessimistic Utilise le verrouillage pessimiste afin
de déterminer de quelle façon les
modifications sont apportées à l'objet

- 69 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Recordset dans un environnement


multi-utilisateur. La page contenant
l'enregistrement que vous modifiez
est verrouillée dès que vous utilisez la
méthode Edit (option par défaut pour les
espaces de travail Microsoft Jet).
dbOptimistic Utilise le verrouillage optimiste afin
de déterminer de quelle façon les
modifications sont apportées à l'objet
Recordset dans un environnement
multi-utilisateur. La page contenant
l'enregistrement n'est pas verrouillée
tant que l'exécution de la méthode
Update n'est pas terminée

Certaines constantes ont été volontairement oubliées dans cette liste du fait qu'elles sont
inapplicables sous Access.

Exemple :

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("SELECT * FROM Client WHERE NumClient=2",dbOpenDynaset)

Cet exemple ouvre un Recordset retournant le client possédant le numéro 2.

5.2.2 - Depuis un objet QueryDef

Si vous souhaitez accéder aux données d'une requête enregistrée vous pouvez utiliser la méthode OpenRecordset
de l'objet QueryDef correspondant plutôt que d'utiliser celle de l'objet Database qui nécessite de passer en paramètre
le nom de la requête.

La syntaxe de cette méthode est la suivante :

Set recordset = QueryDef.OpenRecordset ([type, options, lockedits])

Les arguments à utiliser sont les mêmes que ceux de la méthode Database.OpenRecordset. Notons toutefois qu'il
est impossible d'ouvrir un Recordset de type Table sur un objet QueryDef.

Dans le cas d'une requete paramétrée, vous devez affecter les paramètres avant d'ouvrir le
recordset. Il est impossible d'ouvrir un recordset sur une requete qui demande à l'utisateur
de saisir des critères via une boite de dialogue (type inputbox). Une erreur d'éxecution ( X
arguments attendus serait alors levée).

5.2.3 - Depuis un formulaire Access

Sans que vous le sachiez, vous avez déjà manipuler des objets Recordset par le biais d'un formulaire. En effet, tout
formulaire (et état) Access possédant une source de données (Propriété Source / RecordSource) utilise un curseur
pour afficher et manipuler les données qu'il contient. Vous pouvez vous même agir sur ce jeu d'enregistrement via la
propriété Recordset du formulaire. Ainsi, si vous utilisez la méthode Movenext sur le Recordset du formulaire, vous
vous apercevrez que votre formulaire a atteint l'enregistrement suivant. Notons aussi que tout déplacement dans le
Recordset du formulaire entraine l'appel de l'evenement Form_Current (sur activation) du formulaire.

- 70 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Syntaxe :

Set recordset=Me.Recordset

La méthode RecordsetClone d'un formulaire permet de dupliquer le jeu d'enregistrements du formulaire afin que
vous puissiez manipuler les données sans que ces modifications ne soient répercutées sur le formulaire et sans
qu'aucun évènement ne soit déclenché. Pour que le formulaire prenne en compte les modifications apportées sur le
jeu d'enregistrements, il est nécessaire d'appeler la méthode Requery de ce formulaire.

Set recordset=Me.RecordsetClone

5.2-4 - Fermer un Recordset

Lorsque vous manipulez les recordsets, une quantité importante de données est chagée en mémoire. Pour la libérer
il est nécessaire de procéder en deux temps :

1 appel de la méthode Recordset.Close,


2 affectation de Nothing à la variable.

Si la phase Set Recordset=Nothing est optionnelle car les variables seront inévitablement détruites à la fin de la
procédure (hors variables publiques détruite en fin d'application), l'appel à Close à quant à lui un caractère obligatoire.
En effet, une non fermeture systématique des Recordsets est à l'origine de l'accroissement si particulier de la taille
des bases de données Access, obligeant l'utilisateur à recourrir au compactage régulièrement.

Une bonne pratique consiste à placer la ligne suivante dès qu'un recordset n'est plus utile :

oRst.Close : Set oRst=Nothing

5.3 - Positions et déplacements

5.3.1 - Se déplacer dans un Recordset

Lorsque vous initialisez un jeu d'enregistrements, l'enregistrement courant est le premier si le recordset n'est pas
vide. Toutefois, il existe deux positions particulières :

• une avant le premier enregistrement. Lorsque vous êtes à cet emplacement, la propriété BOF du Recordset
est égale à True
• une après le dernier enregistrement. Dans ce cas, la propriété EOF est égale à True.

Dans le cas où le jeu d'enregistrement est vide, la position courante se trouve à la fois avant le premier enregistrement
et aprés le dernier. Ainsi, pour tester si le Recordset est vide ou pas, il suffit d'utiliser la condition suivante :

If Not oRecordset.EOF Then


Msgbox "Le jeu d'enregistrements n'est pas vide"
else
Msgbox "Le jeu d'enregistrements est vide"
End if

Cinq méthodes sont disponibles pour se déplacer dans le Recordset :

• MovePrevious permet d'atteindre l'enregistrement précédent.


• MoveNext permet d'atteindre l'enregistrement suivant.
• MoveFirst permet d'atteindre le premier enregistrement.
• MoveLast permet d'atteindre le dernier enregistrement.

- 71 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

• Move permet un déplacement relatif par rapport à la position courante..

Exemple :

'Se place sur le premier enregistrement


oRecordset.MoveFirst
'Se place sur le dernier enregistrement
oRecordset.MoveLast
'Se place sur l'enregistrement précédent
oRecordset.MovePrevious
'Se place sur l'enregistrement suivant
oRecordset.MoveNext
'Recule de trois enregistrements
oRecordset.Move -3
'Avance de trois enregistrements
oRecordset.Move 3

Lorsque vous atteignez le dernier enregistrement et que vous utilisez la méthode MoveNext, la
propriété EOF est égale à True et la position courante n'est plus un enregistrement. Vous êtes
à la fin du recordset et un nouveau déplacement vers l'avant entrainera une erreur d'exécution.
(Il en va de même pour BOF et les déplacements en arrière)

Pour parcourir l'ensemble des enregistrements d'un Recordset, vous procéderez ainsi :

'Tant que non fin du recordset


While Not oRecordset.EOF
'Passer au suivant
oRecordset.MoveNext
Wend

5.3.2 - Trouver un enregistrement

Les méthodes dont le nom commence par Find permettent d'atteindre un enregistrement dont les données vérifient
le critère passé en paramètre. Ce critère correspond à la clause WHERE d'une requête SQL.

La différence entre les diverses méthodes réside dans le sens de la recherche.

• FindNext recherche le prochain enregistrement (à partir de la position courante) vérifiant le critère.


• FindPrevious effectue la même recherche mais vers l'arrière.
• FindFirst trouve le premier enregistrement (à partir du début du jeu d'enregistrement) vérifiant le critère.
• FindLast trouve le dernier enregistrement (à partir de la fin du jeu d'enregistrement).

Ainsi, pour se positionner sur le premier enregistrement dont le champ NomClient commence par T dans un
formulaire :

Dim strCritere as string


strCritere="NomClient LIKE " & chr(34) & "T*" & chr(34)
Me.Recordset.FindFirst strCritere

Si aucun enregistrement ne vérifie le critère, la propriété NoMatch du recordset est égale à True.

Exemple :

Dim strCritere as string


strCritere="NomClient LIKE " & chr(34) & "T*" & chr(34)
Me.Recordset.FindFirst strCritere
If Me.Recordset.NoMatch Then Msgbox "Aucun enregistrement n'a été trouvé"

- 72 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.3.3 - Mémoriser une position

Parfois, vous souhaitez naviguer dans le jeu d'enregistrements puis revenir à la position ou vous étiez avant. La
propriété Bookmark du Recrodset retourne un signet vers l'enregistrement. Il s'agit d'un tableau contenant des
données de type Byte.

Dim BytPosition() as Byte


BytPosition=oRecordset.Bookmark

Si par la suite, vous souhaitez revenir à cette position, il suffit d'affecter la valeur mémorisée à la propriété Bookmark.

oRecordset.Bookmark=BytPosition

5.4 - Manipulation des données

5.4.1 - Lire un enregistrement

Il est possible de lire les données de l'enregistrement courant à l'aide de la collection Fields. Cette collection
fonctionne comme les autres collection DAO et il est possible d'appeler chaque élément par son nom ou par sa
position dans la collection.

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("SELECT NumClient,NomClient FROM Client WHERE
NumClient=2",dbOpenDynaset)
Msgbox "Le nom du client est : " & Rst.Fields("NomClient").Value

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Ou

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("SELECT NumClient,NomClient FROM Client WHERE
NumClient=2",dbOpenDynaset)
Msgbox "Le nom du client est : " & Rst.Fields(1).Value

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

La propriété Value est le membre par défaut d'un objet Field. Vous pouvez donc utiliser :

Msgbox "Le nom du client est : " & Rst.Fields(1)

5.4.2 - Modifier un enregistrement

La modification d'un enregistrement peut se décomposer en 4 étapes :

- 73 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

L'exemple suivant fixe la date de toutes les commandes à aujoud'hui.

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("TblCommande",dbOpenTable)
While Not oRst.EOF
'Passe en mode modification
oRst.Edit
'Affecte la date actuelle
oRst.Fields("DateCommande").Value=Now()
'Met à Jour
oRst.Update
'Passe au suivant
oRst.MoveNext
Wend

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Notre exemple réalise un Update massif sur l'ensemble de la table commande. Toutefois ne
perdez pas de vue que dans bien des cas, une instruction SQL peut suffir et reste bien plus
performante qu'une boucle sur un jeu d'enregistrement.

CurrentDb.Execute "UPDATE TblCommande SET DateCommande=#" & Now() & "#"

5.4.3 - Ajouter un enregistrement

La méthode AddNew d'un Recordset permet d'ajouter un enregistrement. Aprés avoir assigné les valeurs aux
différents champ, vous devez faire appel à la méthode Update pour mettre à jour les données ou bien à la méthode
CancelUpdate pour annuler l'ajout. L'enregistrement nouvellement créé est placé à la fin du jeu d'enregistrement,
excepté dans le cas d'un Recordset de type Table où l'enregistrement est placé suivant l'ordre des index de la table.
Dans tout les cas, le Recordset revient à sa position d'origine avant l'appel de la méthode Update.

Exemple :

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database

- 74 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("TblProduit",dbOpenTable)
'Passe en mode Ajout
oRst.AddNew
'Affecte les différents champs
oRst.Fields("Reference").Value="SRS200"
oRst.Fields("Libelle").Value="Souris optique sans fil"
'Met à Jour
oRst.Update

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Vous devez affecter chacun des champs dont la propriété Required est égale à True, sans quoi une erreur sera levée.
De même vous devez respecter les contraintes d'index que vous avez définit sur la table. Ainsi, une clé primaire ne
peut contenir de doublons.

Dans le cas où un des champs est de type NuméroAuto, il est impossible d'affecter une valeur à ce champ. La
numérotation automatique est gérée par le moteur Jet. Toutefois, pour des raisons diverses et variées, vous pouvez
avoir le besoin de connaitre la nouvelle valeur du NuméroAuto créé. La valeur d'un tel champ est disponible avant
l'appel de la méthode Update. Prenons l'exemple d'une table client dont le champ NumClient est auto-incrémenté :

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Dim LngNouvelleValeur as Long
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("TblClient",dbOpenTable)
'Passe en mode Ajout
oRst.AddNew
'Affecte les différents champs
oRst.Fields("NomClient").Value="DUPONT"
oRst.Fields("PrenomClient").Value="Martin"
'Récupère le nouvel identifiant
LngNouvelleValeur=oRst.Fields("NumClient").Value
'Met à Jour
oRst.Update
'Affiche le numéro client de
'l'enregistrement nouvellement créé
Msgbox "Le client " & NouvelleValeur & " a été créé"

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Dans le cas d'un nombre important d'enregistrements à ajouter, un ordre SQL (INSERT)
envoyé à la méthode Execute de l'objet Database sera plus performant que de charger un
curseur contenant tous les enregistrements en mémoire.

Nous aurions donc avec l'exemple de la souris optique :

Dim StrChaineSQL As String


StrChaineSQL="INSERT INTO TblProduit (Reference,Libelle) VALUES
(" & chr(34) & "SRS200" & chr(34) & _
"," & chr(34) & "Souris optique sans fil" & chr(34) & ")"
CurrentDb.Execute StrChaineSQL

Toutefois, avec cette syntaxe il est impossible de retrouver la valeur d'un champ NuméroAuto lors de l'ajout d'un
enregistrement. Certains affirmeront qu'il suffit alors de récupérer la valeur maximum du champ concerné pour ne
sélectionner que le dernier enregistrement de la table, toutefois, cela ne garantit pas qu'il s'agisse de l'enregistrement

- 75 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

que vous venez d'ajouter. En effet, un autre utilisateur peut avoir ajouté un autre enregistrement immédiatement
après vous.

5.4.4 - Supprimer un enregistrement

La méthode Delete d'un objet Recordset de type Table ou Dynaset permet de supprimer l'enregistrement courant.
Aprés la suppression, l'enregistrement en cours n'est plus défini. Il est considéré comme supprimé et une erreur sera
levée si vous tentez d'y accéder. Il vous faut donc modifier la position courante du curseur à l'aide des méthodes
MoveNext ou MovePrevious.

L'exemple suivant supprimer toute les commandes du client numéro 13

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur
Set oRst=oDb.OpenRecordset("SELECT * FROM TblCommandes WHERE NumClient=13")
'Parcours le jeu d'enregistrement jusqu'à la fin
While Not oRst.EOF
'Supprime l'enregistrement
oRst.Delete
'Passe au suivant
oRst.MoveNext
Wend

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

5.4.5 - Compter les enregistrements

Il existe deux façons de procéder pour compter le nombre d'enregistrements d'un Recordset.
La première consiste à utiliser une requete utilisant l'instruction SQL Count et de lire cette valeur.

Ainsi, le nombre de clients habitant à Paris peut être déterminé par :

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim LngNbEnregistrement As Long
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant le nombre de clients résidant à Paris
Set oRst=oDb.OpenRecordset("SELECT Count(*) FROM TblCLients WHERE
Ville=" & Chr(34) & "Paris" & Chr(34))
'Lit le résultat
LngNbEnregistrement=oRst.Fields(0).Value

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Notons qu'une requête utilisant la fonction de regroupement Count retourne au moins un


enregistrement. De ce fait le curseur ne sera jamais vide à son ouverture, il n'est donc
pas obligatoire de tester l'existence d'enregistrement au sein du recordset avant de lire sa
première ligne.

- 76 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La seconde façon de procéder consiste à utiliser la propriété RecordCount du Recordset. Cette propriété renvoie
le nombre d'enregistrements d'un recordset de type Table ou le nombre d'enregistrements accédés lorsqu'il s'agit
d'un Recordset d'un autre type.

Ainsi, pour compter le nombre d'enregistrements d'un recordset de type table, nous pouvons utiliser :

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim LngNbEnregistrement As Long
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant tous les clients
Set oRst=oDb.OpenRecordset("TblCLients",dbOpenTable)
'Compte les enregistrements
LngNbEnregistrement=oRst.RecordCount

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

Dans le cas d'un autre type de Recordset, nous devons utiliser MoveLast afin d'atteindre le dernier enregistrement.
La propriété RecordCount retournera alors le nombre d'enregistrements de l'objet.

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim LngNbEnregistrement As Long
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant le nombre de clients résidant à Paris
Set oRst=oDb.OpenRecordset("SELECT * FROM TblCLients WHERE
Ville=" & Chr(34) & "Paris" & Chr(34),dbOpenDynaset)
'Atteint le dernier enregistrement
oRst.MoveLast
'Compte les enregistrements accédés (soit le total)
LngNbEnregistrement=oRst.RecordCount

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

5.4.6 - Filtrer les données

Il est possible d'ouvrir un nouvel objet Recordset depuis un premier Recordset tout en restreignant la selection des
données à l'aide d'un filtre. Pour cela, vous devez spécifier un filtre à la propriété Filter du premier Recordset puis
utiliser sa méthode OpenRecordset afin de retourner un nouveau jeu d'enregistrements filtré.

Le filtre à appliquer est une chaîne de caractères correspondant à la clause WHERE d'une requête (sans le WHERE).

Prenons comme exemple une table TblClients dont on ne sélectionne que les clients résidant à Paris.

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim oRstFiltre as DAO.Recordset
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant tous les clients
Set oRst=oDb.OpenRecordset("SELECT * FROM TblClients",dbOpenDynaset)
'Applique le filtre de sélection des habitants de Paris
oRst.Filter="Ville=" & Chr(34) & "Paris" & Chr(34)

- 77 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

'Ouvre un nouveau curseur


Set oRstFiltre=oRst.OpenRecordset
'***************************************
'ici, traitement sur le recordset filtre
'***************************************

'Libération des objets


oRst.Close
oRstFiltre.Close
oDb.Close
Set oRst=Nothing
Set oRstFiltre=Nothing
Set oDb=Nothing

Notons toutefois que dans la majorité des cas, il est plus rapide d'ouvrir un nouvel objet Recordset directement depuis
un objet Database en spécifiant une requête SQL complète à l'argument source.

Dim oDb as DAO.Database


Dim oRstFiltre as DAO.Recordset
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre un curseur retournant tous les clients résidant à Paris
Set oRstFiltre=oDb.OpenRecordset("SELECT * FROM TblClients WHERE
Ville=" & Chr(34) & "Paris" & Chr(34)",dbOpenDynaset)
'***************************************
'ici, traitement sur le recordset filtre
'***************************************

'Libération des objets


oRstFiltre.Close
oDb.Close
Set oRstFiltre=Nothing
Set oDb=Nothing

5.5 - Lecture par bloc

5.5.1 - Généralités

La lecture par bloc est un point trés important mais malheureusement fort oublié de DAO. En effet, la méthode
GetRows permet de retourner un tableau possédant un nombre donné d'enregistrements. Ces enregistrements sont
extraits à partir de la position courante du Recordset.

La syntaxe est la suivante :

Set varArray = recordset.GetRows (numrows)

VarArray est un tableau à deux dimensions recevant les données. Le premier indice correspond au champ et le
second au numéro de l'enregistrement.

Recordset est le recordset possédant les données.

Numrows correspond au nombre d'enregistrements à lire.

Dans le cas où le nombre d'enregistrements disponibles est inférieur au nombre à extraire, la méthode GetRows
retourne un tableau dont le nombre d'élément sera égal au nombre d'enregistrements disponibles. Il est donc conseillé
d'utiliser la méthode UBound pour connaitre la borne supérieure du tableau.

Après extraction, la position courante du Recordset est définit sur l'enregistrement suivant le dernier lu, vous pouvez
donc enchaîner une autre lecture vers l'avant. Dans le cas où vous souhaiteriez lire les X enregistrements précédents,

- 78 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

il vous faut atteindre le premier enregistrement à lire à l'aide de l'instruction Move. (Sans toutefois atteindre la position
BOF)

Lorsque le nombre de données à lire devient important, il s'avère que l'utilisation de la méthode
GetRows pour accéder aux données représente un gain de rapidité pouvant atteindre 20 %.

5.5.2 - Exemple

Cet exemple met en oeuvre l'utilisation de la méthode GetRows afin de réaliser un formulaire affichant les
enregistrements par blocs de 10. Les données proviennent de la table Clients de la base de données Comptoir.mdb
(Répertoire samples d'Access). De cette table, nous conserverons uniquement les champs suivants :

Code Client, Société, Ville, Pays

Notre formulaire ce compose ainsi :

Chaque zone de texte est indépendante et possède un nom égal à celui de sa colonne, concaténé avec le numéro
de l'enregistrement quelle affichera.

Nous utiliserons deux variables dans la portée du formulaire :

Dim oRstClient As DAO.Recordset 'Stocke le curseur


Dim intnbLus As Integer 'Stocke le nb d'enregistrements lus la dernière fois

Le principe est simple, à l'ouverture du formulaire, nous chargons le Recordset et affichons les 10 premiers
enregistrements.

Private Sub Form_Load()


Dim oDb As DAO.Database
'Instancie la base de données
Set oDb = CurrentDb
'Ouvre le recordset
Set oRstClient = oDb.OpenRecordset("Clients", dbOpenTable)
'Lit les 10 premiers
LectureVersLAvant
End Sub

Private Sub LectureVersLAvant()


On Error GoTo err
RemplirZoneTexte oRstClient.GetRows(10)
Exit Sub

- 79 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

err:
'Si on est sur le dernier enregistrement
'alors ne rien faire, sinon avertir
If err.Number <> 3021 Then
MsgBox "Une erreur est survenue pendant la lecture des données", vbCritical, "Erreur"
End If
End Sub

La procédure RemplirZonetexte boucle sur chaque ligne du tableau et affiche la valeur du champ dans la zone de
texte correspondante pour la ligne sélectionnée. Les autres lignes sont ensuites masquées.

Sub RemplirZoneTexte(Tableau As Variant)


Dim I As Integer
'Récupère le nombre d'enregistrements Lus
intnbLus = UBound(Tableau, 2) + 1
'affecte les valeurs aux zones de texte
For I = 0 To intnbLus - 1
'Affiche le code client
Controls("TCodeClient" & I + 1) = Tableau(0, I)
Controls("TCodeClient" & I + 1).Visible = True
'Affiche la societe
Controls("TSociete" & I + 1) = Tableau(1, I)
Controls("TSociete" & I + 1).Visible = True
'Affiche la ville
Controls("TVille" & I + 1) = Tableau(2, I)
Controls("TVille" & I + 1).Visible = True
'Affiche le pays
Controls("TPays" & I + 1) = Tableau(3, I)
Controls("TPays" & I + 1).Visible = True
Next I
'Masque les autres zones de textes
For I = intnbLus + 1 To 10
'Masque le code client
Controls("TCodeClient" & I).Visible = False
'Masque la societe
Controls("TSociete" & I).Visible = False
'Masque la ville
Controls("TVille" & I).Visible = False
'Masque le pays
Controls("TPays" & I).Visible = False
Next I
End Sub

Les déplacements vers l'arrière sont plus complexes étant donné que si nous avons lu les 20 premiers, la position
courante du Recordset est définie à 21 et les enregistrements 11 à 20 sont affichés. Or, la plage souhaitée est celle
des lignes 1 à 10. Nous devons donc reculer du nombre d'enregistrements lu la précédente fois et nous positionner
10 enregistrements en arrière pour commencer la lecture. Toutefois, il se peut que ce nombre de sauts excède le
nombre d'enregistrements disponibles vers l'arrière. Le plus simple est alors d'intercepter l'erreur levée (3021) afin
de ne pas stopper l'éxecution et de se positionner sur le premier enregistrement du curseur.

Private Sub LectureVersLArriere()


On Error GoTo err
'Recule du nombre d'enregistrements nécessaire
oRstClient.Move -1 * intnbLus - 10
RemplirZoneTexte oRstClient.GetRows(10)
Exit Sub
err:
Select Case err.Number
'Si on a trop reculé alors, se positionner sur le premier
Case 3021: oRstClient.MoveFirst
'Sinon, Avertir
Case Else: MsgBox "Une erreur est survenue pendant la lecture des
données", vbCritical, "Erreur"
End Select
End Sub

Vous pouvez aisément obtenir une interface ressemblant à ceci :

- 80 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Vous pouvez télecharger le fichier exemple ici.

5.6 - Liste des propriétés

Cette section récapitule l'ensemble des propriétés appliquables au Recordset DAO.

5.6.1 - AbsolutePosition

Type : Long

La propriété AbsolutePosition correspond à un numéro représentant la position courante dans le Recordset. Le


premier enregistrement possède la position zéro. En affectant à cette propriété une valeur comprise entre 0 et le
nombre d'enregistrements - 1, le curseur va se déplacer de telle sorte à atteindre l'enregistrement spécifié. Toutefois,
privilégiez l'utilisation de la propriété Bookmark pour mémoriser une position et y retourner. Dans le cas où le jeu
d'enregistrements est vide, cette propriété renvoie -1.

Elle ne s'applique pas aux Recorset de type Table (dbOpenTable) ni En avant seulement (dbOpenForwardOnly).

5.6.2 - BOF

Lecture seule.

Type : Boolean

Lorsque la propriété BOF d'un Recordset est égale à True, cela signifie que la position courante du curseur est
définie avant le premier enregistrement.

Cette propriété s'applique à tous les types de Recordset.

5.6.3 - Bookmark

Type : Variant

- 81 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La propriété Bookmark correspond à un signet identifiant de manière unique l'enregistrement au sein du Recordset.
Cette propriété est à utiliser pour mémoriser une position ou se déplacer dans le jeu. Un exemple est disponible dans
la section intitulée : 5.3.3 Mémoriser une position.

Cette propriété ne s'applique pas aux Recordset de type En avant seulement (dbOpenForwardOnly).

Les signets ne sont pas utilisables lorsque la propriété Bookmarkable est égale à False.

5.6.4 - Bookmarkable

Lecture seule.

Type : Variant

La propriété Bookmarkable renvoie True lorsque le curseur accepte les signets (Ce qui est automatiquement le cas
pour une base de données Access). Si vous travailler en liaison avec certains SGBD, il est nécessaire de tester cette
valeur avant d'utiliser la propriété Bookmark.

Cette propriété ne s'applique pas Recordset de type En avant seulement (dbOpenForwardOnly).

5.6.5 - CacheSize

Type : Long

La propriété CacheSize correspond au nombre d'enregistrements stockés en mémoire cache. Sa valeur doit être
comprise entre 5 et 1200 sans dépasser la quantité de mémoire disponible. La valeur 0 désactive l'utilisation de la
mémoire cache.

Cette propriété est utilisable uniquement avec les Recordset de type dynamique ou instantané et lorsque les données
proviennent d'une source ODBC.

5.6.6 - CacheStart

Type : String

La valeur de la propriété CacheStart correspond au signet du premier enregistrement de l'objet Recordset à placer
en mémoire cache. Vous pouvez utiliser le signet de tout enregistrement pour définir la propriété CacheStart.

Cette propriété est utilisable uniquement avec les Recordset de type dynamique ou instantané et lorsque les données
proviennent d'une source ODBC.

Cette propriété étant très bien documentée dans l'aide, je vous renvoie vers cette dernière
pour de plus amples détails

5.6.7 - Connection

Lecture seule.

Type : Connection

- 82 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Dans un environnement ODBC Direct, la propriété Connection renvoie l'objet Connection depuis lequel le Recordset
a été ouvert.

Cette propriété n'est pas disponible pour les curseurs de type Table.

5.6.8 - DataCreated

Lecture seule.

Type : Date

Pour un Recordset de type Table, cette propriété retourne la date de création de la table.

5.6.9 - EditMode

Lecture seule.

Type : Long

La propriété EditMode renvoie une valeur indiquant l'état de modification de l'enregistrement courant.

Il s'agit d'une des constantes suivantes :

Constante Signification
dbEditNone Aucune opération de modification
en cours.
DbEditInProgress La méthode Edit a été invoquée
et l'enregistrement actuel est
dans le tampon de copie. (La
méthode Update n'a pas encore
été appelée)
dbEditAdd La méthode AddNew a été
invoquée et l'enregistrement actuel
dans le tampon de copie est un
nouvel enregistrement qui n'a pas
été enregistré dans la base de
données.

Cette propriété s'applique à tous les types de Recordset.

Ainsi dans un code complexe, il est possible de connaitre le statut de votre Recordset. Ainsi, pour savoir si nous
sommes sur le point de valider l'ajout d'un enregistrement, nous devrons évaluer :

If oRecordset.EditMode=dbEditAdd then Msgbox "Un ajout est en cours"

Toutefois, si votre code est bien structuré, vous devez être capable de connaitre le statut de
votre curseur à chaque ligne de code. L'utilisation de cette propriété doit donc se limiter a des
cas extrèmes, ou pour debugguer un code existant.

5.6.10 - EOF

Lecture seule.

- 83 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Type : Boolean

Lorsque la propriété EOF d'un Recordset est égale à True, cela signifie que la position courante du curseur est définie
après le dernier enregistrement.

Cette propriété s'applique à tous les types de Recordset.

5.6.11 - Fields

Lecture seule.

Type : Collection

Cette collection regroupe l'ensemble des champs du Recordset. De plus amples informations sur les objets Field
sont disponibles dans la section 4.4 L'objet Field.

Cette propriété s'applique à tous les types de Recordset.

5.6.12 - Filter

Type : String

La propriété Filter permet de spécifier un filtre qui sera appliqué lors de l'appel de la méthode OpenRecordset. Il s'agit
de la clause WHERE d'une requête SQL (sans le mot clé WHERE). De plus amples informations sont disponibles
dans la section 5.4.6 Filtrer les données.

5.6.13 - Index

Type : String

La propriété Index correspond au nom de l'index utilisé dans un Recordset pour rechercher les enregistrements dans
un Recordset de type Table exclusivement.

5.6.14 - LastModified

Lecture seule.

Type : Variant

Cette propriété retourne un signet pointant vers le dernier enregistrement modifié ou ajouté au jeu d'enregistrements.
Vous pouvez atteindre ensuite cet enregistrement en affectant ce signet à la propriété Bookmark.

Exemple :

With oRecordset
.Bookmark=.LastModified
End With

Cette propriété s'applique à tous les types de Recordset hormis le type En avant seulement (dbOpenForwardOnly).

- 84 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.6.15 - LastUpdated

Lecture seule.

Type : Date

La propriété LastUpdated retourne la date à laquelle la table d'un Recordset a été modifiée pour la dernière fois.

Elle n'est appliquable qu'aux objets Recordset de type Table.

5.6.16 - LockEdits

Type : Boolean

Cette propriété définit le type de verrouillage utilisé par le Recordset. Lorsque'elle est égale à True (Valeur par défaut),
la page est verrouillée dés l'appel de la méthode Edit. Dans le cas contraire (False), la page d'enregistrements est
verrouillée uniquement lors de l'appel de la méthode Update.

5.6.17 - Name

Type : String

La propriété Name représente le nom de l'objet. Cette propriété est inutile dans l'utilisation des Recordset étant donné
que ceux-ci ne sont pas nommés. Cette propriété est en fait égale aux 256 premiers caractères de l'argument Source
utilisé lors de la méthode Database.OpenRecordset.

5.6.18 - NoMatch

Lecture seule.

Type : Boolean

La propriété NoMatch est égale à True lorsque l'une des méthodes Find.... n'a pas trouvé d'enregistrement vérifiant
le critère.

5.6.19 - PercentPosition

Type : Single

La propriété PercentPosition correspond à une valeur 0 à 100 indiquant la position approximative dans le Recordset.
Bien que vous puissiez la définir pour vous déplacer, elle est de faible intérêt en écriture car approximative.

Elle n'est appliquables qu'aux Recordset de type Table, Dynaset et instantané.

Vous devez avoir atteint le dernier enregistrement afin que sa valeur soit significative par
rapport à la globalité du Recordset. Sinon, cette propriété ne se base pas sur le nombre
d'enregistrements total mais parcourus. Pour atteindre le dernier enregistrement, vous pouvez
utiliser la méthode MoveLast.

- 85 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.6.20 - Properties

Lecture seule.

Type : Collection

Cette collection regroupe l'ensemble des propriétés du Recordset, comme spécifié dans la section 4.2 Propriétés
spécifiques.

5.6.21 - RecordCount

Lecture seule.

Type : Long

La propriété RecordCount retourne le nombre d'enregistrements total d'un Recordset de type Table ou le nombre
d'enregistrements auxquels vous avez eu accès dans un Recordset d'un autre type.

Elle n'est pas appliquable aux Recordset de type En avant seulement (dbOpenForwardOnly)

De plus amples informations sur cette propriété sont disponible dans la section intitulée 5.4.5
Compter les enregistrements

5.6.22 - Restartable

Lecture seule.

Type : Long

Lorsque cette propriété est égale à True, cela signifie qu'il est possible de mettre les données à jour en réexécutant la
requête à l'aide de Requery. En d'autres thermes, elle indique si la méthode Requery est supportée par le Recordset.
Dans le cas contraire, vous devrez réouvrir le curseur à l'aide de la méthode OpenRecordset de l'objet Database
ou QueryDef utilisé pour y puiser les données.

Elle est utilisable sur tout type de Recordset, toutefois, elle renvoie toujours False pour un Recordset de type Table.

5.6.23 - Sort

Type : String

La propriété Sort permet de spécifier un ordre de tri qui sera appliqué lors de l'appel de la méthode OpenRecordset.
Il s'agit de la clause ORDER BY d'une requête SQL (sans le mot clé ORDER BY). Ainsi, il est possible d'instancier
un nouvel objet Recordset trié depuis un autre :

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim oRstTrie as DAO.Recordset
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant tous les clients
Set oRst=oDb.OpenRecordset("SELECT Ville,NomClient,PrenomClient FROM TblClients" _
,dbOpenDynaset)
'Tri sur la ville et le nom du client
oRst.Sort="Ville,NomClient"

- 86 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

'Ouvre un nouveau curseur


Set oRstTrie=oRst.OpenRecordset
'*************************************
'ici, traitement sur le recordset trié
'*************************************

'Libération des objets


oRst.Close
oRstTrie.Close
oDb.Close
Set oRst=Nothing
Set oRstTrie=Nothing
Set oDb=Nothing

Cette propriété ne s'applique qu'aux Recordset de type Dynaset et Instantané.

Notons toutefois que dans la majorité des cas, il est plus rapide d'ouvrir un nouvel objet Recordset directement depuis
un objet Database en spécifiant une requête SQL complète à l'argument source.

5.6.24 - StillExecuting

Lecture seule.

Type : Boolean

Dans un environnement ODBC Direct, la propriété StillExecuting renvoie True si la requête d'ouverture du Recordset
est encore en cours d'exécution.

5.6.25 - Transactions

Lecture seule.

Type : Boolean

Lorsque la propriété Transactions d'un objet Recordset est égale à True, cela signifie que vous pouvez utiliser les
transactions sur ce Recordset. Pour démarrer une transaction, utilisez la méthode BeginTrans de l'objet Workspace
ayant créer le curseur. Invoquez ensuite la méthode CommitTrans pour mettre à jour les données ou Rollback pour
annuler.

Exemple :

Dim oRst as DAO.Recordset


Dim oDb as DAO.Database
Set oDb=CurrentDb
Set oRst=oDb.OpenRecordset("TblCommande",dbOpenTable)
'Demarre la transaction
DBEngine.Workspaces(0).BeginTrans
While Not oRst.EOF
'Passe en mode modification
oRst.Edit
'Affecte la date actuelle
oRst.Fields("DateCommande").Value=Now()
'Met à Jour
oRst.Update
'Passe au suivant
oRst.MoveNext
Wend
'Demande confirmation
If Msgbox("Etes vous sûr de vouloir continuer")=VbYes
'Si oui, mettre à jour
DBEngine.Workspaces(0).CommitTrans

- 87 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

Else
'Sinon, annuler
DBEngine.Workspaces(0).Rollback
End if

'Libération des objets


oRst.Close
oDb.Close
Set oRst=Nothing
Set oDb=Nothing

5.6.26 - Type

Lecture seule.

Type : Long

La propriété Type renvoie le type de curseur utilisé conformément aux informations spécifiées dans la section : 5.2
Les différents types de Recordset.

5.6.27 - Updatable

Lecture seule.

Type : Boolean

Lorsque la propriété Updatable est égale à False, il est impossible de mettre à jour les données du Recordset.

5.6.28 - UpdateOptions

Type : Long

La propriété UpdateOptions correspond au mode de création d'une clause WHERE dans une requête UPDATE lors
d'une mise à jour par lot dans un environement ODBC Direct. Dans certains cas, il est ainsi possible de contourner un
déclencheur Update du SGBD distant en forçant le moteur de base de données à remplacer une requête UPDATE par
une requête DELETE suivie d'une requête INSERT. Toutefois, cette propriété ne sera pas d'avantage documentée
dans ce document et je vous propose de consulter l'aide Access pour plus de détails.

5.6.29 - ValidationRule

Lecture seule.

Type : String

La propriété ValidationRule définit la règle de validation qui sera utilisée pour valider les données lors de l'appel
de la méthode Update.

5.6.30 - ValidationText

Lecture seule.

Type : String

- 88 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

La propriété ValidationText correspond au message qui sera affiché lors d'une mise à jour si les données ne vérifie
pas la règle spécifiée dans ValidationRule.

5.7 - Liste des méthodes

Voici un récapitulatif des méthodes de la classe Recordset.

5.7.1 - AddNew

La méthode AddNew permet d'ajouter un nouvel enregistrement au Recordset. Elle est illustrée dans la section 5.4.3
Ajouter un enregistrement.

Exemple :

With oRecordset
.AddNew
.Fields("Nom")="Toto"
.Update
End With

5.7.2 - CancelUpdate

La méthode CancelUpdate est à invoquer après les méthodes Edit ou Addnew pour annuler la mise à jour. Dans
le cas d'un ajout, la position du Recordset est redéfinie à ce qu'elle était avant l'appel de AddNew.

Exemple :

With oRecordset
.AddNew
.Fields("Nom")="Toto"
'Annule l'insertion
.CancelUpdate
End With

5.7.3 - Clone

La méthode Clone retourne un Recordset identique à celui sur lequel elle est appliquée. Le recordset cloné ne
possède pas d'enregistrement courant vous devez alors vous positionner sur l'enregistrement de votre choix. Notons
que les signets sont interchangeables entre chaque Recordset. Ainsi, il est possible de positionner le clone au même
endroit que la source avec :

Dim oRst as DAO.Recordset


Dim oRstClone as DAO.Recordset
'****************************
'ici Code d'ouverture de Rst
'****************************

'Copie du recordset
Set oRstClone=oRst.Clone
'Définit le même enregistrement courant
oRstClone.Bookmark=oRst.Bookmark

Une fois oRst cloné, vous pouvez le fermer sans aucune incidence sur RstClone.

Cette méthode n'est pas compatible avec les objets Recordset de type En avant seulement (dbOpenForwardOnly)

- 89 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.7.4 - Close

La méthode Close ferme le Recordset. Toutefois, celle-ci ne libère pas la variable objet de la mémoire. Pour la libérer,
vous devez attendre la fin de la procédure et la destruction de la variable ou affecter Nothing à cette dernière.

Exemple :

oRecordset.Close
Set oRecordset=Nothing

5.7.5 - CreateQueryDef

La méthode CreateQueryDef copie l'objet QueryDef utilisé pour ouvrir le Recordset. Celui-ci doit impérativement avoir
été ouvert à l'aide de la méthode OpenRecordset d'un objet QueryDef.

Syntaxe :

Set querydef = oRecordset.CopyQueryDef

Cette méthode ne s'applique pas aux Recordset de type Table (Puisqu'ils ne sont pas ouverts depuis un objet
QueryDef).

5.7.6 - Delete

La méthode Delete supprime un enregistrement du Recordset. Elle est illustrée dans la section 5.4.4 Supprimer un
enregistrement. Une fois l'enregistrement supprimé, la position du Recordset n'est plus valide, vous devez donc
atteindre un autre enregistrement.

Exemple :

With oRecordset
.Delete
Msgbox "Suppression réussie"
.MoveNext
End With

5.7.7 - Edit

La méthode Edit copie l'enregistrement dans le tampon et passe le Recordset en mode acEditInProgress afin que
vous puissiez modifier les données.

Un exemple d'utilisation est disponible dans la section : 5.4.2 Modifier un enregistrement.

5.7.8 - FindFirst, FindLast, FindNext, FindPrevious

Ces méthodes sont à utiliser pour trouver des enregistrements au sein du jeu. Une section complète leur est dédiée :
5.3.2 Trouver un enregistrement.

Elles ne sont disponibles que pour les Recordset de type Dynaset et Instantané.

- 90 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

5.7.9 - GetRows

La méthode GetRows lit et retourne dans un tableau à deux dimensions X enregistrements à partir de l'enregistrement
courant (X étant un nombre positif spécifié dans le seul argument de GetRows). Un exemple de formulaire lisant les
données par bloc est disponible dans la section 5.5 Lecture par bloc.

5.7.10 - Move, MoveFirst, MoveLast, MoveNext, MovePrevious

Ces méthodes sont à utiliser pour se déplacer au sein du jeu d'enregistrements comme indiqué dans la section 5.3.1
Se déplacer dans un Recordset.

Elles sont disponibles pour tout type de Recordset hormis les méthodes MoveFirst et MovePrevious qui opèrent
des déplacements vers l'arrière et qui sont donc incompatibles avec les curseurs de type En avant seulement
(dbOpenForwardOnly).

5.7.11 - OpenRecordset

La méthode OpenRecordset instancie un nouvel objet Recordset possédant la même source de données que le
Recordset original mais en tenant compte des éventuelles propriétés Filter et Sort.

Voici un exemple d'utilisation appliquant un filtre :

Dim oDb as DAO.Database


Dim oRst as DAO.Recordset
Dim oRstFiltre as DAO.Recordset
'Instancie la base de données
Set oDb=CurrentDb
'Ouvre le curseur retournant tous les clients
Set oRst=oDb.OpenRecordset("SELECT * FROM TblClients",dbOpenDynaset)
'Applique le filtre de sélection des habitants de Paris
oRst.Filter="Ville=" & Chr(34) & "Paris" & Chr(34)
'Ouvre un nouveau curseur
Set oRstFiltre=oRst.OpenRecordset
'***************************************
'ici, traitement sur le recordset filtre
'***************************************

Cette méthode n'est pas disponible pour les Recordset de type En avant seulement (dbOpenForwardOnly).

5.7.12 - Requery

La méthode Requery met à jour les données contenues dans un objet Recordset en exécutant de nouveau la requête
sur laquelle l'objet est fondé.

Notons que certains SGBD ne supportent pas l'utilisation de la méthode Requery. Dans
ce cas, vous pouvez interroger la propriété Restartable afin de connaître si Requery est
applicable.

5.7.13 - Update

La méthode Update permet d'enregistrer les données depuis le tampon de copie vers la base de données. Cette
méthode est à invoquer aprés l'affectation des différents champs suite à un appel à la méthode Edit ou AddNew.
Pour ne pas enregistrer les données, vous devez utiliser la méthode CancelUpdate.

Pour de plus amples informations, vous pouvez consulter la section 5.4.2 Modifier un enregistrement.

- 91 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/
Définition et manipulation de données avec DAO par Christophe WARIN

6 - Conclusion

Tout au long de ce document, vous avez pu constater que DAO offre de multiples possibilités quant à la manipulation
d'une base de données. Toutefois, chaque action doit être réfléchie et en aucun cas vous ne devez perdre de vue
que la cohérence et l'intégrité des données sont primordiales. A aucun moment vous ne devez prendre le risque de
perdre des enregistrements.

Depuis quelques années, DAO tente à être remplacé par le modèle objet ADO (ActiveX Data Object). Cependant, il
reste un moyen simple d'accéder à votre base de données dans du code VBA. La hiérarchie du modèle DAO étant
très proche de la fenêtre base de données sous Access, son approche est très intuitive et ne nécessite pas de réelles
connaissances dans le monde de la programmation orientée objet.

Je tiens à remercier l'ensemble de l'équipe Access pour ses précieux conseils et sa relecture ainsi que MED ALAOUI
SOSSE pour sa traduction en arabe. Je reste à votre disposition par MP pour d'éventuelles remarques.

- 92 -
Copyright ® 2005 WARIN Christophe. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation
expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.
http://warin.developpez.com/access/dao/