Stockez les images statiques de vos formulaires et états Access hors de la base de données

Claude Leloup

Ce tutoriel décrit UNE méthode pour garder, hors de la base de données, les images qui garnissent un formulaire ou un état.

Commentez

- Titre : Stockez les images statiques de vos formulaires et états Access hors de la base de données

- Auteur : Claude Leloup

- Parution : 20 février 2012

- Mise à jour : 8 mars 2019

- Public visé :

- Licence : Copyright ® 2011 Claude Leloup. 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.

Sommaire

- I. Avant-propos

- II. L'idée

- II-A. De quelles images parle-t-on ?

- II-B. Les propriétés que nous allons utiliser

- II-B-1. Propriété Image (Picture)

- II-B-2. Propriété Type image (PictureType)

- II-B-3. Propriété Remarque (Tag)

- II-C. Déclenchement du processus

- III. La procédure Sub AmnImages()

- III-A. YAKA

- III-B. Actions en cas d'erreur

- III-C. Le code de la procédure

- III-C-1. Une procédure dans un module de classe indépendant des formulaires ou états

- III-C-2. Construisons le code pas à pas

- III-C-3. Gestion des erreurs

- III-C-4. Version finale

- IV. Encore une suggestion

- V. Téléchargez une base de données avec un exemple

- VI. Remerciements

I - Avant-propos

Access permet de stocker des images directement dans la base de données. Que ce soit en tant que valeur du champ OLE d'une table ou en tant que propriété Image (Picture) d'un formulaire, d'un état ou d'un contrôle de l'un de ces deux objets.

Toutefois, cela peut très vite alourdir la base de données si l'on a un grand nombre d'images en jeu.

cafeine, dans son tutoriel Gestion de photos par formulaire, a montré comment externaliser les images : ce sont les adresses qui sont stockées dans la table et non les images elles-mêmes.

Cafeine s'est concentré sur l'aspect dynamique du traitement : la photo affichée varie au fur et à mesure que le formulaire parcourt les enregistrements de la table qui constitue sa source.

Ici, nous allons aborder le côté statique : l'affichage des images fixes qui décorent les formulaires et les états de la base de données.

Certes le problème du poids de ces images dans la base de données se pose d'une manière moins aiguë que lorsqu'il s'agit de tables contenant des milliers d'enregistrements avec des champs OLE. Cependant pensez à une base avec quelques dizaines de formulaires et autant d'états, tous décorés du logo de l'entreprise : ça commence à peser...

II - L'idée

Exactement la même que celle suivie par Cafeine : c'est l'adresse de l'image qui se trouve dans la base. Le programme va chercher l'image là où elle est stockée physiquement et seulement pour le temps nécessaire à son utilisation.

II-A - De quelles images parle-t-on ?

Celles que l'on affiche sur un contrôle image, un bouton de commande, un bouton bascule, un onglet, ou comme image de fond d'un formulaire ou d'un état.

II-B - Les propriétés que nous allons utiliser

Il s'avère que tous les objets (formulaire ou état) et les différents contrôles qui peuvent contenir une image ont tous trois propriétés en commun.

II-B-1 - Propriété Image (Picture)

C'est, en principe, ici que l'on spécifierait le chemin d'une image. Plusieurs types de fichiers sont autorisés, dépendant des filtres d'importation dont vous disposez. Toutefois, les boutons de commande ou de bascule ne peuvent comporter que des images bitmap.

Dans notre cas, nous n'affecterons aucune valeur à cette propriété lors de la construction de l'état ou du formulaire. « (aucune) » apparaîtra en regard de la propriété.

II-B-2 - Propriété Type image (PictureType)

Ici, lorsqu'une image a été affectée à la propriété précédente on a le choix entre « Intégré » et « Attaché ».

Si l'on choisit « Intégré », l'image est incorporée dans l'objet et fait partie du fichier de base de données. La taille de la base de données s'accroît alors d'autant d'octets que le fichier image (parfois plus).

Lorsque cette propriété est définie sur « Attaché », la taille de la base de données n'augmente pas, car Access enregistre seulement un pointeur vers l'emplacement.

Lors de la construction de l'état ou du formulaire, nous fixerons la valeur de cette propriété à « Attaché ».

II-B-3 - Propriété Remarque (Tag)

Voici une propriété rarement utilisée et pourtant bien pratique ! C'est un pense-bête, vous pouvez y inscrire ce que vous voulez avec un maximum de 2048 caractères. Contrairement aux autres propriétés, le paramétrage de celle-ci n'affecte pas les attributs d'un objet.

Nous allons nous en servir pour y stocker le nom du fichier image que nous voudrons affecter à ce contrôle en temps utile.

On pourrait y inscrire le chemin complet. Toutefois, nous avons opté pour le rassemblement de toutes les images de notre base de données dans un même répertoire que nous logerons dans le même dossier que la base.

Cette méthode a deux avantages :

- si on connaît le nom du fichier de l'image, on peut construire de chemin avec l'instruction :

CurrentProject.Path & "\Images\" & "le contenu de la propriété Remarque"

- quel que soit le dossier où se situent la base et le répertoire : sur votre PC, une clé USB...

II-C - Déclenchement du processus

Dans l'événement Sur ouverture de l'état ou du formulaire, nous explorerons les propriétés de l'objet et de ses contrôles et chaque fois que nous constaterons que nous avons simultanément :

Nom de la propriété

Valeur de la propriété

Picture (Image)

(aucune)

PictureType (Type image)

1

Tag (Remarque)

De la forme : nom.extension

Nous déclencherons un processus pour modifier temporairement la propriété Picture : nous remplacerons « (aucune) » par le chemin de l'image construit au départ du contenu de la propriété Tag.

Ainsi, si la base est logée dans le répertoire c:\MesBases et que la propriété Tag contient « Fond.jpg », la propriété Picture deviendra : c:\MesBases\Images\Fond.jpg le temps que le formulaire ou l'état concerné restera ouvert.

Ce processus est codé dans la procédure Public Sub AmnImages(). Celle-ci sera appelée lors de l'ouverture de l'état ou du formulaire.

III - La procédure Sub AmnImages()

III-A - YAKA

Dans le meilleur des mondes, elle se présenterait comme ceci pour un formulaire :

1. Public Sub AmnImages()

2. Dim ctrl As Control

3. For Each ctrl In LeFormulaire.Controls

4. If IsNull(Ctrl.PictureData) And ctrl.PictureType = 1 And ctrl.Tag Like "*.*" Then

5. ctrl.Picture = CurrentProject.Path & "\Images\" & ctrl.Tag

6. End If

7. Next ctrl

8. End Sub

À la ligne 3, on lance une boucle dans la collection des contrôles de l'objet.

À la ligne 4, on vérifie si les trois propriétés ont :
Picture = (aucune) ;
PictureType = 1 ;
Tag = la syntaxe d'un fichier (nom.extension).

À la ligne 5, si les conditions sont remplies, on construit le chemin de l'image et on l'affecte à la propriété Picture.

Attention : cela, c'est sans compter que :

-tous les contrôles n'ont pas ces trois propriétés ;
-le format de l'image proposée est peut-être incompatible avec ce que Access attend ;
-le lien construit pour trouver le fichier de l'image est peut-être mort.

Dans tous ces cas, une erreur sera relevée.

III-B - Actions en cas d'erreur

Type d'erreur

Numéro

Action correctrice

Le contrôle n'a pas
les trois propriétés

438

Passer au suivant.

Le format est inadéquat

2114

Signaler à l'utilisateur (message ad hoc).
S'il s'agit de l'image de fond de l'objet, laisser « (aucune) ».
S'il s'agit de l'image d'un contrôle, assigner une image par défaut.
Dans les deux cas, passer au contrôle suivant.

Le format est adéquat, mais
l'image est absente

2220

Signaler à l'utilisateur (message ad hoc).
S'il s'agit de l'image de fond de l'objet, laisser « (aucune) ».
S'il s'agit de l'image d'un contrôle, assigner une image par défaut.
Dans les deux cas, passer au contrôle suivant.

Dans le processus de gestion de la survenance éventuelle des erreurs 2114 ou 2220, il conviendra de distinguer si l'on traite l'image de fond de l'objet ou l'image d'un de ses contrôles.

III-C - Le code de la procédure

III-C-1 - Une procédure dans un module de classe indépendant des formulaires ou états

Ceci a pour but d'éviter d'inclure un code semblable pour chaque objet. Ce qui facilite la portabilité (puisque plus générique) et la maintenance éventuelle.

Le code de la procédure sera donc logé dans un module.

L'objet y fera appel dans son événement Sur ouverture :

Private Sub Form_Open(Cancel As Integer)
Call AmnImages
End Sub

Lorsqu'elle se déclenchera, cette procédure doit être capable de déterminer quel est l'objet qui l'appelle. C'est en effet ce formulaire ou cet état spécifique qu'il faut toiletter.

Access dispose de la propriété CodeContextObject pour répondre à ce besoin. Elle permet de déterminer dans quel objet du code Visual Basic est en cours d'exécution.

Quand la routine AmnImages() s'exécute : CodeContextObject représente l'objet qui a déclenché l'exécution. Il hérite alors de toutes les propriétés de ce dernier.

Par exemple, si le formulaire fImagesExternes appelle AmnImages(), nous aurons :

CodeContextObject.name égal à « fImagesExternes » ;
CodeContextObject.Controls représentera la collection des contrôles de fImagesExternes ;
CodeContextObject.picture donnera le chemin de l'image de fond.

III-C-2 - Construisons le code pas à pas

Il faut d'abord déclarer les variables et donner l'étiquette où l'on gère les erreurs :

Dim Ctrl As Control         ' pour boucler dans la collection des contrôles
Dim bFond As Boolean    ' nous permettra de savoir si l'on s'occupe ou non de l'image de fond
On Error GoTo GestionErreur

On s'occupe ensuite de l'image de fond de l'objet.

On positionne le flag bFond à True.

Comme il s'agit d'atteindre des propriétés de l'objet (et non d'un contrôle), on utilise les propriétés de CodeContextObject.

bFond = True
If IsNull(CodeContextObject.PictureData) And CodeContextObject.PictureType = 1 And CodeContextObject.Tag Like "*.*" Then
CodeContextObject.Picture = CurrentProject.Path & "\Images\" & CodeContextObject.Tag
End If

Si les trois conditions sont remplies (Image = (aucune) ; Type image = Attaché ; Remarque = la structure d'un nom de fichier), on construit le chemin complet de l'image et on l'affecte à la propriété Image de l'objet.

Deux causes d'erreur : le format de l'image est inadéquat (2214) ou l'image est introuvable (2220). Nous expliquerons plus loin comme réagir.

Ensuite, on positionne le flag bFond à False : on va parcourir la collection de contrôles de l'objet :

ImgControles:            'cette étiquette sera nécessaire pour le traitement des erreurs
bFond = False
For Each Ctrl In CodeContextObject.Controls
[...]
Next Ctrl

et pour chaque contrôle, si les trois propriétés ont la valeur ad hoc, on affecte le chemin de l'image :

If Ctrl.Picture = "(aucune)" And Ctrl.PictureType = 1 And Ctrl.Tag Like "*.*" Then
Ctrl.Picture = CurrentProject.Path & "\Images\" & Ctrl.Tag
End If

Trois erreurs sont possibles : le contrôle examiné n'a pas ce type de propriété (438) ; le format de l'image est inadéquat (2214) ou l'image est introuvable (2220).

III-C-3 - Gestion des erreurs

On passe en revue les cas possibles :

Select Case err.Number
[...]
End Select

438 : le contrôle actuellement examiné n'a pas l'une des propriétés qui nous intéressent.

Rien de spécial, on passe au suivant :

Case 438
Resume Next

2114 : le format de l'image est inadéquat. Il faut distinguer si cette erreur survient

- soit lors du traitement de l'image de fond : il faut alors prévenir l'utilisateur et continuer avec le processus relatif aux contrôles. Il n'y aura pas d'image de fond ;

Case 2114
If bFond = True Then
MsgBox "(2114) L'image de fond de '" & CodeContextObject.Name & "', c'est-à-dire : '" _
& CodeContextObject.Tag & "' est d'un format invalide."
Resume ImgControles

- soit lors du traitement de l'image d'un contrôle : il faut alors prévenir l'utilisateur, affecter une image par défaut et passer au contrôle suivant :

MsgBox "(2114) L'image '" & Ctrl.Tag & "' est d'un format invalide pour le contrôle '" _
& Ctrl.Name & "' de l'objet '" & CodeContextObject.Name & "'."
Ctrl.Picture = CurrentProject.Path & "\Images\Default.bmp"
Resume Next

Avant de vérifier si le format est adéquat, Access voit d'abord si le fichier existe.

Donc une image d'un format inadéquat et manquante relèvera une erreur 2220, et non 2114.

2220 : l'image est absente. C'est exactement la même réaction que celle de l'erreur 2214, aux messages d'erreurs près.

Case 2220
If bFond = True Then         'C'est l'image de fond
MsgBox "(2220) L'image de fond de '" & CodeContextObject.Name & "', c'est-à-dire : '" _
& CodeContextObject.Tag & "' est absente."
Resume ImgControles
Else
MsgBox "(2220) L'image '" & Ctrl.Tag & "' est absente pour le contrôle '" _
& Ctrl.Name & "' de l'objet '" & CodeContextObject.Name & "'."
Ctrl.Picture = CurrentProject.Path & "\Images\Default.bmp"
Resume Next
End If

Enfin, on peut utiliser ceci pour les erreurs non prévues :

Case Else
MsgBox "Erreur inattendue dans AmnImages" & vbLf _
& err.Number & " : " & err.Description, vbCritical

III-C-4 - Version finale

Option Compare Database
Option Explicit

Public Sub AmnImages()
Dim Ctrl As Control
Dim bFond As Boolean
On Error GoTo GestionErreur
'Image de fond
bFond = True
If IsNull(CodeContextObject.PictureData) And CodeContextObject.PictureType = 1 And CodeContextObject.Tag Like "*.*" Then
CodeContextObject.Picture = CurrentProject.Path & "\Images\" & CodeContextObject.Tag
End If
ImgControles:
'Image des contrôles
bFond = False
For Each Ctrl In CodeContextObject.Controls
If IsNull(Ctrl.PictureData) And Ctrl.PictureType = 1 And Ctrl.Tag Like "*.*" Then
Ctrl.Picture = CurrentProject.Path & "\Images\" & Ctrl.Tag
End If
Next Ctrl
Exit Sub
GestionErreur:
Select Case err.Number
Case 438   ' pas d'image dans le contrôle examiné
Resume Next
Case 2114 'format d'image invalide
If bFond = True Then         'C'est l'image de fond
MsgBox "(2114) L'image de fond de '" & CodeContextObject.Name & "', c'est-à-dire : '" _
& CodeContextObject.Tag & "' est d'un format invalide."
Resume ImgControles
Else
MsgBox "(2114) L'image '" & Ctrl.Tag & "' est d'un format invalide pour le contrôle '" _
& Ctrl.Name & "' de l'objet '" & CodeContextObject.Name & "'."
Ctrl.Picture = CurrentProject.Path & "\Images\Default.bmp"
Resume Next
End If
Case 2220  'L'image est absente
If bFond = True Then         'C'est l'image de fond
MsgBox "(2220) L'image de fond de '" & CodeContextObject.Name & "', c'est-à-dire : '" _
& CodeContextObject.Tag & "' est absente."
Resume ImgControles
Else
MsgBox "(2220) L'image '" & Ctrl.Tag & "' est absente pour le contrôle '" _
& Ctrl.Name & "' de l'objet '" & CodeContextObject.Name & "'."
Ctrl.Picture = CurrentProject.Path & "\Images\Default.bmp"
Resume Next
End If
Case Else
MsgBox "Erreur inattendue dans AmnImages" & vbLf _
& err.Number & " : " & err.Description, vbCritical
End Select
End Sub

IV - Encore une suggestion

Si votre propos est d'afficher une image à l'écran en dehors de votre formulaire, pensez à l'instruction :

shell "C:\WINDOWS\EXPLORER.EXE " & "Chemin de l'image", vbNormalFocusc

ce qui équivaut à un double-clic sur le nom du fichier dans l'Explorateur Windows.

V - Téléchargez une base de données avec un exemple

Vous trouverez ici, un exemple d'application pour illustrer tous les cas possibles :

- un formulaire (fImagesExternes) qui contient à la fois des images incorporées et des images externes. Dans ce formulaire, si vous double-cliquez sur un contrôle de type « Imagexxx », l'image renseignée dans la propriété Remarque s'affichera à l'écran avec le logiciel associé à ce type de fichier ;

- un formulaire (fImagesExternes) qui contient lui-même un sous-formulaire (sfImEx) tous deux faisant appel à la routine AmnImages() ;

- un état (eImEX).

Vous devez décompresser l'archive dans un dossier qui contiendra la base de données ImagesExternes.mdb et le répertoire Images.

- N.B. À l'ouverture du formulaire, une série de messages d'alerte : dans l'exemple, des images sont volontairement absentes pour montrer la réaction du formulaire dans de telles circonstances.

VI - Remerciements

Merci à l'équipe Office, pour sa collaboration dans la réalisation de ce tutoriel et à Maxime Gault (_Max_) et Fabian Piette (bifconsult) pour en avoir corrigé le texte.