1. #1
    Futur Membre du Club
    Inscrit en
    juin 2009
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : juin 2009
    Messages : 22
    Points : 7
    Points
    7

    Par défaut Recherche sur plusieurs fichiers CSV avec clé commune

    Bonjour,

    Habituellement je me débrouille tout seul mais là je sais que je ne suis plus loin mais la syntaxe me manque.

    J'ai travaillé sur un p'tit bout de code, qui me permet de reformater et merger 2 fichiers CSV via une clé commune.

    J'ai commencé ça sur vba et cela fonctionne très bien puis je l'ai porté vers vbs pour une utilisation plus générale.
    Et là, c'est le drame ... pleins de petit problème que j'ai pu corriger un a un mais il en reste un et pas le moindre.

    Explication:

    J'ai 2 fichiers avec comme séparateur ;

    Le Fichier 1 (poste.csv) contient les entêtes suivants:
    numero;nom;prénom;type de poste;nom entité
    11111;toto;alain;PC;IT
    11112;tata;jean;PC;Local

    Le Fichier 2 (tscip.txt) contient les entêtes suivants:
    Usagers;No annuaire;Type de poste;IP;MAC;Droit
    11111;11111;PC;10.10.10.22;00:01:02:03:04:05;Oui
    11112;11112;PC;10.10.10.21;00:05:04:03:02:01;

    Je voudrais créer un fichier fusionner avec les entêtes suivants:
    numéro;nom;prénom;type de poste;nom entité;IP;MAC;Droit
    11111;toto;alain;PC;IT;10.10.10.22;00:01:02:03:04:05;Oui
    11112;tata;jean;PC;Local;10.10.10.21;00:05:04:03:02:01;

    Pour cela j'ai choisi d'utiliser ADODB.Recordset qui fait le boulot assez rapidement.
    Comme je vous l'ai dit sur VBA aucun problème ça roule par contre même en adaptant la requête j'ai toujours des erreurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     
    	FichierCSV = "postes.csv"
    	FichierTXT = "TSCIP.txt"
     
            'Creation de la connection et de l'objet recordset
    	Set objConnection = CreateObject("ADODB.Connection")
    	Set objRecordset = CreateObject("ADODB.Recordset")
     
    	'Declaration de la connection a la base de donnees
    	objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                       "Data Source=" & strFilePath & ";" & _
                       "Extended Properties=""text;HDR=No;FMT=CSVDelimited"";"
     
    	objRecordset.Open "SELECT * FROM [" & FileNameCSV & "] As Sample1, [" & FileNameTXT & "] As Sample2 Where Sample1.numero=Sample2.Usagers", _
                      objConnection, 3, 3, &H1
    L'erreur au départ était ADODB.Connection: Provider cannot be found. It may not be properly installed. mais en utilisant C:\Windows\SysWOW64\cscript.exe,
    maintenant j'ai Microsoft JET Database Engine: Syntax error in FROM clause.

    Qu'en pensez vous ? Je sais que cela doit venir du délimiteur mais je ne vois pas comment formater celui-ci.

    J'ai l'impression que le split n'est pas fait correctement et donc il ne trouve pas numero et Usagers.
    Quand j’exécute pour tester SELECT * FROM " & FileNameCSV, le resultat de l'item(0) est numero;nom;prénom;type de poste;nom entité
    Alors qu'il devrait être numero tout simplement.

  2. #2
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    8 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2013
    Messages : 8 310
    Points : 16 415
    Points
    16 415

    Par défaut


    Bonjour,

    j'ai eu aussi le souci avec ADODB à cause de la mauvaise gestion de Windows en 64 bits !
    Du coup j'ai contourné en utilisant l'objet Dictionary pour regrouper par clef …

    ___________________________________________________________________________________________________________
    Je suis Paris, Egypte, Stockholm, London, Istanbul, Berlin, Nice, Bruxelles, Charlie, …
    . . . . . Comme la vitesse de la lumière est supérieure à celle du son, certains ont l'air brillant avant d'avoir l'air con !

  3. #3
    Futur Membre du Club
    Inscrit en
    juin 2009
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : juin 2009
    Messages : 22
    Points : 7
    Points
    7

    Par défaut

    Merci pour ta réponse Marc. C'est sur que j'aurais besoin que cela fonctionne sur toutes les plateformes dans le cas ou.

    Je n'ai jamais utilisé l'objet Dictionary mais je vais jeter un coup d'oeil.

  4. #4
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    8 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2013
    Messages : 8 310
    Points : 16 415
    Points
    16 415

    Par défaut



    Donc déjà pour du multi-plateforme ADODB risque d'être un souci selon la version utilisée du Provider !

    Pas de souci avec Dictionary, documentation consultable sur MSDN comme dans l'aide VBA interne …
    . . . . . Comme la vitesse de la lumière est supérieure à celle du son, certains ont l'air brillant avant d'avoir l'air con !

  5. #5
    Futur Membre du Club
    Inscrit en
    juin 2009
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : juin 2009
    Messages : 22
    Points : 7
    Points
    7

    Par défaut

    bon j'ai fait un ptit bout de code qui repond a mon besoin mais je vous le soumet pour savoir si je peux faire mieux ...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
     
    Const INPUT_FILE_1 = "c:\test\poste.csv"
    Const INPUT_FILE_2 = "c:\test\tscip.txt"
    Const OUTPUT_FILE = "c:\test\result.csv"
     
    Const ForReading = 1
    Const ForWriting = 2
     
    Dim dicPostes, dicTSCIP, strKey, fso, ts, strItem
    Dim filInput1, filInput2, filResults, strLine, bolFound
     
    Set fso = CreateObject("Scripting.FileSystemObject")
     
    Set filInput1 = _
      fso.OpenTextFile(INPUT_FILE_1, ForReading)
    Set filInput2 = _
      fso.OpenTextFile(INPUT_FILE_2, ForReading)
    Set filResults = _
      fso.OpenTextFile(OUTPUT_FILE, ForWriting, True)
     
    strLine = filInput1.ReadLine
    Set dicPostes = CreateObject("Scripting.Dictionary")
    While Not filInput1.AtEndOfStream
     
        strLine = filInput1.ReadLine
        dicPostes.Add Split(strLine, ";")(0), Array(Split(strLine, ";")(1), Split(strLine, ";")(2), Split(strLine, ";")(3), Split(strLine, ";")(4))
        'numero;nom;prenom;type de poste;nom entité
     
    Wend
    filInput1.Close
     
    strLine = filInput2.ReadLine
    Set dicTSCIP = CreateObject("Scripting.Dictionary")
    While Not filInput2.AtEndOfStream
        strLine = filInput2.ReadLine
        dicTSCIP.Add Split(strLine, ";")(2), Array(Split(strLine, ";")(6), Split(strLine, ";")(7), Split(strLine, ";")(8), Split(strLine, ";")(13))
    Wend
    filInput2.Close
     
    filResults.WriteLine "Numéro;Nom;Prenom;Type de poste;Nom entité;MAC;Adresse IP;Numéro domaine;IP-Softphone;Anomalie"
     
    For Each strKey In dicPostes
        strItem = dicPostes.Item(strKey)
        If Not dicTSCIP.Exists(strKey) Then
            filResults.WriteLine strKey & ";" & Join(strItem, ";") & ";;;;;Numero uniquement dans la base Poste"
        Else
            filResults.WriteLine strKey & ";" & Join(strItem, ";") & ";" & Join(dicTSCIP.Item(strKey), ";")
        End If
    Next
     
    For Each strKey In dicTSCIP
        strItem = dicTSCIP.Item(strKey)
        If Not dicPostes.Exists(strKey) Then
            filResults.WriteLine strKey & ";;;;;" & Join(strItem, ";") & ";Numero uniquement dans la base TSC-IP"
        End If
    Next
     
    filResults.WriteLine vbCrLf
    filResults.WriteLine "Lignes compter dans Postes " & _
      "(" & dicPostes.Count & ") and TSC-IP " & _
      "(" & dicTSCIP.Count & ")."
    filResults.Close
    Si j'ai bien compris le fonctionnement de l'objet dictionnaire, je ne peux pas faire autrement que d'avoir une clé (key) et des objets (Item).
    Et comme j'ai des fichiers a multiple colonnes, je ne suis pas sur que j'utilise la bonne methode.

  6. #6
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    8 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2013
    Messages : 8 310
    Points : 16 415
    Points
    16 415

    Par défaut


    La Logique requérant un seul dictionnaire …
    Comparer la ligne de code n°27 avec la ligne n°9 du code ci-dessous.
    Si la ligne n°37 ne déclenche pas d'erreur alors cela n'a plus rien à voir avec la présentation initiale …

    Tel que présenté initialement c'est assez simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
                 Const C = "poste.csv", T = "tscip.txt", D = ";"
    With CreateObject("Scripting.FileSystemObject")
        If .FileExists(C) And .FileExists(T) Then
                 Set oDic = CreateObject("Scripting.Dictionary")
            With .OpenTextFile(C, 1)
                     V = .ReadLine
                Do Until .AtEndOfStream
                     S = .ReadLine
                     oDic(Split(S, D)(0)) = S
                Loop
                    .Close
            End With
                 Set oCsv = .OpenTextFile("result.csv", 2, True)
            With .OpenTextFile(T, 1)
                        S = Split(.ReadLine, D)
                        oCsv.WriteLine V & D & S(3) & D & S(4) & D & S(5)
                Do Until .AtEndOfStream
                        S = Split(.ReadLine, D)
                     If oDic.Exists(S(0)) Then
                        oCsv.WriteLine oDic(S(0)) & D & S(3) & D & S(4) & D & S(5)
                        oDic.Remove S(0)
                     Else
                        oCsv.WriteLine S(0) & ";;;;;" & S(3) & D & S(4) & D & S(5)
                     End If
                Loop
                    .Close
            End With
                For Each V In oDic
                     oCsv.WriteLine oDic(V) & ";;;"
                Next
                     oCsv.Close
                 Set oCsv = Nothing
                     oDic.RemoveAll
                 Set oDic = Nothing
                 MsgBox "Fichier créé …", vbInformation
        Else
            MsgBox "Fichier source absent !", vbExclamation
        End If
    End With
    ___________________________________________________________________________________________________________

          Merci de cliquer sur en bas à droite de chaque message ayant aidé puis sur pour clore cette discussion …

    . . . . . Comme la vitesse de la lumière est supérieure à celle du son, certains ont l'air brillant avant d'avoir l'air con !

  7. #7
    Futur Membre du Club
    Inscrit en
    juin 2009
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : juin 2009
    Messages : 22
    Points : 7
    Points
    7

    Par défaut

    Salut Marc,

    Merci pour le bout de code, cela m'a permis de détecter un problème.
    Car quand j'ai des lignes vide a savoir la dernière les codes plantes.


    Pour la ligne 27 et 9, tu as l’œil, entretemps le format a un peu changer et j'ai qq colonnes en plus d’où la modif mais le principe reste le même.

    J'ai testé ton code, tres bien, MERCI

    Je vais faire un mix entre le mien et le tiens en gardant un max du tiens ...

  8. #8
    Futur Membre du Club
    Inscrit en
    juin 2009
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : juin 2009
    Messages : 22
    Points : 7
    Points
    7

    Par défaut

    Marc,

    Une petite question, pourquoi tu n'utilises pas les .Item de l'objet dic ?
    Est ce une question d'optimisation ou plutôt d’intérêt ?


    Voici le code final:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    Const C = "C:\Local\postes.csv", T = "C:\Local\TSCIP.txt", D = ";"
     
    With CreateObject("Scripting.FileSystemObject")
        If .FileExists(C) And .FileExists(T) Then
                 Set oDic = CreateObject("Scripting.Dictionary")
            With .OpenTextFile(C, 1)
                     V = .ReadLine
                Do Until .AtEndOfStream
                     S = .ReadLine
                     oDic(Split(S, D)(0)) = S
                Loop
                    .Close
            End With
     
                 LineCSV = oDic.Count
                 Set oCsv = .OpenTextFile("C:\Local\result.csv", 2, True)
     
           With .OpenTextFile(T, 1)
                        S = Split(.ReadLine, D)
                        oCsv.WriteLine V & D & S(7) & D & S(9) & D & S(10) & D & S(13)
                Do Until .AtEndOfStream
                        S = Split(.ReadLine, D)
     
                     If UBound(S) = -1 Then Exit Do
                     LineTXT = LineTXT + 1
     
                     If oDic.Exists(S(2)) Then
                        oCsv.WriteLine oDic(S(2)) & D & S(7) & D & S(9) & D & S(10) & D & S(13)
                        oDic.Remove S(2)
                     Else
                        oCsv.WriteLine S(2) & ";;;;;" & S(7) & D & S(9) & D & S(10) & D & S(13)
                     End If
                Loop
                    .Close
            End With
                For Each V In oDic
                     oCsv.WriteLine oDic(V) & ";;;"
                Next
                     oCsv.Close
                 Set oCsv = Nothing
                     oDic.RemoveAll
                 Set oDic = Nothing
                 MsgBox "Fichier créé …", vbInformation
        Else
            MsgBox "Fichier source absent !", vbExclamation
        End If
    End With

  9. #9
    Expert éminent sénior
    Avatar de Marc-L
    Homme Profil pro
    Développeur informatique
    Inscrit en
    avril 2013
    Messages
    8 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2013
    Messages : 8 310
    Points : 16 415
    Points
    16 415

    Par défaut


    En fait je l'utilise sans le spécifier car Item est la propriété par défaut de l'objet Dictionary !
    Tu peux très bien l'ajouter si pour toi c'est plus clair …

    ___________________________________________________________________________________________________________

          Merci de cliquer sur en bas à droite de chaque message ayant aidé puis sur pour clore cette discussion …
    . . . . . Comme la vitesse de la lumière est supérieure à celle du son, certains ont l'air brillant avant d'avoir l'air con !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. VBA consolider plusieurs fichiers .csv vers .xlsm avec conditions
    Par ProjetRH dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 23/04/2017, 10h40
  2. Lecture de plusieurs fichiers csv avec R
    Par Korera dans le forum R
    Réponses: 1
    Dernier message: 06/03/2017, 17h20
  3. [XL-2010] Effectuer un tri sur plusieurs fichiers avec la même macro excel
    Par flodrows dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 18/03/2016, 16h31
  4. [XL-MAC 2011] Recherche sur plusieurs fichiers excel
    Par Muzzik dans le forum Excel
    Réponses: 2
    Dernier message: 14/05/2015, 17h50
  5. [XL-2010] Recherche données dans plusieurs fichiers XLS avec argument
    Par gregory.d dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 13/08/2014, 14h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo