Mise à jour d’une base Access par fichier CSV ou Excel – Episode 8

Passerelles Access CSV

Suite de la série sur l‘importation de données CSV ou Excel dans Access.

L’article précédent a mis en place la classe DatabaseUpdater qui va permettre de « jouer » une série d’importations automatiquement. Voici comment tester cette classe.

Si vous avez manqué le début

Relisez la loooongue série d’articles précédents, si vous ne l’avez pas déjà fait, sinon, rien ne marchera. 😉

Les fichiers de test

  • Sur mon bureau Windows, j’ai un dossier appelé « Fichiers CSV« , dont le chemin est donc : C:\Users\Hervé\Desktop\Fichiers CSV.
  • Dans ce dossier, j’ai deux séries de fichiers : trois fichiers CSV, et trois fichiers Excel. Il s’agit de deux scénarios d’importation différents (on importera soit les fichiers CSV, soit les fichiers Excel).

Fichiers à importer

La table de mise à jour

Comme l’idée est d’automatiser l’importation de ces fichiers, on va d’abord les référencer dans la table tbl Updates, créée dans l’article précédent. Voici ma table de mises à jour :

CAPT

Comme vous ne voyez rien sur la capture d’écran 😉 voici le détail de la première ligne :

  • Id : numéro automatique
  • Source : C:\Users\Hervé\Desktop\Fichiers CSV\Dest01.csv
  • SourceType : CSV
  • ExcelVersion : 9 (qui est la valeur de la constante acSpreadsheetTypeExcel12, Excel 2007 et plus)
  • Target : tbl Destinataires Newsletter
  • TempTable : vide
  • Headers : cochée
  • ImportSpecs : vide
  • AutoClean : cochée
  • Priority : 1
  • Category : Test CSV
  • Les 2 lignes suivantes sont identiques, à part la Source (changez le nom de fichier), et la priorité (2, puis 3).
  • Les 3 lignes qui suivent concernent les fichiers Excel : les noms de fichiers changent, ainsi que SourceType = EXCEL.

Le code

Pour tester tout ça, recopiez le code qui suit dans un module standard de votre base de données :

Tester

  1. Placez le curseur dans la première procédure (Sub TestNewsletterCSV / End Sub).
  2. Cliquez sur l’icône Exécuter Sub/UserForm.
  3. Faites la même chose avec la deuxième procédure.

Les 2 procédures de test appellent elles-mêmes la procédure ImportationGlobale, qui déclenche l’importation proprement dite. Le principe consiste à :

  1. Créer un objet DatabaseUpdater.
  2. Appeler la méthode Update() de cet objet, en lui passant une catégorie. La catégorie permet de ne traiter que certaines lignes de la table tbl Updates (les 3 lignes marquées « Test CSV » pour le scénario CSV, et les 3 lignes marquées « Test Excel » pour le scénario Excel).

Avec tout ce qui a été mis en place précédemment, il suffit maintenant d’une seule ligne (l’appel de ImportationGlobale) pour déclencher une série d’importations. Pratique, non ?

Importation terminée !

Vous aimerez aussi...

45 réponses

  1. Maleko dit :

    Bonjour,

    Merci pour ce blog et merci aussi à tous ceux qui ont commentés. Je cherche aussi à importer un fichier csv dans une table avec clé composée, je commente ici puisqu’on en parle. Tout d’abord, j’ai l’impression qu’il n’y a pas de possibilité de créer une specification d’importation avec une clé primaire composée ? C’est possible ?

    Merci d’avance,

    • Hervé Inisan dit :

      La spécification d’importation n’a pas nécessairement de notion de clef (il s’agit d’une liste de champs à importer). Donc a priori, si le fichier source contient une clef composée, ça peut passer.

  2. MAylo dit :

    Bonjour , je reviens vers vous pour d’autres contraintes , en fait je voulais savoir si possible de modifier le code pour que la mise à jour se fasse par ordre de colonne et non pas par libelle de l’entête de la colonne ET pour que les clé primaire composé de plusieurs champ soit prise en compte , c’est a dire les deux premières colonnes , c’est les clés primaires et le reste c des données normal

    merci d’avance pour votre aide
    Cordialement

    • Hervé Inisan dit :

      Ce sont effectivement 2 adaptations possibles du code (un peu long à publier tout de suite, comme ça :)).
      Par contre, autant la gestion de clefs composées est une ouverture pratique, autant le fait d’utiliser les champs par leurs index me semble moins pratique : si la table ou le fichier évoluent en structure, on risque de mettre toute la moulinette par terre (donc c’est compliqué en termes de maintenance).

      • Maleko dit :

        Bonjour MAylo,

        vous avez pu importer des fichiers avec clés composées ? ça me serait aussi très utile !!

        J’ai cru avoir imaginé quelque chose d’acceptable en imaginant que la propriété PrimaryKey renverrait un tableau mais je n’arrive pas à l’écrire, j’ai des erreurs. De meme, je ne trouve pas la possibilité de créer une specification d’importation avec clée composée…

        Merci beaucoup par avance

        • Hervé Inisan dit :

          Dans mon exemple de code, j’ai fait (pour l’instant) le choix d’une clef primaire simple, ce qui fait que la propriété PrimaryKey est une chaîne. Sa valeur est précisément Indexes("PrimaryKey").Fields(0).Name. Mais on peut adapter le code en renvoyant directement la collection Indexes("PrimaryKey").Fields, ce qui permet d’avoir la liste de tous les champs de la clef.
          Bien sûr, ça ne suffira pas (il faut adapter les requêtes SQL également), mais c’est déjà une piste…
          Je posterai sans doute une version avec clef composée un jour, mais je suis trop pris ces temps-ci pour le faire ces jours-ci. 🙁

  3. Sakoun dit :

    Bonjour, magnifique article très clair et professionnel !
    J’ai un petit problème, mes lignes s’importe dans la table temporaire avec un message erreur d’importation et une table se crée avec un problème de conversion de type sur des dates ! Avez vous deja eu ce genre de problème ?

  4. MAylo dit :

    Bonjour ,

    J’ai suivi le tuto à la lettre et quand je lance l’importation sur plusieurs fichiers , j’ai un message d’erreur :
    “Eléments non trouvé dans cette collection”

    si quelqu’un peut m’aider a résoudre le problème , merci d’avance

    Cordialement

  5. Sam dit :

    Bonjour,

    D’abord très bon article qui répond partiellement à mon besoin,

    J’ai suivi jusqu’ici, mais maintenant j’ai un cas particulier :

    1- D’abord, je dois sélectionner plusieurs fichiers CSV à emporter à partir d’une Boite de dialogue (Sélectionner les Fichiers à importer)

    2- Mes fichiers source CSV ne contiennent pas une ligne d’en-tête ==> Donc je dois mettre Headers : False et après qu’est ce que je dois faire ?

    3- Je n’ai pas besoin de toutes Les informations contenues dans les fichiers CSV, je dois choisir lesquels je veux importer et aussi indiquer à quels noms de champs de la table Access ils correspondent.
    (Aussi il faut que je fasse un test sur les dates car il sont de cette forme 20131224 ==> Donc je dois les transformer au format Date compris par la BD).

    Exemple :

    Les champs de la Table dans Access :

    CODEOPERATION DATEMATURITE DATEOPERATION DATEVALEUR DEVISE MONTANTDEVISE MONTANTDINAR OPERATION TAUX BANQUE OPERATEUR

    Exemple de ligne des fichiers CSV :

    MM1335415608;20131220;20131223;20131224;PRET;CAD;2080000.00;339;BCT;;0.8125;46.94;Pret MM DVS;NABIL;

    (Je dois sélectionner que les informations dont j’ai besoin)

    Si c’est possible de m’envoyer un exemple qui peut le faire ce serait gentil,
    Merci pour ton aide, c’est très urgent.

    • Hervé Inisan dit :

      Vu les contraintes diverses sur le fichier source (pas d’en-têtes, des dates à reformater, des colonnes à sélectionner…), j’ai peur que son importation ne puisse pas se faire directement avec le code de ces articles (voir le 1er article de la série pour les différentes conditions à respecter).
      Il va sans doute falloir passer par une importation sur mesure, par exemple :

      1. Importation des données dans une table temporaire.
      2. Retraitement des données (par une requête sans doute, du VBA sinon)
      3. Transfert des données dans la table finale

      Peut-être qu’une spécification d’importation peut également faire l’affaire (à vérifier pour les dates) ?

      • Sam dit :

        Merci pour m’avoir répondu,

        Une spécification d’importation résout partiellement le problème sauf que je dois spécifier quel champ du CSV appartient à quel champ de la Table,

        Donc l’idée est de découper les lignes du CSV avec le délimiteur « ; » et affecter à chaque partie un nom significatif, ensuite faire correspondre chacun au champ qui lui correspondant dans la Table.

        ==> Mais je ne sais pas comment appliquer ça en VBA.

        • Hervé Inisan dit :

          C’est un peu long à expliquer dans un commentaire de blog. Dans les grandes lignes, il faudrait sans doute :

          • Ouvrir un fichier par les fonctions Access ou le Scripting Runtime
          • Lire les lignes une par une.
          • « Eclater » chaque ligne via la fonction Split()
          • Faire sorte que chaque colonne éclatée soit mise en correspondance avec un nom de colonne Access.
          • Transférer les données dans la table à l’aide d’un DAO.Recordset.

          Pas simple dit comme ça, ça demande du code sur mesure… 😉

  6. Sami dit :

    Bonjour,
    J’apprécie vraiment votre article bien détaillé,
    mais je ne retrouve pas dans la section Téléchargements du blog la base de données complète reprenant tous ces exemples ainsi que le fichier Clients.csv.

    si vous ne l’avez pas encore posé, je vous prie de me les envoyer par mail :
    sami.jilani1983@gmail.com

    Merci pour votre aide.

  7. Hervé Inisan dit :

    angel > Sur quelle ligne est-ce que cela « casse » ?

  8. Hervé Inisan dit :

    Fab > Content que ça fonctionne ! 🙂

  9. Fab dit :

    Merci! Effectivement maintenant cela fonctionne très bien une fois que j’ai neutralisé
    ‘If blnIncludeKey Then
    ‘strSQL = strSQL &  » AND ([{2}] > 0) »
    ‘Else
    ‘strSQL = strSQL &  » AND ([{2}] < 1) »
    ‘End If

    Merci encore 😉

  10. Hervé Inisan dit :

    Fab > Merci pour le retour. 🙂 A priori, l’erreur viendra entre autres de cette partie :

    …et de la suivante. Pour des raisons de gestion des NuméroAuto, je compare la clef primaire à 0 ou à 1, ce qui échouera sur ces champs Texte (ou non numériques de manière générale). Il faudrait adapter un peu le code pour adapter cette partie. J’ai noté la remarque, ça fera sans doute un article futur (mais il faut un peu de temps pour tester 😉 ).

  11. Fab dit :

    Bonjour,

    1er) super le projet! j’aime bien le cotés pédagogique.

    2émé) j’ai juste un pb avec la clé primaire qui n’est pas numérique mais au format texte. J’ai un champs qui peut servir de clé primaire lettres et chiffres (xxxx-12345678). si je tronque sur les chiffres pas de pb ça marche au format numérique mais si je passe au format texte j’ai erreur lors de l’insertion de lignes. J’ai cherché mais pas trouvé ce qui m’en empêche. avez vous une idées?

    Fab

  12. Hervé Inisan dit :

    Thomas> Merci pour le retour. 🙂 Et bonne visite sur le blog !

  13. angel dit :

    Bonjours,
    Je suis un retraité qui essaie de comprendre:
    j’ai suivi les huit étapes et à l’arrivée j’ai un message lors de l’importation

    « Eléments non trouvé dans cette collection »

    je ne parviens pas à trouver l’erreur
    Pouvez vous m’aider ?
    Cordialement

  14. Thomas dit :

    Félicitations pour votre blog, qui est d’une très grande clarté. Les exemples proposés me semblent particulièrement utiles, bien choisis et bien conçus.

    Je n’ai encore rien testé, mais je suis convaincu par avance, rien qu’à la lecture.

    Merci à vous.

  15. Ludo34 dit :

    Bonjour,
    Merci pour toutes ces infos. c’est super sympa.
    je viens de me créer dans le fichier de liaison entre SAP et Acces, un champ concatener, afin de pouvoir apposer une clé primaire dans Access.
    cela me va bien pour l’instant.
    Me plongeant juste dans le VBA, je préfére y aller doucement car j’ai besoin de cette base pour bosser donc petit à petit….
    en tout cas merci Bcp pour vos eclaircissements.
    ludo

  16. Hervé Inisan dit :

    Ludo34 > Il y a effectivement un peu d’adaptation à prévoir pour gérer une clef composée. En gros, partout dans le code où la propriété PrimaryKey est utilisée, il faudra des retouches. La structure objet du code fait que c’est très cloisonné, donc en principe plus adaptable… mais il y a quand même des retouches. 😉

  17. Ludo34 dit :

    Parfait.
    Je préférerais la piste N°1 mais vba et moi ce n’est qu’une nouvelle histoire qui commence. je vais donc essayer de m’y pencher en espérant ne pas y perdre ni mon latin ni trop de temps 🙂
    merci

  18. Hervé Inisan dit :

    Ludo34 > Techniquement, il peut effectivement y avoir une clef primaire composée de plusieurs champs. L’important étant que l’ensemble des champs constitue une valeur unique. D’un point de vue Bases de données, c’est parfait…

    Le seul problème est que ma moulinette, en l’état actuel, ne gère qu’une clef simple, non composée (voir le point 8 de l’introduction du premier article de la série). 😉 Il y a donc 2 pistes :

    • Adapter le code VBA pour qu’il gère les clefs composées.
    • Faire en sorte, dans Excel par exemple, de concaténer les 2 champs en un seul, qui deviendra la clef primaire simple.
  19. Ludo34 dit :

    Bonsoir,
    je viens de trouver deux champs :
    – un champ pour le N° de document
    – un champ pour la Position comptable dans ce document (1,2,3…) autant de numéro différent que de lignes dans un même N° de Document.
    Apparemment d’aprés un collègue, on peut indiquer 2 clés primaires dans une même table, me permettant d’obtenir une clé unique pour chaque enregistrement.
    les défauts possible pour ce genre d’utilisation ?
    merci

  20. Hervé Inisan dit :

    Ludo34 > Mais dans ces données, il n’y a vraiment aucune info qui serve de clef ? Genre : un numéro de client, un numéro de produit… ? On n’a pas le choix des champs à inclure dans l’extraction ?

    Sinon, la solution qui consiste à ajouter un numéro dans Excel n’est sans doute pas viable. Exemple :

    1. J’importe 10 lignes SAP. Je les numérote par Excel (on va dire de 1 à 10).
    2. Je les intègre à Access.
    3. J’importe 10 autres lignes SAP (11 à 20).
    4. Je les intègre à Access.
    5. J’importe 10 autres lignes SAP (21 à 30). Mais dans ces 10 lignes, il y en a 3 qui ont déjà été importées lors de l’import #1, et 2 autres qui ont déjà été importées à l’import #2. Il faudrait donc créer 5 nouvelles lignes dans Access, et en mettre à jour 5 anciennes.

    Mais comment peut-on le savoir ?

  21. Ludo34 dit :

    Si solution 1, cela serait trop facile et donc moins marrant….
    Les données enregistrées dans SAP peuvent bouger (financière et quantité) Il me faut donc trouver le moyen de créer une clé primaire entre SAP ==> Access.
    Pas facile. Si je liais la feuille excel avec une formule de calcul dans la dernière colonne qui pourrait me donner un Numéro Unique de ligne cela pourrait le faire ?
    Je t’avoues que je préférerais passer par du VBA si possible pour éviter de devoir créer une grosse feuille excel avec calul et peut-être risque d’erreurs.

  22. Hervé Inisan dit :

    Ludo34 > Il n’y a pas un champ, dans SAP, qui puisse être intégré à l’extraction, et qui soit déjà une clef primaire SAP ?

    Sinon, avant de lancer des usines à gaz : est-ce que le but est :

    • seulement d’importer des données SAP dans Access (en partant à vide à chaque fois côté Access) ?
    • d’importer des données SAP ET de mettre à jour l’existant dans Access, en cas de correspondance ?

    Le premier scénario est plus simple et ne nécessite pas de clef primaire. Il ne nécessite d’ailleurs pas tout le code VBA de cette série d’articles. 😉

  23. Ludo34 dit :

    Bon et bien, je ne sais pas obtenir une numérotation unique de chaque ligne extraite de SAP qui pourrait me servir de clé primaire.
    y aurait il un autre moyen ?
    Peut-être en me créant une clé primaire automatique dans Excel qui serait reprise dans Access ?
    par avance merci

  24. Hervé Inisan dit :

    Ludo34 > S’il n’y a pas de clef primaire dans la source, il n’y a aucun moyen fiable de comparer les données importées à celles existantes dans la base Access. N’est-il pas possible, lors de l’extraction, d’inclure la clef primaire des données de départ ? Sinon, qu’est-ce qu’on fait dans ce cas quand une ligne vient de SAP et qu’elle existe déjà dans Access ?

    Si on incrémente un champ supplémentaire « à la volée », le problème est qu’il n’y aura pas de moyen de comparaison avec une importation future. Donc ça ne résout pas complètement le problème. 🙁

  25. Ludo34 dit :

    Bonjour et bravo pour votre Blog. Les passionés sont toujours de bons conseils et aides.
    Je viens de suivre à la lettre votre procédure et tout fonctionne à merveille.
    Pour mon utilisation personnelle par contre j’aurais une petite question.
    J’ai une extraction de données d’une base (SAP) que je veux importer dans Access (csv ou excel). bien entendu je n’ai pas de clés primaire extraite de cette extraction.
    Ma question : comment puis-je faire pour reussir à importer mes données dans ma table tout en incrémentant une clé primaire automatiquement et abscente de mon fichier source ?
    je ne sais pas si j’ai été trés clair là pour le coup 🙂
    merci pour votre support.
    ludovic

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *