formateur informatique

Corriger et exporter les données d'une base en VBA

Accueil  >  Bureautique  >  Access  >  Access VBA  >  Corriger et exporter les données d'une base en VBA
Livres à télécharger


Pour partager cette vidéo sur les réseaux sociaux ou sur un site, voici son url :


Inscription Newsletter    Abonner à Youtube    Vidéos astuces Instagram
Sujets que vous pourriez aussi aimer :


Nettoyer et exporter les données en Visual Basic Access

Dans cette formation VBA Access, nous proposons de réaliser l'exportation des données après nettoyage, en vue d'une exploitation par un logiciel tiers, comme Excel. Cette base des idées de sorties offre des miniatures d'images, archivées dans un sous dossier de l'application. Mais toutes n'existent pas. Certains enregistrements sont donc orphelins. En parcourant le sous dossier des miniatures, nous devons donc tester leur existence. Si elle n'est pas présente, l'enregistrement correspondant doit être supprimé. Nous devons de même purger le champ Description des balises Html prévues pour une restitution Web, afin de permettre une exploitation textuelle correcte. Puis, nous exporterons le résultat au format universel CSV pour permettre des importations et extractions, notamment avec VBA Excel, afin de traiter et manipuler les photos. Comme la base de données aura été purgée, nous proposerons enfin de la compacter par le code.

Base Access pour nettoyer et exporter donnees par code Visual Basic

La capture ci-dessus propose un extrait des données de la base Access à partir de laquelle nous proposons de travailler. Le volume de cette table a volontairement été restreint pour les besoins du téléchargement. Elle offre néanmoins plus de 500 enregistrements. Chacun de ces enregistrements est décrit sur 7 Champs. L'un d'entre eux, le champ societes_descriptif est particulièrement riche, puisqu'il propose une description textuelle multiligne de chaque activité recensée.

Sources et présentation de la problématique
Pour débuter directement nos travaux par le code VBA Access, il est donc nécessaire de disposer des données source. Comme vous le constatez, la décompression conduit au fichier de la base de données : nettoyer-exporter.mdb, accompagné des miniatures dans le sous dossier images. Comme nous le disions en préambule, les noms de ces fichiers images sont référencés dans la table id_sorties de la base de données, et plus précisément dans le champ societes_photo1. Mais il n'y a pas autant de photos qu'il y a d'enregistrements.
  • Double cliquer sur le sous dossier images pour afficher son contenu dans l'explorateur,
Dossier des images reliées aux enregistrements de la base de données à purger

Comme l'indique la barre d'état en bas de la fenêtre de l'explorateur Windows, ce dossier ne contient que 273 éléments, soit 273 images. Or la table de la base de données, compte près de 600 enregistrements. Cela signifie que 300 lignes environ, sont orphelines. Il s'agit de les détecter pour les supprimer. Et pour ce faire, nous devons parcourir chaque enregistrement de la base de données. Et pour chacun d'entre eux, nous devons vérifier la présence de l'image spécifiée dans le champ societes_photo1. Nous allons donc devoir, pour chaque enregistrement, parcourir l'ensemble des fichiers contenus dans le sous dossier images, à la recherche d'une correspondance.
  • A la racine du dossier de décompression, double cliquer sur le fichier nettoyer-exporter.mdb, pour l'ouvrir dans Access,
  • Puis, cliquer sur le bouton Activer le contenu du bandeau de sécurité,
  • Dans le volet des objets Access sur la gauche, double cliquer sur la table id_sorties pour afficher son contenu,
Vous remarquez l'énumération des 558 enregistrements, comme l'indique la petite barre de navigation en bas de la fenêtre Access. Chacun d'entre eux est décrit sur 7 champs. Il s'agit d'une petite base de données des idées de sorties, catégorisées par activité, département et ville. Le champ societes_photo1 restitue bien le nom du fichier image associé à l'idée de sortie. Vous constatez enfin la présence du champ societes_descriptif. Comme nous le disions en préambule, ces descriptions sont accompagnées de balises Html pour permettre une restitution Web instantanée, avec mise en forme. Or, notre exportation est dédiée à des exploitations par des logiciels tiers pour produire des extractions sur des recherches textuelles. Donc nous devons purger ce champ de ces balises, pour tous les enregistrements. Et pour un traitement productif par le code VBA, nous aurons besoin d'exploiter les expressions régulières que nous nous avions apprises lors de la formation VBA Excel pour nettoyer des chaînes de texte.

Enfin, vous avez pu constater l'extension ancienne génération de cette base de données(.mdb). Cette base est en effet le fruit d'une exportation d'un site Web professionnel. Et ce traitement a été réalisé il y a quelques années. Mais ce format n'a aucune incidence. Nous pourrons exploiter tous les objets de programmation VBA Access, comme si nous le faisions avec une base de données à l'indice actuel, d'extension accdb.

Parcourir les enregistrements par le code VBA
Comme un formulaire n'est pas nécessaire pour cette application dédiée au traitement, nous proposons de créer un module. Ce module est destiné à accueillir nos procédures de code VBA.
  • Fermer la table id_sorties en cliquant sur sa croix située en haut à droite de sa fenêtre,
  • Cliquer sur l'onglet Créer en haut de la fenêtre Access pour activer son ruban,
  • Tout à fait à droite du ruban, dans la section Macros et code, cliquer sur le bouton Module,
Nous basculons ainsi dans l'éditeur de code Visual Basic Access. Avant de débuter les travaux de développement, il s'agit d'enregistrer ce module.
  • Réaliser le raccourci clavier CTRL + S,
  • Dans la petite boîte de dialogue qui surgit, saisir le nom : purger et valider par Ok,
Le module apparaît ainsi renommé dans l'explorateur de projet sur la gauche de la fenêtre de l'éditeur. Il sera reconnu par ce même nom, dans le volet des objets Access.
  • Dans sa feuille de code, au centre de l'écran, sous l'instruction Option Compare Database, ajouter l'instruction suivante :
Option Explicit

Comme nous l'avons évoqué à maintes reprises dans nos formations VBA Access, cette instruction impose à l'éditeur d'effectuer le contrôle de chacune des variables. De fait, il sera interdit de réaliser des erreurs dans leur désignation ou encore d'employer des variables non déclarées. Nous codons au plus juste.
  • A la suite dans la feuille de code, créer les bornes de la procédure nettoyer_exporter :
Sub nettoyer_exporter()

End Sub


Il s'agit de la procédure principale destinée aux traitements récursifs pour parcourir à la fois, les enregistrements de la base de données et les fichiers du sous dossier images.

Comme toujours, avant de débuter le codage, nous devons commencer par déclarer les variables nécessaires au traitement.
  • Dans les bornes de la procédure, ajouter les déclarations suivantes :
Dim ligne As Recordset : Dim base As Database
Dim nom_dossier As String : Dim nom_fichier As String
Dim lid As String : Dim desc As String
Dim ligne_export As String : Dim requete As String
Dim fichier As Object


Nous commençons par déclarer les deux objets nécessaires pour accéder aux éléments de base de données. L'objet ligne typé comme un Recordset est prévu pour manipuler les enregistrements résultant des requêtes exécutées sur la base. Et précisément, l'objet base est destiné à manipuler la base de données en cours. Mais encore faut il initialiser ces objets afin qu'ils instancient les classes proposant ces propriétés et méthodes. Ces déclarations ont été rendues possibles grâce à l'ajout de la référence ActiveX Data Object.

Référence ActiveX Data Objects pour manipuler enregistrements de base de données par le code VBA

C'est ce qu'illustre la boîte de dialogue dans l'extrait de la capture ci-dessus. Vous pouvez l'atteindre en déroulant le menu Outils de l'éditeur, puis en cliquant sur la rubrique Références. Si elle n'est pas cochée, vous devez l'ajouter avec le numéro (6.1 ici) le plus élevé, soit le dernier indice.

Les variables nom_dossier et nom_fichier déclarées comme des String, sont prévues pour mémoriser les chemins d'accès complets, respectivement au sous dossier images et à chacun des fichiers qu'il contient.

Ensuite les variables lid et desc permettront de prélever les informations des champs societes_id et societes_descriptif, pour traitement. La variable ligne_export, elle aussi typée comme un String, doit servir à reconstituer les informations concaténées pour chaque enregistrement, afin de les exporter dans un fichier Csv. La variable requete servira à mémoriser la syntaxe Sql des requêtes actions à exécuter sur la table. Enfin la variable fichier est déclarée comme une variable de type Object. Son objectif est en effet d'instancier la classe lui permettant d'hériter des méthodes nécessaires pour parcourir les fichiers d'un dossier.

Fort logiquement, nous proposons désormais d'affecter les premières variables.
  • A la suite du code, ajouter les affectations suivantes :
nom_dossier = Application.CurrentProject.Path & "\images\"

Set base = Application.CurrentDb
Set ligne = base.OpenRecordset("id_sorties", dbOpenTable, dbReadOnly)
Set fichier = CreateObject("scripting.filesystemobject")


Tout d'abord, la propriété CurrentProject de l'objet VBA Access Application permet de désigner le projet en cours. Son attribut Path retourne alors le chemin d'accès complet au dossier de la base de données. C'est la raison pour laquelle nous le concaténons avec le nom du sous dossier (& "\images\"). Ainsi nous mémorisons bien le chemin d'accès au sous dossier images, dans la variable nom_dossier.

Les trois affectations qui suivent consistent à instancier des classes. Et dans ce cas, le mot clé Set est nécessaire. Grâce à la méthode CurrentDb de l'objet Application, nous désignons la base de données en cours. De fait, l'objet base hérite des pouvoirs pour la manipuler. D'ailleurs nous exploitons dans la foulée sa méthode OpenRecordset. Comme nous l'avait appris la formation VBA Access pour accéder aux données, cette méthode requiert trois arguments. Le premier peut être une requête Sql ou une table. Ici, nous lui passons la table id_sorties afin d'accéder à ses enregistrements. Puis, grâce aux deux paramètres qui suivent, enseignés par l'aide en ligne, nous définissons le type d'accès (dbOpenTable) et le mode (dbReadOnly), soit en lecture seule. Il s'agit en effet de prélever et non d'écrire. Nous préservons ainsi l'intégrité des données. De fait, notre objet ligne hérite des méthodes permettant de manipuler les enregistrements de cette table.

Enfin nous initialisons la dernière variable objet grâce à la fonction VBA CreateObject. Comme nous l'avait appris la formation VBA Access pour archiver les données, elle permet d'instancier une classe selon le paramètre qui lui est passé. Et ce paramètre scripting.filesystemobject permet à la variable fichier d'hériter de tous les pouvoirs, pour manipuler les fichiers du disque dur. C'est grâce à elle que nous pourrons atteindre les miniatures du sous dossier images, par le code VBA.
  • A la suite du code, ajouter les instructions suivantes :
Open Application.CurrentProject.Path & "\exportation.txt" For Output As #1

Close #1


Lorsque nous parcourrons les enregistrements, nous aurons besoin de les exporter, après les avoir nettoyés. Pour pouvoir les exporter en ajoutant les nouvelles données à la suite des précédentes, le fichier externe doit exister. Ce bloc VBA permet de créer le fichier exportation.txt dans le dossier de l'application. En effet, comme nous l'avait appris la formation VBA Excel pour importer et exporter les données, l'instruction VBA Open permet d'accéder en mémoire au fichier désigné juste après. Le mode For Output spécifie un accès en écriture avec écrasement. Si le fichier existe déjà, il est remplacé et donc réinitialisé.

Il est temps d'accéder aux enregistrements de la table id_sorties. Et pour cela, nous devons exploiter l'objet Recordset que nous avons ainsi initialisé.
  • A la suite du code, ajouter les deux instructions suivantes :
If ligne.RecordCount = 0 Then Exit Sub
ligne.MoveFirst


Tout d'abord, la propriété RecordCount d'un objet Recordset permet de renseigner sur le nombre d'enregistrements présents dans la sélection définie. Nous testons donc s'ils existent. Le cas échéant, nous stoppons l'exécution du code. Dans le cas où les enregistrements sont bien trouvés, nous plaçons le pointeur de lecture sur le premier d'entre eux, grâce à la méthode MoveFirst de l'objet Recordset. Dès lors, nous devons initialiser une boucle permettant de les parcourir tous.
  • A la suite du code, ajouter les instructions VBA suivantes :
Do

ligne.MoveNext
Loop Until ligne.EOF = True


Une boucle VBA Do Loop permet de réaliser un traitement récursif tant qu'un critère à valider n'est pas vérifié. C'est l'instruction Until qui permet d'annoncer ce critère. La propriété EOF de l'objet Recordset renvoie un booléen déterminant si la fin des enregistrements est atteinte. Donc, tant que ce booléen ne vaut pas True, le traitement de la boucle se poursuit.

Supprimer des enregistrements d'une base de données
Pour chaque enregistrement passé en revue dans la boucle, nous devons prélever le nom du fichier image associé. Nous devons alors tester l'existence de ce fichier dans le sous dossier images, grâce à notre objet fichier, instancié en début de code. Si la miniature n'est pas trouvée, nous devons supprimer l'enregistrement correspondant. Et pour ce faire, nous exécuterons une requête SQL de suppression sur la table id_sorties.
  • Dans les bornes de la boucle, avant l'instruction ligne.MoveNext, ajouter les lignes de code suivantes :
nom_fichier = nom_dossier & ligne.Fields("societes_photo1").Value
lid = ligne.Fields("societes_id").Value

If fichier.FileExists(nom_fichier) = False Then
requete = "DELETE FROM id_sorties WHERE societes_id =" & lid
base.Execute requete

Else

End If


Tout d'abord, nous récupérons les informations nécessaires. La propriété Fields de l'objet Recordset permet d'atteindre le champ qui lui est passé en paramètre. Sa propriété Value accède alors au contenu du champ societes_photo1, pour l'enregistrement en cours de lecture. Le nom de l'image ainsi récolté est concaténé au chemin d'accès complet, que nous avions mémorisé dans la variable nom_dossier. Le tout est stocké dans la variable nom_fichier qui permettra le test de comparaison. De la même façon, nous récupérons l'identifiant de l'enregistrement en cours, dans la variable lid. Le champ societes_id est le champ de la clé primaire. Cette information permettra de désigner l'enregistrement à supprimer, si l'image n'est pas trouvée, grâce à une clause Where dans la requête SQL.

Ensuite et comme nous l'avions dit au moment de l'affectation, l'objet fichier a hérité, grâce à la fonction VBA CreateObject, des propriétés et méthodes permettant de manipuler les fichiers du disque. Ainsi, sa propriété FileExists retourne un booléen permettant de savoir si le fichier qui lui est passé en paramètre existe ou non. C'est la raison pour laquelle nous intégrons le test dans le critère d'une instruction conditionnelle If. Lorsque le critère est vérifié, le booléen retourné est False, signifiant que le fichier correspondant est absent. Dans ce cas, nous devons supprimer l'enregistrement. Nous écrivons donc la syntaxe de la requête de suppression, dans la variable requete. C'est le mot clé Delete en SQL qui initie une requête suppression. Dans la syntaxe, nous lui indiquons d'agir sur la table id_sorties (FROM id_sorties), mais seulement pour l'enregistrement en cours (WHERE societes_id=" & lid). Comme lid est une variable, elle doit être concaténée (&) à la chaîne statique. Enfin, c'est la méthode Execute de l'objet Database qui ordonne l'exécution de la requête action qui lui est passée en paramètre.

Nettoyer des champs par les expressions régulières
Dans le cas où le fichier image est bien trouvé au contraire (Else), il s'agit de traiter l'information du champ societes_descriptif, pour le purger de ses balises Html. Après nettoyage, nous pourrons mettre à jour les données purgées dans l'enregistrement en cours, toujours grâce à l'exécution d'une requête Sql. Pour cela, nous devons commencer par récolter les informations du champ, pour l'enregistrement en cours de lecture.
  • Dans la branche Else de l'instruction If, ajouter les deux lignes suivantes :
desc = ligne.Fields("societes_descriptif").Value
desc = purger_balises(desc)


Comme précédemment, la propriété Fields de l'objet Recordset permet d'atteindre le champ societes_descriptif. Grâce à sa propriété dérivée Value, nous stockons son contenu dans la variable desc, pour traitement. Et d'ailleurs dans la foulée, nous appelons la fonction purger_balises. Cette dernière n'existe pas. Nous devons la créer. Sa mission est de purger le contenu de la variable qui lui est passée en paramètre, des balises Html et de retourner le résultat après traitement. Ainsi, nous réceptionnerons le contenu du champ sans les balises, dans la variable desc. Il ne restera plus qu'à mettre à jour l'enregistrement en cours, avec ces nouvelles données. Nous devons donc quitter temporairement le développement de la procédure nettoyer_exporter.
  • Après le End Sub de la procédure nettoyer_exporter, créer la fonction purger_balises, comme suit :
Function purger_balises(chaine As String) As String
Dim expReg As Object : Dim motif As Object

End Function


Le but d'une fonction est de retourner une valeur après traitement. C'est le mot clé Function qui permet de la déclarer. Cette fonction attend le texte du champ societes_descriptif, mémorisé dans la variable desc, pour le nettoyer. Nous déclarons donc la variable chaine comme un String, pour que ce paramètre puisse lui être passé. Après traitement, la fonction retourne elle-même une chaîne de caractères. Donc nous la typons aussi comme un String. Puis, nous déclarons les deux variables nécessaires pour piloter les expressions régulières. La variable expReg doit instancier la classe de ces expressions pour hériter des propriétés et méthodes. La variable motif doit permettre de vérifier la présence d'occurrences présentant une forme remarquable, celle des balises Html, afin de les supprimer.

Mais avant de purger toutes les balises, nous souhaitons remplacer celles qui consistent en un saut de ligne par un tiret, afin de conserver les séparations explicites, après nettoyage. Et pour ce faire, nous pouvons exploiter la fonction VBA Replace qui permet de remplacer une occurrence par une autre, dans une chaîne de caractères.
  • Après les déclarations de la fonction, ajouter les instructions VBA suivantes :
chaine = Replace(chaine, "<BR>", "-")
chaine = Replace(chaine, "</BR>", "-")
chaine = Replace(chaine, "</P>", "-")
chaine = Replace(chaine, "&nbsp;", " ")


Les balises BR et /P provoquent un saut de ligne. Nous les remplaçons donc par le tiret et stockons le résultat dans la variable d'origine, la variable chaine. Le code &nbsp; transcrit un espace en langage Html. Mais comme il ne peut être interprété que par un navigateur Web, nous le remplaçons par un véritable espace.

Puisque les éléments que nous souhaitions conserver sont enregistrés dans la variable chaine sous une autre forme, nous pouvons désormais enclencher le traitement permettant de purger les balises Html. Nous devons dans un premier temps instancier la classe permettant d'hériter des pouvoirs pour manipuler les expressions régulières.
  • A la suite de la fonction, ajouter les trois lignes de code VBA suivantes :
Set expReg = CreateObject("vbscript.regexp")
expReg.Pattern = "(<)[0-9a-zA-Z_   ?~#\/.:;'=-]*(>)"
Set motif = expReg.Execute(chaine)


Comme toujours, pour initialiser une variable objet, le mot clé Set est nécessaire. C'est ensuite et encore une fois la fonction VBA CreateObject qui permet d'instancier une classe, selon le paramètre qui lui est passé. Et le paramètre vbscript.regexp désigne la classe permettant de manipuler les expressions régulières. Et d'ailleurs dans la foulée, nous exploitons la propriété héritée Pattern afin de définir le motif à trouver dans la chaîne de caractères. Ce motif consiste en une forme reconnaissable, bien qu'il n'y ait pas vraiment de règle pour déceler toutes les balises Html. Dans la syntaxe des expressions régulières, nous indiquons que les occurrences à trouver commencent et se terminent nécessairement par un symbole inférieur ou supérieur (< ou >), grâce aux parenthèses. Les crochets quant à eux, permettent d'énumérer tous les caractères susceptibles de se trouver entre ces bornes remarquables. Nous énumérons donc chacun d'entre eux. Mais comme le nombre de ces caractères entre les deux symboles, peut varier d'une balise à une autre, nous indiquons que leur répétition est indéfinie, grâce au symbole de l'étoile situé juste après le crochet fermant.

Puis, nous initialisons la variable objet motif, grâce à la méthode héritée Execute. Cette dernière permet de lancer la recherche de la forme remarquable définie par le motif, sur la chaîne qui lui est passée en paramètre. Mais comme cette recherche se stoppe sur la première occurrence trouvée, nous devons initialiser une boucle de traitement, afin de réitérer la recherche jusqu'à la dernière balise Html.
  • Pour ce faire, à la suite de la fonction, ajouter les instructions suivantes :
While motif.Count > 0

chaine = expReg.Replace(chaine, "")
Set motif = expReg.Execute(chaine)

Wend

purger_balises = chaine


La propriété héritée Count de l'objet motif permet de compter les occurrences trouvées, selon le motif imposé. Nous exploitons son résultat comme un critère de boucle afin de poursuivre le traitement, tant qu'elles ne sont pas toutes remplacées. En effet, à chaque passage de la boucle While, nous exploitons la méthode héritée Replace de l'objet expReg, afin de remplacer chacune de ces occurrences par une chaîne vide (""). Et avant de boucler, nous exécutons de nouveau la recherche du motif sur la chaîne. Si son résultat est toujours positif, le traitement se poursuit, sinon la boucle se termine. A l'issue, nous affectons au nom de la fonction, la variable chaine ainsi retravaillée et purgée. C'est ainsi que la variable Desc se voit affectée de son contenu nettoyé, depuis la procédure appelante nettoyer_exporter. Le code VBA complet de la fonction purger_balises est le suivant :

Function purger_balises(chaine As String) As String
Dim expReg As Object: Dim motif As Object

chaine = Replace(chaine, "<BR>", "-")
chaine = Replace(chaine, "</BR>", "-")
chaine = Replace(chaine, "</P>", "-")
chaine = Replace(chaine, "&nbsp;", " ")

Set expReg = CreateObject("vbscript.regexp")
expReg.Pattern = "(<)[0-9a-zA-Z_   ?~#\/.:;'=-]*(>)"
Set motif = expReg.Execute(chaine)

While motif.Count > 0

chaine = expReg.Replace(chaine, "")
Set motif = expReg.Execute(chaine)

Wend

purger_balises = chaine

End Function


Mettre à jour des enregistrements de la base de données
Nous devons exploiter ce résultat dans la procédure nettoyer_exporter, lorsque l'image correspondant à l'enregistrement a été trouvée, afin de mettre à jour l'information de champ. C'est à nouveau une requête Sql qui doit être exécutée sur l'enregistrement en cours. Et c'est le mot clé Update qui permet de définir une requête mise à jour.
  • Dans la branche Else de la procédure nettoyer_exporter, juste après l'appel de la fonction purger_balises (desc = purger_balises(desc)), ajouter les deux lignes de code VBA suivantes :
requete = "UPDATE id_sorties SET societes_descriptif ='" & desc & "' WHERE societes_id = "+ lid
base.Execute requete


Le principe est identique au précédent, pour la suppression des données, sauf qu'il s'agit cette fois d'une actualisation de l'enregistrement en cours de lecture dans la boucle VBA. Nous désignons quelle table doit être mise à jour dans la syntaxe Sql, juste après le mot clé Update. Puis il s'agit de définir la nouvelle valeur du champ à désigner juste après le mot clé SET. Nous l'affectons au contenu de la variable desc, purgée de ses balises grâce à l'appel de la fonction. Comme il s'agit d'une variable, nous la concaténons (&) à la chaîne de la syntaxe Sql. Bien sûr cette mise à jour ne doit pas être réalisée sur tous les enregistrements de la table. C'est pourquoi nous concaténons une clause Where à la fin de la syntaxe pour spécifier l'enregistrement en cours. Et pour cela, nous imposons l'égalité avec la variable lid, concaténée elle aussi.

Cet enregistrement validé et nettoyé doit désormais être ajouté à la suite dans le fichier d'exportation. Chacune des informations de champ doit être séparée d'une autre par un caractère remarquable, comme la barre verticale (|). On appelle ce caractère un séparateur de liste pour matérialiser les colonnes.
  • A la suite du code, toujours dans la branche Else, ajouter les instructions suivantes :
ligne_export = lid & "|" & ligne.Fields("societes_nom").Value & "|"
ligne_export = ligne_export & ligne.Fields("societes_activite").Value & "|" & ligne.Fields("societes_departement").Value & "|"
ligne_export = ligne_export & ligne.Fields("societes_ville").Value & "|" & desc & "|" & ligne.Fields("societes_photo1").Value


Nous décomposons la manoeuvre sur plusieurs lignes pour des raisons de lisibilité. Le principe consiste en effet à concaténer chaque information de champ pour l'enregistrement en cours, dans l'ordre où ils apparaissent, avec le séparateur de liste.

Pour ajouter cette ligne à la suite des autres afin d'offrir un fichier d'exportation complet et consolidé à l'issue, nous devons de nouveau accéder au fichier texte que nous avons créé en début de procédure. Il s'agit d'un accès en écriture. Mais pour pouvoir écrire à la suite sans écraser les précédentes données, le mode d'accès est Append.
  • A la suite du code, toujours dans la branche Else, ajouter les instructions suivantes :
Open Application.CurrentProject.Path & "\exportation.txt" For Append As #1
Print #1, ligne_export
Close #1


Le code est très semblable à celui que nous avons écrit pour créer le fichier exportation.txt. Seul le mode change (For Append), afin de consolider les données sans les écraser. En effet, comme ces instructions sont encapsulées dans la boucle de lecture des enregistrements, dès que l'un d'entre eux est validé, il est ajouté à la suite.

Avant de tester le bon fonctionnement du code, nous devons fermer les accès à la base de données et libérer les ressources de la mémoire.
  • A la fin de la procédure nettoyer_exporter, après la boucle et avant le End Sub, ajouter les lignes de code VBA suivantes :
ligne.Close
base.Close
Set fichier = Nothing
Set ligne = Nothing
Set base = Nothing


La méthode Close des objets Recordset et Database permet de fermer les connexions respectives. Puis, nous réaffectons tous les objets à Nothing afin de les vider de la mémoire.
  • Enregistrer les modifications (CTRL + S),
  • Placer le point d'insertion n'importe où dans la procédure nettoyer_exporter,
  • Puis, l'exécuter en enfonçant la touche F5 du clavier,
Visuellement, rien ne se produit a priori. Le traitement s'effectue en arrière-plan.
  • Basculer sur l'application Access (ALT + F11),
  • Puis, double cliquer sur la table id_sorties dans le volet des objets, pour l'ouvrir,
Nettoyer données de champ Access avec expressions régulières exécutées par le code VBA

Si vous consultez l'indication dans la petite barre de navigation, en bas de la fenêtre de la feuille de données, vous constatez que le nombre d'enregistrements a fortement chuté. Il est passé de 558 à 271. Près de 300 lignes ont donc été supprimées car leur fichier image n'existait pas. Les miniatures précisément sont au nombre de 273. Cet écart s'explique par le fait que deux d'entre elles sont en supplément et ne sont attachées à aucun enregistrement de la table Access. Enfin, vous remarquez que le champ societes_descriptif a parfaitement été purgé de toutes ses balises Html et ce, pour tous les enregistrements. Notre procédure VBA pour nettoyer la base de données a donc parfaitement fonctionné.

Il reste à vérifier que les informations ont correctement été exportées.
  • Dans l'explorateur Windows, afficher le dossier de l'application Access,
  • Double cliquer sur le fichier exportation.txt qui s'y trouve effectivement,
Exporter les données de base Access nettoyées par le code Visual Basic

Comme vous le constatez, tous les enregistrements s'y trouvent. Pour chacun d'entre eux, vous notez que les informations de champ sont explicitement séparées par le caractère remarquable de la barre verticale, tel que nous l'avons codé.
  • Fermer ce fichier texte et revenir sur l'application Access,
A l'avenir, nous pourrons exploiter ce fichier pour réaliser l'importation dans un autre logiciel, comme Excel. Le code VBA complet de la procédure nettoyer_exporter est le suivant :

Sub nettoyer_exporter()
Dim ligne As Recordset: Dim base As Database
Dim nom_dossier As String: Dim nom_fichier As String
Dim lid As String: Dim desc As String
Dim ligne_export As String: Dim requete As String
Dim fichier As Object

nom_dossier = Application.CurrentProject.Path & "\images\"

Set base = Application.CurrentDb
Set ligne = base.OpenRecordset("id_sorties", dbOpenTable, dbReadOnly)
Set fichier = CreateObject("scripting.filesystemobject")

Open Application.CurrentProject.Path & "\exportation.txt" For Output As #1

Close #1

If ligne.RecordCount = 0 Then Exit Sub
ligne.MoveFirst

Do
nom_fichier = nom_dossier & ligne.Fields("societes_photo1").Value
lid = ligne.Fields("societes_id").Value

If fichier.FileExists(nom_fichier) = False Then
requete = "DELETE FROM id_sorties WHERE societes_id = " & lid
base.Execute requete
Else
desc = ligne.Fields("societes_descriptif").Value
desc = purger_balises(desc)

requete = "UPDATE id_sorties SET societes_descriptif = '" & desc & "' WHERE societes_id = " + lid
base.Execute requete

ligne_export = lid & "|" & ligne.Fields("societes_nom").Value & "|"
ligne_export = ligne_export & ligne.Fields("societes_activite").Value & "|" & ligne.Fields("societes_departement").Value & "|"
ligne_export = ligne_export & ligne.Fields("societes_ville").Value & "|" & desc & "|" & ligne.Fields("societes_photo1").Value

Open Application.CurrentProject.Path & "\exportation.txt" For Append As #1
Print #1, ligne_export
Close #1

End If

ligne.MoveNext
Loop Until ligne.EOF = True

ligne.Close
base.Close
Set fichier = Nothing
Set ligne = Nothing
Set base = Nothing

End Sub


Compacter la base de données Access par le code VBA
Le compactage consiste à réduire la taille du fichier tout en améliorant les performances, grâce à une réorganisation des données. Comme nous avons purgé les informations et que nous avons supprimé de nombreux enregistrements, il est raisonnable d'estimer que le gain ne sera pas négligeable. La taille actuelle de la base de données est de plus de 3,3Mo.
  • Revenir dans l'éditeur de code VBA Access (ALT + F11),
  • Après la fonction purger_balises, créer la procédure compacter, comme suit :
Sub compacter()

End Sub


Cette procédure devra être appelée à la fin du traitement, par la procédure nettoyer_exporter.
  • Dans les bornes de la procédure compacter, ajouter les déclarations suivantes :
Dim nom_bd As String: Dim nom_tmp As String: Dim nom_fin As String
Dim fichier As Object


Une base de données peut être compactée seulement si elle n'est pas ouverte. Or notre code s'exécute précisément dans la base de données qui doit être optimisée. L'astuce consiste à créer une copie et à compacter cette dernière. C'est la raison pour laquelle nous créons plusieurs variables de type String afin de manipuler ces copies. Copier une base de données signifie être en mesure de manipuler les fichiers. C'est pourquoi nous créons une variable de type Object qui devra de nouveau instancier la classe nécessaire.
  • A la suite du code, ajouter les affectations suivantes :
Set fichier = CreateObject("scripting.FilesystemObject")

nom_bd = Application.CurrentDb.Name
nom_tmp = nom_bd & ".tmp"
nom_fin = Replace(nom_tmp, ".mdb.tmp", "-optimise.mdb")


Tout d'abord nous instancions la classe permettant à l'objet fichier de manipuler les fichiers du disque. Comme toujours, c'est la fonction VBA CreateObject avec le bon argument qui permet de le faire. Nous prélevons le nom de la base de données en cours avec son chemin complet, grâce à la propriété Name de la méthode CurrentDb de l'objet Application. A ce nom, nous concaténons une extension supplémentaire (".tmp"), pour le fichier de la copie. Comme la méthode de compactage demande de définir un nouveau nom de destination, nous remplaçons cette double extension par le suffixe-optimise.mdb. Le compactage génère en effet une autre copie.

Si plusieurs exécutions successives sont produites, le fichier optimisé peut déjà exister. Si c'est le cas, la méthode de compactage génèrera une erreur. Donc, nous devons d'abord le supprimer avant de compacter.
  • A la suite du code, ajouter l'instruction conditionnelle suivante :
If fichier.FileExists(nom_fin) = True Then
fichier.DeleteFile nom_fin
End If


Comme nous l'avons fait pour tester la présence des images, nous exploitons la propriété booléenne FileExists de l'objet fichier, sur le nom de la base de données optimisée. Si elle renvoie True, nous supprimons la copie grâce à la méthode héritée DeleteFile, en lui passant le nom du fichier.

Il ne reste plus qu'à créer la copie, compacter cette dernière et supprimer la copie qui aura servi d'intermédiaire pour le compactage.
  • Pour ce faire, à la suite du code, ajouter les instructions VBA suivantes :
fichier.copyfile nom_bd, nom_tmp, True
DBEngine.CompactDatabase nom_tmp, nom_fin
fichier.DeleteFile nom_tmp


La méthode héritée copyfile de l'objet fichier permet de copier un fichier source défini en premier paramètre, vers un fichier de destination passé en deuxième paramètre. C'est ensuite la méthode CompactDatabase de l'objet VBA Access DBEngine qui permet de réaliser le compactage de la base passée en premier paramètre, dans une base de données optimisée dont le nom lui est passé en second paramètre. Enfin, la méthode héritée DeleteFile de l'objet fichier permet de supprimer la copie temporaire qui a servi de lien pour compacter la base de données.

Pour tester le résultat, cette procédure doit être appelée.
  • A la fin de la procédure nettoyer_exporter, avant le End Sub, réaliser l'appel de la procédure par son nom, soit : compacter ,
  • Enregistrer les modifications puis exécuter le code,
Optimiser taille de base de données nettoyée en VBA Access par compactage

Encore une fois, le traitement est transparent pour l'utilisateur. Néanmoins, si vous ouvrez le dossier de l'application Access dans l'explorateur Windows, vous notez la présence de la copie optimisée. Et comme vous le remarquez, la différence de taille est importante. Nous avons divisé le poids du fichier par trois. Voilà donc un traitement automatisé et optimisé par le code Visual Basic fort intéressant pour les bases de données.

Le code complet de la procédure compacter, est le suivant :

Sub compacter()
Dim nom_bd As String: Dim nom_tmp As String: Dim nom_fin As String
Dim fichier As Object

Set fichier = CreateObject("scripting.FilesystemObject")

nom_bd = Application.CurrentDb.Name
nom_tmp = nom_bd & ".tmp"
nom_fin = Replace(nom_tmp, ".mdb.tmp", "-optimise.mdb")

If fichier.FileExists(nom_fin) = True Then
fichier.DeleteFile nom_fin
End If

fichier.copyfile nom_bd, nom_tmp, True
DBEngine.CompactDatabase nom_tmp, nom_fin
fichier.DeleteFile nom_tmp

End Sub


 
Sur Facebook
Sur Youtube
Les livres
Contact
Mentions légales



Abonnement à la chaîne Youtube
Partager la formation
Partager sur Facebook
Partager sur Twitter
Partager sur LinkedIn