Se connecter avec
S'enregistrer | Connectez-vous

Extraction des données de plusieurs fichiers xls

Dernière réponse : dans Programmation

Bonjour à tous,

J'ai été chargé, pour mon stage, de créer un questionnaire pour des magasins et d'analyser les retours.
J'ai donc créé un questionnaire (Feuil1) sous excel que je vais envoyer aux magasins mais je risque d'avoir beaucoup de retour.
Aussi pour simplifier l'analyse, je pense qu'il existe une macro pour récupérer les "Feuil1" de tous les questionnaires présents dans un dossier et les ajouter les unes à la suite des autres dans un fichier excel à part où chaque questionnaire aura son onglet (Feuil1, Feuil2...) propre.
Le soucis bien évidement, c'est que je n'ai jamais fait de programmation, pour l'instant, mais je pense m'y mettre.
D'ici là j'aurai besoin d'aide.

En vous remerciant grandement par avance,

Romanohow
Lassé par la pub ? Créez un compte

Merci,

Peut on créer une macro pour automatiser ce que je souhaiterai faire, à savoir:

récupération automatique des données contenues dans des fichiers Excel (placés dans un dossier spécifique), et agencées de la façon suivante, un fichier Excel = une feuille dédiée (Feuil1...) dans un fichier Excel "maitre".

Désolé si ce n'est pas clair, dites le moi j'essayerai de détailler.

Merci!
Expert Programmation

Salut,

Nous ne réalisons pas de travail à la demande.
Ce site est un forum d'entraide entre développeurs.
Cela dit, sache que nous acceptons volontiers les novices.

Bonjour,

Je ne demandais pas à ce qu'on me le fasse, je demandais juste si c'était possible et dans ce cas là me donner des pistes pour que j'essaye de faire quelque chose.
Je vais essayer de commencer tout seul, je posterai ce que j'ai trouvé...
Merci!
Expert Programmation

Bon, sache que la réponse à la question "Est-ce possible ?" est toujours "Oui".
C'est ce que je réponds toujours à mes clients (je suis pro). Mais j'ajoute toujours "Mais ça peut être très compliqué, ce qui veut dire très cher !" :lol: 

Ton problème est donc possible. Et il me semble même que ça peut être fait facilement.

Est-ce qui te pose problème ? Parcourir les fichiers d'un répertoire (pas évident au premier abord pour un débutant - on peut t'aider) ? Copier une feuille d'un classeur à l'autre (très facile si tu daignes te servir de l'enregistreur de macro - on peut t'aider aussi) ?

A te lire.

Bonjour Seb,

Merci pour ta contribution.
Effectivement le plus dur pour l'instant c'est de copier le contenu de plusieurs fichiers excel présent dans un dossier, vu que je n'ai aucune base...
Je pense quand même pouvoir m'en sortir pour le reste avec l'enregistreur et un peu de logique.
Je regarde ça cet aprem et poste quelque chose.
Expert Programmation

Bon, l'enregistreur de macro ne va pas t'être d'un grand secours pour lister des fichiers dans un dossier. Alors je te le donne, avant que tu ne t'énerves après l'aide d'Excel... C'est plus du VBS que du VBA ;) 

  1. Dim FSO As New FileSystemObject
  2. Dim f As File
  3.  
  4. For Each f In FSO.GetFolder("ton dossier")
  5. If LCase(f.Name) Like "*.xls" Then
  6. MsgBox "Il faut faire quelque chose du fichier """ & f.Path & """"
  7. End If
  8. Next


Tips : Pour que FileSystemObject soit connu d'Excel, il faut ajouter Microsoft Scripting Runtime (%windir%\System32\scrrun.dll) à tes références.

Je viens de voir ton post, je m'y penche de suite.

Voilà l'idée un peu si c'est plus compréhensible.



  1. Ovrir dossier X
  2.  
  3. Assigner un numéro de 1 à X en fonction du nombre de fichier
  4.  
  5.  
  6. If fichier X
  7. Then open fichier X; lbl 1;
  8. Sheets("Feuil1").Select;
  9. Cells.Select;
  10. Selection.Copy;
  11. open fichier maitre;
  12. sheets("Feuil(X)).select;
  13. ActiveSheet.paste;
  14. Sheets("Feuil(X+1)").select;
  15. Else lbl2;
  16.  
  17. lbl2; If fichier (X+1);
  18. then open fichier (X+1); goto 1;
  19. Else stop
  20.  
  21. End


edit: oups pardon :) 
Expert Programmation

(Attention, si le modérateur s'aperçoit que tu prends des libertés avec le règlement, ça va barder. Utilise la balise [code] pour présenter ton code ;)  )
Expert Programmation

C'est marrant, ça. Je te file le code pour parcourir les fichiers avec une jolie boucle For et tu me sors une horreur de code, digne des pires années 1985 avec des labels et des Goto. :vomi:  <-- j'aime pô les gotoux

Bon, on a quelques idées sur la copie, on a la boucle sur les fichiers. Propose-moi de quoi ouvrir un classeur et on aura presque tous les éléments.

hoo un peu d'indulgence :) 
C'est mes restes de souvenirs de mes années lycée où on s'amusait à faire des programmes sur les calculettes...

Je construis et te propose.

edit: j'avous que c'est quand même horriblement môche... :/ 

Voilà ce que j'ai pu trouvé jusqu'à maintenant, si tu peux me dire ce que tu en penses, notamment au niveau du problème à l'endroit précisé.

  1. Option Explicit
  2. Sub test()
  3.  
  4.  
  5. Dim Fso As Object
  6. Dim MonRepertoire As String, f As Object
  7. Dim f1 As Object
  8. Set Fso = CreateObject("Scripting.FileSystemObject")
  9. MonRepertoire = "D:\QuestionnaireTP"
  10.  
  11. For Each f In Fso.GetFolder(MonRepertoire).Files
  12. Workbooks(f).Worksheets("feuil1").Copy 'problème à ce niveau
  13. Workbooks.Open ("maitre.xls")
  14. Sheets("Feuil1").Paste
  15. Worksheets("Feuil1").Name = Sheets("Feuil1").Cells("D4")
  16. Worksheets.Add
  17.  
  18.  
  19.  
  20. Next f
  21.  
  22. End Sub
Expert Programmation

  1. Option Explicit
EXCELLENT !!!!!!!!!!!!!!!!!!
Rien que ça, ça donne envie de t'aider
  1. Sub test()
  2. Dim Fso As Object
  3. Dim MonRepertoire As String, f As Object
Euh, ne t'ai-je pas proposé d'ajouter Microsoft Scripting Runtime à tes références,
et de déclarer FSO comme un New FileSystemObject et f comme un File ??
Tu peux faire autrement, mais donne-moi l'impression que je sers à quelque chose : ça ne donne pas envie de t'aider :/ 
  1. Dim f1 As Object
euh... ???
  1. Set Fso = CreateObject("Scripting.FileSystemObject" )
  2. MonRepertoire = "D:\QuestionnaireTP"
  3.  
  4. For Each f In Fso.GetFolder(MonRepertoire).Files
Faut l'ouvrir, le classeur f, avant de l'utiliser !
Et où as-tu vérifier qu'il s'agissait d'un classeur Excel ?
  1. Workbooks(f).Worksheets("feuil1" ).Copy 'problème à ce niveau
Ah, ça c'est bien. C'est comme cela qu'on ouvre un classeur
Mais je me demande s'il est bien judicieux de l'ouvrir autant de fois qu'il y a de fichiers.
  1. Workbooks.Open ("maitre.xls" )
Oui mais de quel classeur ?
  1. Sheets("Feuil1" ).Paste
Raté. Cells() attend des coordonnées; Pour D4, c'est (4,4).
Utilise Range() si tu préfères la notation alphanumérique
  1. Worksheets("Feuil1" ).Name = Sheets("Feuil1" ).Cells("D4" )
Euh, n'aurait-il pas fallu le faire avant ?
  1. Worksheets.Add
  2. Next f
Le f est optionnel. Indispendable en 1985 quand on n'avait pas encore inventé l'indentation que tu respectes : ça c'est très bien !
  1. End Sub


Bon, ben il faut tout récrire ! :o 
( :D  )

  1. Option Explicit
  2.  
  3. Sub test()
  4. ' // Ajoute Microsoft Scripting Runtime à tes références.
  5. Dim FSO As Scriting.FileSystemObject
  6. Dim file_quesTP As Scriting.File
  7.  
  8. ' // Quelques variables
  9. Dim wb_maitre As Workbook
  10. Dim wb_quesTP As Workbook
  11. Dim ws_maitre_der As Worksheet
  12.  
  13. ' // On ouvre le classeur maître
  14. Set wb_maitre = Workbooks.Open("un_chemin\maitre.xls")
  15.  
  16. ' // On cherche sa dernière feuille
  17. Set ws_maitre_der = wb_maitre.Worksheets(wb_maitre.Worksheets.Count)
  18.  
  19. For Each file_quesTP In FSO.GetFolder("D:\QuestionnaireTP").Files
  20.  
  21. ' // On vérifie a priori que le fichier est un classeur (XLS)
  22. If UCase(file_quesTP.Name) Like "*.XLS" Then
  23. ' // On ouvre le classeur quesTP en lecture seule
  24. Set wb_quesTP = Workbooks.Open(file_quesTP.Path, ReadOnly:=True)
  25.  
  26. ' // On copie la première page du quesTP dans le classeur maître, tout à la fin
  27. wb_quesTP.Worksheets(1).Cells.Copy After:=ws_maitre_der
  28.  
  29. ' // On cherche la dernière feuille du maître qui est la nouvelle feuille
  30. Set ws_maitre_der = wb_maitre.Worksheets(wb_maitre.Worksheets.Count)
  31.  
  32. ' // On donne un ptit nom à la nouvelle feuille
  33. ws_maitre_der.Name = wb_quesTP.Worksheets(1).Range("D4")
  34.  
  35. ' // On ferme le classeur quesTP, sans rien enregistrer - euh, à quoi sert le readonly alors ???
  36. wb_quesTP.Close SaveChanges:=False
  37. End If
  38. Next
  39.  
  40. ' // On enregistre et on ferme le classeur maître
  41. wb_maitre.Save
  42. wb_maitre.Close SaveChanges:=False ' // paraniac coding
  43. End Sub


Et voilà :sol: 

(Il manque encore la gestion des erreurs si un classeur ne peut pas être ouvert, enregistré, etc.)

Bonjour Zeb!

Un grand merci pour ces précisions.

Très bon pédagogue qui donne envie de se plonger concrètement dans les macros...

Je vais avoir besoin de toi encore, je suis entrain de terminer une autre partie et j'aimerai que tu me dises ce que tu en penses mais surtout si il y a une meilleur écriture car je pense que c'est un peu brouillon même si ça marche.

Et voila le second code que j’intégrerai au premier.

  1. Option Explicit
  2. Sub test()
  3. '
  4. ' Macro2 Macro
  5. '
  6. Dim R As String
  7. Dim X As Integer
  8. Dim y As Integer
  9. Dim z As Integer
  10. Dim p As Integer
  11. Dim u As Integer
  12.  
  13.  
  14. Dim Cellule(23) As Integer
  15.  
  16. p = 5
  17.  
  18. For u = 2 To Worksheets.Count
  19.  
  20.  
  21. Worksheets(u).Select
  22.  
  23. R = Range("D4")
  24. Cellule(1) = Range("D13")
  25. Cellule(2) = Range("D14")
  26. Cellule(3) = Range("D15")
  27. Cellule(4) = Range("d16")
  28. Cellule(5) = Range("d20")
  29. Cellule(6) = Range("d21")
  30. Cellule(7) = Range("d22")
  31. Cellule(8) = Range("d26")
  32. Cellule(9) = Range("d27")
  33. Cellule(10) = Range("d28")
  34. Cellule(11) = Range("d29")
  35. Cellule(12) = Range("d37")
  36. Cellule(13) = Range("d38")
  37. Cellule(14) = Range("d39")
  38. Cellule(15) = Range("d43")
  39. Cellule(16) = Range("d44")
  40. Cellule(17) = Range("d45")
  41. Cellule(18) = Range("d53")
  42. Cellule(19) = Range("d54")
  43. Cellule(20) = Range("d55")
  44. Cellule(21) = Range("d59")
  45. Cellule(22) = Range("d60")
  46. Cellule(23) = Range("d61")
  47.  
  48.  
  49. Sheets(1).Select
  50.  
  51. y = 3
  52.  
  53.  
  54.  
  55.  
  56. For X = 1 To 23
  57.  
  58.  
  59.  
  60. z = Cellule(X)
  61. Worksheets(1).Cells(p, y).Value = z
  62.  
  63. X = X + 1
  64. y = y + 1
  65.  
  66. Next
  67.  
  68. Worksheets(1).Cells(p, 2).Value = R
  69.  
  70. p = p + 1
  71.  
  72.  
  73. Next u
  74.  
  75.  
  76.  
  77. End
  78.  
  79.  
  80.  
  81. End Sub


J'ai testé et il marche, mais il y a un soucis.
Comme tu le vois, les données que je veux récupérer dans un questionnaire sont en colonne et espacées. Je veux les mettre en ligne et ra-coller. Il y a bien le copier/coller mais ce n'est pas les bonnes données ou mal copiées.

Une idée?

Merci :) 
Expert Programmation

Beurk. j'aime pô voir des Select dans une macro.
Au lieu d'écrire
  1. ' // Code moche
  2. Worksheets(u).Select
  3.  
  4. R = Range("D4" )
  5. Cellule(1) = Range("D13" )
  6. Cellule(2) = Range("D14" )
écris :
  1. ' // Code efficace
  2. R = Worksheets(u).Range("D4" )
  3. Cellule(1) = Worksheets(u).Range("D13" )
  4. Cellule(2) = Worksheets(u).Range("D14" )
C'est un peu plus lourd à écrire, c'est vrai. Mais tu peux aussi utiliser une variable que tu substitues aux objects que tu utilises de façon récurrente :
  1. Dim ws_source As Worksheet
  2. Dim ws_cible As Worksheet
  3.  
  4. ...
  5.  
  6. Dim ws_source = Worksheets(1)
  7. Dim ws_cible = Worksheets(u)


------------

  1. y = 3
  2. For X = 1 To 23
  3. z = Cellule(X)
  4. Worksheets(1).Cells(p, y).Value = z
  5.  
  6. X = X + 1
  7. y = y + 1
  8. Next
Rhoolala, mais quelle horreur !!!!!!
Interdiction ABSOLUE de toucher à la variable d'itération dans une boucle For :o 
Quant à Y, m'enfin, réfléchis. Quelque soit x, y = x + 2.
  1. For x = 1 To 23
  2. Worksheets(1).Cells(p, x + 2).Value = Cellule(x)
  3. Next
T'as vu, j'ai viré z. Faut pas exagérer.

------------

  1. Cellule(1) = Range("D13" )
  2. Cellule(2) = Range("D14" )
  3. Cellule(3) = Range("D15" )
  4. Cellule(4) = Range("d16" )
  5. Cellule(5) = Range("d20" )
  6. Cellule(6) = Range("d21" )
  7. Cellule(7) = Range("d22" )
  8. Cellule(8) = Range("d26" )
  9. Cellule(9) = Range("d27" )
  10. Cellule(10) = Range("d28" )
  11. Cellule(11) = Range("d29" )
  12. Cellule(12) = Range("d37" )
  13. Cellule(13) = Range("d38" )
  14. Cellule(14) = Range("d39" )
  15. Cellule(15) = Range("d43" )
  16. Cellule(16) = Range("d44" )
  17. Cellule(17) = Range("d45" )
  18. Cellule(18) = Range("d53" )
  19. Cellule(19) = Range("d54" )
  20. Cellule(20) = Range("d55" )
  21. Cellule(21) = Range("d59" )
  22. Cellule(22) = Range("d60" )
  23. Cellule(23) = Range("d61" )
M'ouhais ... :/  Alors d'abord, il manque la référence à la feuille, (puisqu'on vire le Select :whistle:  ).
Et puis, dans ce cas, je verrais bien une notation numérique (Cells() plutôt que Range()).
Pour finir, ce n'est pas la cellule, mais la valeur de la cellule que tu mets dans ta variable.
  1. Cellule(1) = CInt(Worksheets(u).Cells(13, 4).Value)
  2. Cellule(2) = CInt(Worksheets(u).Cells(14, 4).Value)
  3. Cellule(3) = CInt(Worksheets(u).Cells(15, 4).Value)
  4. ...
C'est un peu lourd. Je verrai bien une correspondance entre les lignes, plutôt :

1 -> 13
2 -> 14
3 -> 15
4 -> 16
5 -> 20

On peut le mettre dans un tableau comme tu as fait. Mais je préfère l'écriture avec un type Array() :
  1. Dim racollage As Variant
  2. racollage = Array(14, 15, 16, 20, 21, 22, 26, 27, 28, 29, 37, 38, 39, 43, 44, 45, 53, 54, 55, 59, 60, 61)
Faut juste faire gaffe au fait que le premier indice est 0.
Tout ceci donne cela :
  1. Dim racollage As Variant
  2. Dim ws_source As Worksheet
  3. Dim ln_cible As Range
  4. Dim x As Integer
  5.  
  6. racollage = Array(14, 15, 16, 20, 21, 22, 26, 27, 28, 29, 37, 38, 39, 43, 44, 45, 53, 54, 55, 59, 60, 61)
  7.  
  8. Set ln_cible = Worksheets(1).Rows(5)
  9.  
  10. For u = 2 To Worksheets.Count
  11. Set ws_source = Worksheets(u)
  12. ln_cible.Cells(2).Value = ws_source.Range("D4" )
  13. For x = 0 To UBound(racollage)
  14. ln_cible.Cells(x + 3).Value = ws_source.Cells(racollage(x), 4)
  15. Next
  16. Set ln_cible = ln_cible.Offset(1)
  17. Next


------------------------------

Que penses-tu de " l'idée " ? ;) 

Je pense que je ne comprends pas bien, mais elle doit surement être bonne. :) 

En supprimant le "X = X+1" la macro que j'ai écrite fonctionne parfaitement. Néanmoins je veux comprendre ton écriture.


  1. Dim racollage As Variant 'ok
  2. Dim ws_source As Worksheet 'ok
  3. Dim ln_cible As Range 'ok
  4. Dim x As Integer 'ok
  5. racollage = Array(14, 15, 16, 20, 21, 22, 26, 27, 28, 29, 37, 38, 39, 43, 44, 45, 53, 54, 55, 59, 60, 61) 'ok
  6. Set ln_cible = Worksheets(1).Lines(5) 'excel me dit qu'il y a une erreur, je vois pas où....
  7. For u = 2 To Worksheets.Count 'ok
  8. Set ws_source = Worksheets(u) 'ok
  9. ln_cible.Cells(2).Value = ws_source.Range("D4" ) 'ok
  10. For x = 0 To UBound(racollage)
  11. ln_cible.Cells(x + 3).Value = ws_source.Cells(racollage(x), 4) 'humm
  12. Next
  13. Set ln_cible = ln_cible.Offset(1) 'ok
  14. Next



Edit : En relisant bien j'ai tout compris sauf l'erreur : set In_cible = WorkSheets(1).Lines(5)...

Je m'y penche, je m'y penche... :) 

Quoi qu'il en soit, j'ai terminé ce que je voulais et la macro fonctionne parfaitement.

  1. Option Explicit
  2. Sub test()
  3. Dim FSO As Object
  4. Dim file_quesTP As Object
  5. ' // Quelques variables
  6. Dim wb_maitre As Workbook
  7. Dim wb_quesTP As Workbook
  8. Dim ws_maitre_der As Worksheet
  9. Set FSO = CreateObject("Scripting.FileSystemObject")
  10. ' // On ouvre le classeur maître
  11. Set wb_maitre = Workbooks.Open("D:\QuestionnaireTP\rom\maitre.xlsx")
  12. ' // On cherche sa dernière feuille
  13. Set ws_maitre_der = wb_maitre.Worksheets(wb_maitre.Worksheets.Count)
  14.  
  15. For Each file_quesTP In FSO.GetFolder("D:\QuestionnaireTP").Files
  16. ' // On vérifie a priori que le fichier est un classeur (XLS)
  17. If UCase(file_quesTP.Name) Like "*.XLSX" Then
  18. ' // On ouvre le classeur quesTP en lecture seule
  19. Set wb_quesTP = Workbooks.Open(file_quesTP.Path, ReadOnly:=True)
  20. ' // On copie la première page du quesTP dans le classeur maître, tout à la fin
  21. wb_quesTP.Worksheets(1).Copy After:=ws_maitre_der
  22. ' // On cherche la dernière feuille du maître qui est la nouvelle feuille
  23. Set ws_maitre_der = wb_maitre.Worksheets(wb_maitre.Worksheets.Count)
  24.  
  25. ' // On donne un ptit nom à la nouvelle feuille
  26. ws_maitre_der.Name = wb_quesTP.Worksheets(1).Range("D4")
  27. ' // On ferme le classeur quesTP, sans rien enregistrer - euh, à quoi sert le readonly alors ???
  28. wb_quesTP.Close SaveChanges:=False
  29. End If
  30. Next
  31.  
  32. Dim R As String
  33. Dim X As Integer
  34. Dim y As Integer
  35. Dim z As Integer
  36. Dim p As Integer
  37. Dim u As Integer
  38. Dim Cellule(23) As Integer
  39. p = 5
  40. For u = 2 To Worksheets.Count
  41. Worksheets(u).Select
  42. R = Range("D4")
  43. Cellule(1) = Range("D13")
  44. Cellule(2) = Range("D14")
  45. Cellule(3) = Range("D15")
  46. Cellule(4) = Range("d16")
  47. Cellule(5) = Range("d20")
  48. Cellule(6) = Range("d21")
  49. Cellule(7) = Range("d22")
  50. Cellule(8) = Range("d26")
  51. Cellule(9) = Range("d27")
  52. Cellule(10) = Range("d28")
  53. Cellule(11) = Range("d29")
  54. Cellule(12) = Range("d37")
  55. Cellule(13) = Range("d38")
  56. Cellule(14) = Range("d39")
  57. Cellule(15) = Range("d43")
  58. Cellule(16) = Range("d44")
  59. Cellule(17) = Range("d45")
  60. Cellule(18) = Range("d53")
  61. Cellule(19) = Range("d54")
  62. Cellule(20) = Range("d55")
  63. Cellule(21) = Range("d59")
  64. Cellule(22) = Range("d60")
  65. Cellule(23) = Range("d61")
  66.  
  67.  
  68. Sheets(1).Select
  69. y = 3
  70.  
  71.  
  72.  
  73.  
  74. For X = 1 To 23
  75.  
  76. z = Cellule(X)
  77. Worksheets(1).Cells(p, y).Value = z
  78.  
  79. y = y + 1
  80.  
  81. Next
  82. Worksheets(1).Cells(p, 2).Value = R
  83. p = p + 1
  84. Next u
  85.  
  86. End
  87.  
  88. End Sub


Mais je vais essayer de le refaire correctement à partir de ton écriture pour mieux comprendre.

Merci vraiment pour tout, et surement à bientôt ;) 
Lassé par la pub ? Créez un compte