[VBA] Ouverture dossier

Résolu
Bonjour a tous,

je souhaiterais ecrire une macro qui me permette de copier tous les fichiers (.xls ou .txt) contenus dans un certain dossier et de les coller dans un autre document excel, chacun dans une feuille differente.

Deja, est-il possible de realiser le copier-coller sans ouvrir les fichiers ? Ensuite, comment m y prendre ? J e m embrouille un peu avec les commandes open, copy, paste et avec l ouverture de dossier.

Merci beaucoup pour votre aide

Charlotte
Configuration: Windows XP Internet Explorer 7.0

20 réponses

Résumé de la discussion

Une macro est recherchée pour copier tous les fichiers .xls et .txt contenus dans un dossier et les coller chacun dans une feuille distincte d’un autre classeur Excel, sans ouvrir les fichiers. Plusieurs interventions suggèrent de gérer la question de l’ouverture des fichiers et d’utiliser une boucle pour parcourir le répertoire et créer une feuille par fichier, avec gestion des extensions. Des propositions de code évoquent Activate/Open, copier-coller et effacement du presse-papiers, ainsi que des méthodes pour récupérer les fichiers sans connaître leur nom ni leur nombre. Des échanges évoquent aussi des détails comme le passage par AllFilesInFolder et les défis de la conversion des données des fichiers texte vers des feuilles Excel.

Bobot (l’IA à votre service)
  1. Application.EnableEvents = False
            Workbooks.Open Filename:= _
            "D:\***\**\***.xls"
            Application.EnableEvents = True
            Windows("***.xls").Activate
            
            'copie des données sygma
            Sheets(1).Activate
            Cells.Select
            Application.CutCopyMode = False
            Selection.Copy
            'colle les donnée
            Windows("TOTAL.xls").Activate
            Sheets("*****").Select
            ActiveSheet.Range("A1").Select
            ActiveSheet.Paste
             'vide le presse papier pour pouvoir fermer suivi des ofs
            Dim oDataObject As DataObject
    
            Set oDataObject = New DataObject
            oDataObject.SetText ""
            oDataObject.PutInClipboard
            Set oDataObject = Nothing


    puis surtout une boucle pour ton fichier de recepetionpour changer de feuille a chaque copie
    1. Bonjour,

      Je ne peux t'être d'une grande utilité sur la création de graphique dans Excel.

      J'ai trouvé ça sur developpez.com : https://excel.developpez.com/faq/?page=Graphique#GraphCreate

      Peut être y trouveras-tu ta réponse.

      ;o)
      1. Oui, je crois que c est de ce code que je m etais inspiree pour creer mon graphe local mais la le probleme reside dans le fait que je trace le graphe sur chaque feuille que j ouvre.

        Never mind, je vais tenter de debloquer ca.

        Je te remercie infiniment pour tout l aide que tu m as apporte ! C est adorable de ta part.

        A bientot peut etre,

        Charlotte
    2. Désolé mais je ne connais pas trop bien Excel et encore moins les graphiques ...

      Quelle erreur s'affiche sur la ligne "ActiveChart.Location Where:=xlLocationAsObject, Name:=ws" ?

      1. Erreur 5 : "Ungültiger Prozeduraufruf oder ungültiges Argument" en allemand, donc ca doit etre qqchose comme "Mauvaise procedure d appel ou mauvais argument"
    3. Il a fallu que j ecrive "Call DrawCurve(mWs)" pour que ca commence a marcher parce qu avant, il ne comprenait pas. Mais j ai encore une erreur au niveau de la ligne "ActiveChart.Location Where:=xlLocationAsObject, Name:=ws" : il ne comprend pas ou il doit tracer le diagramme donc il me le met en objet dans une feuille annexe.
      1. Je viens de voir ...

        Je te propose de rajouter dans la procédure traiteXLS(), juste après wkIn.Close la ligne suivante :

        DrawCurve(mWs)

        et de modifier ta fonction :

        Private Sub DrawCurve(ByRef ws) 
        
        ws.Activate
        ws.Range("B2:C96").Select 
        Charts.Add 
        ActiveChart.ChartType = xlXYScatterSmoothNoMarkers 
        ActiveChart.SetSourceData Source:=ws.Range("B2:C96"), PlotBy:=xlColumns 
        
        ActiveChart.Location Where:=xlLocationAsObject, Name:=ws
        
        With ActiveChart 
           .HasTitle = True 
           .ChartTitle.Characters.Text = "Kennlinie I(V)" 
           .Axes(xlCategory, xlPrimary).HasTitle = True 
           .Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Spannung [V]" 
           .Axes(xlValue, xlPrimary).HasTitle = True 
           .Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Strom [A]" 
        End With 
        
        End Sub


        Je n'ai pas testé ... :os

        ;o)
        1. Le bouton avec une cle et un marteau reste grise

          Aucune idée ... :o(

          Ensuite, qu entends-tu exactement par "Selectionne le bouton et place-le dans la feuille" ?

          En principe, quand tu cliques sur "la clé et le marteau", tu as la boîte à outils Contrôles qui s'ouvre. En passant le pointeur de la souris sur les icônes, tu peux lire le nom des contrôles ...

          ;o)
          1. OK, merci. Je vais essayer de resoudre ce grand mystere ; )

            Je ne sais pas si tu as vu mon message ci-dessus vu qu on a du ecrire en meme temps...
        2. Peut etre que je peux abuser de ton amabilite aussi en te demandant de jeter un coup d oeil a la sous-procedure que j ai ecrite (ci-dessous) qui devrait me permettre de tracer la courbe I(V) dans chacune des feuilles generees, sachant que chaque fichier contient deux colonnes de chiffres, la premiere pour I et la deuxieme pour V.

          Quand je fais tourner ce code localement, ca marche, mais en l inserant dans ton code, ca bloque parce que je ne suis pas sure d avoir bien indique le nom de la feuille dans laquelle il fallait inserer le graphique (sachant que cette feuille est variable). Je voudrais lui faire comprendre qu il doit dessiner ce graphe dans la feuille qui est active a l instant t.
          Je ne sais pas non plus comment lui demander de me mettre le graphe a un certain endroit de la feuille (par exemple entre les cellules E15, E20, J15 et J20.

          Merci beaucoup !

          Private Sub DrawCurve()

          Range("B2:C96").Select
          Charts.Add
          ActiveChart.ChartType = xlXYScatterSmoothNoMarkers
          ActiveChart.SetSourceData Source:=ThisWorkbook.Worksheets(1).Range("B2:C96"), PlotBy:=xlColumns

          ActiveChart.Location Where:=xlLocationAsObject, Name:=ThisWorkbook.Worksheets(1)

          With ActiveChart
          .HasTitle = True
          .ChartTitle.Characters.Text = "Kennlinie I(V)"
          .Axes(xlCategory, xlPrimary).HasTitle = True
          .Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Spannung [V]"
          .Axes(xlValue, xlPrimary).HasTitle = True
          .Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Strom [A]"
          End With

          End Sub
          1. Merci pour tes explications !

            Dans la barre à outils Excel, il faut affichier le menu Visual Basic. Il faut cliquer sur l'icone qui représente une clé et un marteau pour faire apparître la boîte à outils. Sélectionne le bouton et place le dans la feuille. Pour affecté les propriétés, il faut cliquer sur la main qui pointe une feuille.

            Heu... Le bouton avec une cle et un marteau reste grise quoi aue je tente : tu as une idee ? Ensuite, qu entends-tu exactement par "Selectionne le bouton et place-le dans la feuille" ?
            1. Ah bah en fait, apparemment, en remplacant le nom de mon dossier contenant les .txt par un nom sans espace, ca marche.

              Faut-il que je mette des "" quelquepart dans la cellule C3 pour que ca fonctionne avec un nom a espace ?
              1. Non, pas besoin de mettre de "" dans le texte de la cellule.

                ;o)
            2. Merci, je comprends un peu mieux, meme si je ne suis pas encore tres familiere avec VBA.

              Par exemple, dans ta procedure "Private Sub initEnvironnement()", il suffit que tu ecrives "mTabFiles()" en deuxieme position dans "ModTools.AllFilesInFolder()" pour que VBA comprenne ce qu est "mTabFiles" ?

              Quand je n ai que des .xls dans mon dossier, ca marche impecable. En revanche, j ai un bug avec les .txt (a la ligne "FileCopy mPath, Replace(UCase(mPath), "TXT", "XLS")" il me dit qu il n a pas trouve le chemin - erreur 76). Je vais essayer de voir pourquoi...

              Sinon, ou est-ce que tu as programme ton "bouton" (je ne sais pas trop comment ca s appelle) "Lancer le Traitement" (il faudrait que je le traduise en anglais ou en allemand ; ))

              Merci infiniment, Polux31 !
              1. Par exemple, dans ta procedure "Private Sub initEnvironnement()", il suffit que tu ecrives "mTabFiles()" en deuxieme position dans "ModTools.AllFilesInFolder()" pour que VBA comprenne ce qu est "mTabFiles" ?


                La fonction AllFilesInFolder() demande en entrée 2 paramètres pour fonctionner: Le premier paramètre est le chemin d'accès au dossier à scanner, le 2ème paramètre est le tableau qui va stocker les chemins et noms de chaque fichier contenu dans le répertoire.
                Le premier paramètre est passé par "valeur", c'est à dire le contenu de la variable. Cette variable peut être manipulée et même modifiée à l'intérieur de la fonction sans affecter la valeur initiale de la procédure appelante.

                Le 2ème paramètre est passé par "référence", c'est à dire que c'est l'adresse mémoire qui est passée (c'est un pointeur dans d'autres langages). Ici on modifie directement le contenu de la variable.

                Sinon, ou est-ce que tu as programme ton "bouton" (je ne sais pas trop comment ca s appelle) "Lancer le Traitement" (il faudrait que je le traduise en anglais ou en allemand ; ))

                Dans la barre à outils Excel, il faut affichier le menu Visual Basic. Il faut cliquer sur l'icone qui représente une clé et un marteau pour faire apparître la boîte à outils. Sélectionne le bouton et place le dans la feuille. Pour affecté les propriétés, il faut cliquer sur la main qui pointe une feuille.

                ;o)
            3. Bonjour,

              Effectivement je n'ai pas trop commenté le code ^^

              Option Explicit
              
              'L'objet ClipBoard n'existant pas en VBA, il faut utiliser les fonctions de l'API Windows :
              '-- Déclaration des fonctions API
              Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
              Private Declare Function CloseClipboard Lib "user32" () As Long
              Private Declare Function EmptyClipboard Lib "user32" () As Long
               
              Private mTabFiles()
              Private pathFolder As String
              
              'Setter d'affection de valeur à pathFolder
              'Cette valeur vient de la cellule C3
              'Procédure appelée par cmdMenu_Click() de Feuil1
              Public Sub setPathFolder(ByVal str As String)
                  pathFolder = str
              End Sub
              
              'Procédure Main du traitement
              'Procédure appelée par cmdMenu_Click() de Feuil1
              Public Sub Main()
              
                  initEnvironnement
                  traiteFichiers
                  
              End Sub
              
              'Procédure d'initialisation du tableau mTabFiles()
              'Procédure appelée par Main()
              Private Sub initEnvironnement()
              
                  'On récupère le chemin d'acces de tous les fichiers contenus dans le répertoire
                  '
                  If ModTools.AllFilesInFolder(pathFolder, mTabFiles()) = False Then
                  
                  End If
                  
              End Sub
              '
              'Procédure qui traite tous les fichiers du répertoire
              Private Sub traiteFichiers()
              Dim i As Long
              Dim ext As String
              
                  'Pour tous les fichiers de mTabFiles()
                  For i = LBound(mTabFiles()) To UBound(mTabFiles())
                      'On extrait l'extension
                      'mTabFiles(i) contient le chemin d'acces et le nom d'un fichier
                      'ex mTabFiles(i) = "C:\MonDossier\MonSousDossier\MonFichier.XLS"
                      ext = ModTools.ExtractFileExt(mTabFiles(i))
                      'Si l'extension est XLS
                      If UCase(ext) = "XLS" Then
                          'On lance la procédure pour traiter les fichiers Excel
                          Call traiteXLS(mTabFiles(i))
                      End If
                      'Si l'extension est TXT
                      If UCase(ext) = "TXT" Then
                          'On lance la procédure pour traiter les fichiers TXT
                          Call traiteTXT(mTabFiles(i))
                      End If
                  Next i
                  
              End Sub
              '
              'Procédure qui traite les fichier XLS
              'Elle ouvre le fichier
              'Elle créé un onglet dans le présent fichier
              'Elle copie le contenu du fichier dans le nouvel onglet
              'mPath = le chemin d'acces et le nom d'un fichier
              '
              Private Sub traiteXLS(ByVal mPath As String)
              Dim nom As String
              Dim wkIn As Workbook
              Dim wsIn As Worksheet
              Dim mWk As Workbook
              Dim mWs As Worksheet
              
                  'On déclare un objet wkIn et on l'ouvre
                  Set wkIn = Workbooks.Open(mPath)
                  'On déclare un objet wsIn appartenant à wkIn
                  Set wsIn = wkIn.Worksheets(1)
                  'On déclare un nouvel objet worksheet dans le présent fichier.
                  Set mWs = ThisWorkbook.Worksheets.Add(after:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
              
                  'On extrait le nom du fichier pour nommer le nouvel onglet
                  nom = ModTools.ExtractFileName(mPath)
                  
                  'On active le fichier ouvert et l'onglet
                  wkIn.Activate
                  wsIn.Activate
                  'On copie
                  Range("A1:AA65000").Copy
                  'On colle dans le nouvel onglet
                  mWs.Paste
                  'On nomme le nouvel onglet
                  mWs.Name = Mid(nom, 1, Len(nom) - 4)
                  'On vide le presse papier
                  VideMemoire
                  'on ferme le classeur ouvert
                  wkIn.Close
                  'on libère les objets
                  Set wkIn = Nothing
                  Set wsIn = Nothing
                  Set mWs = Nothing
              
                  
              End Sub
              
              Private Sub traiteTXT(ByVal mPath As String)
              
                  'on copie et on renomme le fichier en .xls
                  FileCopy mPath, Replace(UCase(mPath), "TXT", "XLS")
                  'on remplace l'extension du fichier dans le sPath
                  mPath = Replace(UCase(mPath), "TXT", "XLS")
                  'on traite le fichier comme un fichier .XLS
                  Call traiteXLS(mPath)
                  'on supprime le fichier créer
                  Kill (mPath)
                  
              End Sub
              
              Private Sub VideMemoire()
                  OpenClipboard 0
                  EmptyClipboard
                  CloseClipboard
              End Sub


              Voilà, j'espère que c'est plus clair pour toi, sinon reviens poser tes questions.

              ;o)
              1. Merci beaucoup, Polux31 !

                Je suis en train de regarder ca de pres. Pour l instant je bloque surtout sur ton "mPath" : j ai du mal a voir ou tu le definis. Enfin je vois que tu le definis par exemple de la facon suivante "Private Sub traiteXLS(ByVal mPath As String)" mais je ne vois pas comment le code peut savoir exactement ce que c est quand tu l appelles ensuite pour la premiere fois "Set wkIn = Workbooks.Open(mPath)". Tu as du lui faire correspondre un chemin qqpart ailleurs mais je ne trouve pas...

                Pareil pour mTabFiles et PathFolder : je ne vois pas a quel moment tu leur assignes une valeur.

                Merci !
                1. Bonjour Polux31,

                  je vais detailler un peu plus :

                  - mes fichier txt et xls sont dans un dossier qui est toujours le meme et ne contient pas de sous-dossier (en fait il s agit de fichiers de resultats de simulations contenant les coordonnees des points d une courbe I(V)) ; il n y a donc qu un seul dossier, fixe, a scanner.

                  - les fichiers peuvent se trouver en format txt ou xls (a priori tout l un ou tout l autre) ; la structure des xls est toujours la meme, il n y a qu un seul onglet a copier (le premier) ; celle des txt est egalement toujours la meme (points d une courbe I(V)) et il vaut mieux que chaque donnee se retrouve dans une cellule differente (plus simple pour tracer la courbe ensuite) mais il me semble que cela se fait automatiquement quand j ouvre mon txt avec excel.

                  - je souhaite copier-coller chacun des documents (ou premiere feuille de document) de mon dossier dans une feuille differente de mon nouveau document excel, en donnant a chaque feuille le nom du document d origine dans le dossier. A terme, j aimerais aussi en profiter pour tracer les courbes I(V) sur chaque feuille, apres avoir effectue le coller et avant de passer a la feuille suivante mais on va peut etre commencer par le commancement... ; )

                  J espere avoir ete un peu plus precise.

                  Merci beaucoup pour ton aide
                  1. Bonjour Charlotte,

                    Peux-tu être un peu plus précise stp.

                    Si j'ai bien compris, tu veux récupérer des fichiers .xls et .txt dans un répertoire.

                    1) Est-ce toujours le même répertoire ?
                    2) Y-a-t-il des sous répertoires à scanner également ?

                    Lorsque tu as récupéré les fichiers, tu veux copier le contenu dans un nouveau classeur, 1 onglet par fichier.

                    1) La structure des fichiers .xls est-elle toujours la même ?
                    2) Si c'est un fichier .xls, faut-il copier tous les onglets ou bien 1 seul onglet ?
                    3) Si c'est un fichier .txt, leur structure est-elle toujours identique ? Comment doivent être recopiés les lignes
                    du fichier .txt ? Tout dans la même cellule ou 1 ligne txt = 1 ligne xls ?

                    ;o)
                    1. Ah oui, et puis j ai oublie de te dire que j aimerais bien refermer chaque fichier apres l avoir copie et colle dans la nouvelle feuille excel de mon nouveau document excel.
                      1. Merci beaucoup YATA !

                        Je n arrive pas encore a le faire tourner. Il a l air de coincer sur le "Dim oDataObject As DataObject" : tu as une idee de la raison ?

                        Ensuite, pourrais-tu m expliquer en quoi consiste ton code au niveau de l "OngletaOuvrir" stp ? Et ce que veut dire "If xlsSheet.Name <> """ (a quoi correspond le "") ?

                        Enfin, si j ai bien compris, tu me permets ici de
                        - copier les donnees de mon fichier d origine (dans le dossier d origine) et coller dans la feuille active de mon nouveau document Excel
                        - changer de feuille Excel ensuite

                        mais est ce que ton code comprend le fait de rechercher dans mon dossier d origine tous les documents d extension .xls ou .txt, quel que soit leur nom, afin de les copier chacun dans une feuille differente de mon nouveau document Excel ? Parce que si c est le cas j ai pas trop compris alors... ; )

                        Merci beaucoup pour ton aide en tout cas !

                        Charlotte
                        1. Workbooks(NomDoc).Activate
                          Dim xlsSheet As Excel.Worksheet 'Variable objet "feuille"
                          'Boucle sur toutes les feuilles du classeur actif:
                          For Each xlsSheet In Worksheets
                          xlsSheet.Activate

                          If xlsSheet.Name <> "" Then

                          OngletaOuvrir = xlsSheet.Name
                          OngletaOuvrir = Left(OngletaOuvrir, 8)
                          Windows("****").Activate

                          For Each Sheet In Worksheets
                          Sheet.Activate
                          If Sheet.Name = OngletaOuvrir Then
                          trouver = True
                          Exit For
                          Else
                          'rien
                          End If
                          Next xlsSheet

                          voilà la boucle à toi d'adapter :p
                          1. J ai oublie de preciser que je ne connais pas a l avance le nom ni le nombre de fichiers dans mon dossier.