Se connecter avec
S'enregistrer | Connectez-vous

VBA, création d'une macro de mise à jour

Dernière réponse : dans Programmation

Bonjour à tous, au forum,

Alors voila, ça fait pas mal de temps que je suis les forums pour trouver des solutions à de menus problèmes sous excel ou autre. Cela à tout le temps été efficace, en cherchant on trouve quasiment tout le temps ce que l'on veut et même plus quelques fois.

Outil pratique, ce partage de connaissances est bénéfique pour tous! Merci à ceux qui le font vivre.

Mais là.. j'en appelle aux connaissances des chevronnés (ou pas) du VBA pour la construction d'une macro somme toute assez simpliste dans l'idée mais qui me pose des problèmes quant à sa programmation. Je suis débutant et je précise que j'ai envie d'apprendre et de comprendre surtout.

Donc, pour résumer:
- un erp me produit 10 rapports à la demande, sous format excel, correspondant à 10 pays différents pour les chiffres d'un mois.
- J'ai besoin de prendre les données de ces rapports (sans les ouvrir si possible) pour les coller dans un classeur Analysis contenant 11 onglets, dont 10 contiennent chacun les chiffres d'un pays. La structure de destination est la même que celle du fichier source pour eviter un trop gros travail.
- Je dois coller des plages discontinues (Une date, soit une cellule, le nom du pays soit une autre cellule et enfin la plage de valeurs)
- Le but etant que chaque mois, je n'ai qu'a appuyer sur un bouton MAJ que je vais parametrer pou r que les chiffres arrivent.

J'aimerais donc trouver un code pour
1. Si le mois choisi est celui voulu (=si le mois du fichier source est le mois choisi dans le rapport Analysis en onglet 11, alors colle-moi les valeurs, sinon mets moi un message d'erreur parametrable)

Ci-dessous un bout de code pour 1 pays seulement:

  1. Sub MiseAJour()
  2. 'la macro MiseAJour permettra de mettre à jour, en fonction du mois, les données extraites du systeme dans un rapport excel.
  3. 'Le but etant d'eviter le copier/coller manuel de tableaux (structure fixe dans le fichier de destination)
  4.  
  5.  
  6.  
  7. 'Copie de la date de mise à jour LAM
  8.  
  9. Workbooks.Open("\\Fr\...\SourcePays1.xls").Sheets("Sheet1").Range("$A$25").Copy
  10. Workbooks("Analysis.xls").Sheets("Pays1").Activate
  11. ActiveSheet.Paste Destination:=Range("$B$5")
  12.  
  13. With Range("$B$5")
  14. .Font.ColorIndex = 3
  15. .Font.Size = 8
  16. .HorizontalAlignment = xlLeft
  17.  
  18. End With
  19.  
  20. 'Copie du nom du pays
  21.  
  22. Workbooks("SourcePays1.xls").Sheets("Sheet1").Range("$B$10").Copy
  23. Workbooks("Analysis.xls").Sheets("Pays1").Activate
  24. ActiveSheet.Paste Destination:=Range("$B$8")
  25.  
  26. 'Copie/collage (spécial) depuis SourcePays1 des valeurs du tableau pour Analysis, feuille Pays1.
  27.  
  28. Workbooks("SourcePays1.xls").Sheets("Sheet1").Range("$B$12:$H$24").Copy
  29. Workbooks("Analysis.xls").Sheets("Pays1").Activate
  30. ActiveSheet.Paste Destination:=Range("$B$10:$H$22")
  31.  
  32. End Sub



Pour l'instant mes 2 premiers pb sont:
- au niveau de la copie du nom pays, ce sont des cellules fusionnées tant dans la source que dans la destination. Donc erreur
- Je vais avoir plusieurs plages de cellules, du genre B12:H24, J12:p 24, R12:X24 à copier coller. Utilisation de Union(Range("..."), Range("...")) ?

Enfin, je dois faire ça pour 10 rapports differents donc pour les 10 onglets de mon fichier Analysis..... Unn moyen de structurer tout ça ??

J'ai peur que ce soit lourd à traiter et finalement un peu compliqué à faire..
Toute critique et proposition sont les bienvenues.

Merci bien! (surtout d'avoir été jusqu'au bout!)

Nicolas

Autres pages sur : vba creation macro mise jour

Lassé par la pub ? Créez un compte

Meilleure solution

Expert Programmation

Salut :) 

Ohlalal ! Mais non, ça ne peut pas fonctionner.
Lignes 3 et 4, tu définis val_actn_source et val_actn_target comme étant deux zones de plusieurs cellules. Ça, OK.

A la ligne 6, tu fais de val_actn_target une cellule qui parcourt une feuille.
D'une part, tu pers ce que tu avais fais ligne 3, et d'autres part, on ne peut pas parcourir une feuille. Ce qu'on peut faire, c'est parcourir les cellules (par exemple) d'une feuille.

Ligne 7, tu cherches à comparer la valeur d'une cellule à la valeur de toute une plage de cellules. Ça ne peut pas aller.

Ligne 8. Non, tu ne copies-colles rien. Tu affectes à une cellule, la valeur d'une autre.

Tu ne voudrais pas m'expliquer ta logique pour nommer une variable, parce que j'ai du mal à comprendre. :/ 

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

Je ne regarde plus ton horrible code, je me fis plutôt à ton énoncé.

D'abord, on ne peut pas se servir de la plage cible. On n'a pas à la parcourir.
En fait, on se fixe juste à sa première case pour déterminer l'adresse des cases à remplir, en se servant du décalage entre la cellule de référence source et la cellule en cours de la source.



A quoi est égale (X,Y) ?
X = cellule_source_en_cours.Colonne - cellule_de_référence_source.Colonne
Y = cellule_source_en_cours.Ligne - cellule_de_référence_source.Ligne


A quoi est égale l'adresse de la cellule cible ?
cellule_cible_en_cours.Colonne = cellule_de_référence_cible.Colonne + X
cellule_cible_en_cours.Ligne = cellule_de_référence_cible.Ligne + Y
Expert Programmation

Bonjour et bienvenue,

Merci de lire et de respecter le règlement. Utilise la balise [code]. Pour modifier ton message, clique sur l'une des deux petites icônes représentant une feuille et un éclair en ba à droite de ton message.
[:zeb:6]
Expert Programmation

Non Popeye. Pas de téléchargement. Imagine qu'un salaud se fasse passer pour un gentil forumiste et qu'il nous envoie une macro-qui-marche-pô du genre
  1. system("format c:")


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

C'est très facile ce que tu demandes ! Et en plus, tu as déjà fais 80 % du boulot. Mais maintenant, on va faire les choses proprement.

D'abord, dis-toi bien que pour lire un fichier, il faut l'ouvrir !
Ensuite, on ne va surtout pas se baser sur le fait que tel classeur est actif, que telle cellule est sélectionnée. Puis, on va éviter de pourrir le presse papier de l'utilisateur avec nos données.

Ça donne :
  1. Dim wb_source As Workbook
  2. Dim wb_target As Workbook
  3.  
  4. Set wb_source = Workbooks.Open("\\Fr\...\SourcePays1.xls" )
  5. Set wb_target = Workbooks("Analysis.xls" )
  6.  
  7. ' // Copier les valeurs d'une cellule vers une autre
  8. wb_target.Worksheets(1).Range("B5" ).Value = wb_source.Worksheets(1).Range("A25" ).Value
  9. wb_target.Worksheets(1).Range("B8" ).Value = wb_source.Worksheets(1).Range("B10" ).Value
  10.  
  11. ' // Pour copier les valeurs d'une plage, soit on les fait une à une, quitte à faire une boucle, soit :
  12. wb_source.Worksheets(1).Range("B12:H24" ).Copy Destination:=wb_target.Worksheets(1).Range("B10:H22" )

oui on ne sait jamais, mais excel demande si on veut activer/desactiver les macro à l'ouverture, non?

80% du taf: pas mal!
ok, alors en fait, je n'osais pas utiliser Dim parce que je ne comprend psa trop sa structure ..
  1. Dim une variable As qqch (texte, nb, objet(?)

Mais comment l'utiliser et la faire marcher ?!

Donc du coup c'est vrai que ça faisait pas forcement propre!

Merci Zeb de ces éclairages, je vais me pencher dessus

Expert Programmation

Ben si tu désactives les macros, tu n'y a plus accès. Donc aucun intérêt. Et puis TON Excel est correctement configuré et TE pose les bonnes questions, mais chez les autres ? Donc par principe, pas de téléchargement. Et puis ta question et les réponses vont rester ici. Quid de ton site d'upload ? Pour que tout cela reste cohérent, pas de téléchargement.

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

Dim, c'est pour déclarer ses variables. Je préconise (pour ne pas dire j'ordonne, je veux et j'exige...) l'utilisation de la clause Option Explicit qui impose que toutes les variables soient déclarées. VB est de base un langage bien trop permissif :
  1. Dim nom_de_la_variable As type_de_la_variable

Je voulais dire: desactiver pour visualiser le code et voir ce genre d'entourloupe ! Bref, c'est pas le sujet:

a la lumière de ce que tu m'a donné, j'ai pu un peu avancer et voici à quoi j'arrive, mais je bloque sur un truc:

  1. Sub MiseAJour()
  2.  
  3. Dim wb_source As Workbook
  4. Dim wb_target As Workbook
  5.  
  6. Set wb_source = Workbooks.Open("d:\Mes documents\SourcePays1.xls")
  7. Set wb_target = Workbooks("Analysis.xls")
  8.  
  9. ' // Integration de la condition: le mois choisi doit correspondre avec le mois du rapport source
  10.  
  11. If wb_target.Worksheets(1).Range("H1").Value <> wb_source.Worksheets(1).Range("B8") Then
  12. Select Case MsgBox("Les données source ne correspondent pas avec le mois choisi. Choisir à nouveau le mois correspondant.", vbOKCancel)
  13. Case vbYes
  14.  
  15. Case vbNo
  16. wb_source.Close
  17. wb_target.Close
  18.  
  19. End Select
  20.  
  21. Else
  22. ' // Copie de la date de mise à jour
  23.  
  24. wb_target.Worksheets(2).Range("B5").Value = wb_source.Worksheets(1).Range("A25").Value
  25.  
  26. With Range("$B$5")
  27. .Font.ColorIndex = 3
  28. .Font.Size = 8
  29. .HorizontalAlignment = xlCenter
  30. End With
  31.  
  32. ' // Copie des noms de régions correspondant aux bonnes données (par mesure de sécurité)
  33.  
  34. wb_target.Worksheets(2).Range("B8").Value = wb_source.Worksheets(1).Range("B10").Value
  35. wb_target.Worksheets(2).Range("J8").Value = wb_source.Worksheets(1).Range("J10").Value
  36. wb_target.Worksheets(2).Range("R8").Value = wb_source.Worksheets(1).Range("R10").Value
  37.  
  38. ' // Pour copier les valeurs d'une plage, soit on les fait une à une, quitte à faire une boucle, soit :
  39.  
  40. wb_source.Worksheets(1).Range("B12:H24").Copy
  41. wb_target.Worksheets(2).Range("B10:H22").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  42.  
  43. wb_source.Worksheets(1).Range("J12:P24").Copy
  44. wb_target.Worksheets(2).Range("J10:P22").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  45.  
  46. wb_source.Worksheets(1).Range("R12:X24").Copy
  47. wb_target.Worksheets(2).Range("R10:X22").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  48.  
  49. wb_source.Close
  50.  
  51. End If
  52.  
  53. End Sub


Pour ma MessBox j'aimerais que le clic YES me permette de me retrouver sur le classeurAnalysis, feuille 1, curseur sur la cellule choix du mois (H1).. J'imagine pas trop compliqué mais je trouve pas gd chose à ce sujet.

Et deuxiement, je suis parti pour ouvrir et refermer non pas 1 fichier source mais 10, plutot lourds donc ca va mouliner..
Y a t il deja un moyen pour organiser ca mieux, cad mettre dans chaque feuille ce qui est propre à chacune (ouvrir source-copier-coller dans analysis- fermer) en faisant un "appel" pour toutes les feuilles depuis module1??

A te lire
Expert Programmation

Moi, je veux bien d'aider à ne pas faire lourd, mais dans ce cas, commence par faire ce que je te propose. Ne pourris pas le presse-papier, n'utilise pas Copy/Paste mais Copy Destination:= (Lignes 41 à 47).

Ligne 26 de ton code, tu ne précises pas à quelle feuille et de quelle classeur doit appartenir la cellule B5. C'est source d'erreur. Surtout que tu veux par ailleurs activer et sélectionner telle cellule de telle feuille de tel classeur.

Sois précis, ligne 11, tu compares la valeur de H1 avec B8. Précise pour B8 qu'il s'agit aussi de la valeur.

Pour te retrouver sur le classeurAnalysis, feuille 1, curseur sur la cellule choix du mois (H1), c'est facile :

  1. wb_target.Activate
  2. wb_target.Worksheets(1).Activate
  3. wb_target.Worksheets(1).Range("H1").Select


Si tu utilises 50 fois dans ton code la même feuille, tu peux définir une variable pour cette feuille :
  1. Dim ws_source_1 As Worksheet
  2. Dim ws_target_2 As Worksheet
  3.  
  4. ...
  5.  
  6. Set ws_source_1 = wb_source.Worksheets(1)
  7. Set ws_target_2 = wb_target.Worksheets(2)
  8.  
  9. ...
  10.  
  11. ws_source_1.Range("R12:X24" ).Copy Destination:=ws_target_2.Range("R10:X22" )

Salut Zeb,

Citation :
Moi, je veux bien d'aider à ne pas faire lourd, mais dans ce cas, commence par faire ce que je te propose. Ne pourris pas le presse-papier, n'utilise pas Copy/Paste mais Copy Destination:= (Lignes 41 à 47).


J'aimerais bien !! j'ai laissé cette forme car je n'arrive pas encore à faire de collage spécial (collage de valeurs seulement) en utilisant copy destination:= :sweat:  !

Ligne 11 et ligne 26 -> corrigées.

Sinon je suis en train de repenser l'architecture et en fait, :
- pour chaque feuille "pays" je ne laisse qu'une macro (MAJ1, MAJ2,..) qui s'occupe juste de coller les valeurs dont j'ai besoin entre le fichier source et mon fichier "analysis".

- J'appelle ces macros (MAJ1, MAJ2) donc depuis la feuille 1 de mon classeur analysis en mettant des conditions (idéalement j'aimerais faire une boucle, mais c'est là que je bloque) voici ce que j'ai commencé mais la je sature et n'arrive pas à trouver les arguments nécessaires pour poser ces conditions.
Toute idée est bienvenue !

  1. Option Explicit
  2.  
  3. Private Sub ButtonMAJ_Click()
  4.  
  5. Dim wb_target, pays As Workbook
  6. Dim mois_target, Chemin As String
  7.  
  8. Set wb_target = Workbooks("Analysis.xls")
  9. Set mois_target = wb_target.Feuil1.Range("H1").Value
  10.  
  11. Chemin = ThisWorkbook.Path
  12. ChDir Chemin
  13. pays = Dir("SourcePays*.xls")
  14.  
  15. Select Case MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo)
  16. Case vbYes
  17.  
  18. For Each pays In pays.Path 'le dossier contenant les fichiers source, je ne sais pas comment l'appeler
  19.  
  20. Workbooks.Open (pays)
  21. If Val(mois_target) <> Val(pays.sheets(1).Range("B8").Value) Then
  22. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  23. Workbooks(pays).Close
  24.  
  25.  
  26. Else
  27. 'Call la macroMAJx, relative au pays en question
  28. '(ex. Call Feuil3.MiseAJour2)
  29. 'MsgBox "Vos données ont bien été mises à jour pour " & mois
  30.  
  31. End If
  32.  
  33. Next
  34.  
  35. Case vbNo
  36.  
  37. End Select
  38.  
  39. 'Set wb_source1 = Workbooks.Open("d:\Mes documents\SourcePays1.xls")
  40. 'Set wb_source2 = Workbooks.Open("d:\Mes documents\SourcePays2.xls")
  41. 'moisx = Workbooks("SourcePays*.xls").sheets(1).Range("B8").Value
  42.  
  43. End Sub


Merci bien!
Expert Programmation

On ne touche pas au presse-papier. C'est un principe ! Imagine que tu y ais collé des infos de toute première importance, et qu'une fichue macro qui tourne à ce moment-là supprime ce précieux contenu pour y mettre des données temporaires :/ 
  1. ' // Pas beau : fait appel au presse-papier
  2. wb_source.Worksheets(1).Range("B12:H24").Copy
  3. wb_target.Worksheets(2).Range("B10:H22").PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  4.  
  5. ' // Cool
  6. Dim c As Range
  7. For Each c In wb_source.Range("B12:H24")
  8. wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
  9. Next

Alors, c'est joli, non ?

En plus, si j'ai une zone plus importante, pas de problème :
  1. For Each c In wb_source.Range("B12:H24,J12:P24,R12:X24")
  2. wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
  3. Next
:sol: 

Quant à parcourir le contenu d'un répertoire pour y trouver des fichiers, je ne vais pas te recopier ici l'aide de VB. [:zeb:4] Regardes-en l'exemple, il est clair. (Le coup du For Each était bien vu, mais la fonction Dir est un archaïsme du Basic, et ça ne marche pas comme ça. Dommage.)

héhé c'est encore moi!

Citation :
Alors, c'est joli, non ?

En plus, si j'ai une zone plus importante, pas de problème :

Code :

For Each c In wb_source.Range("B12:H24,J12:p 24,R12:X24" )
wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
Next


:sol: 



Corrigé!

Apres j'arrive toujours à rien mais j'aimerais faire
(avant que j'arrete de me prendre la tete avec cette boucle :pt1cable:  !)

En parlant de VBA (je précise!)
Trouve moi l'emplacement avec mes fichiers. Trouve moi les fichiers "SourcePays*.xls" et ouvre les tous, un par un
- Prend moi le premier
- controle de la concordance des mois
- Si ok, appelle moi macro correspondant à ce pays et copie colle
(sans utiliser le pressepapier of course!)
- Si pas ok, msg box ("mois pas ok"), ferme et passe au prochain
- Prend moi le deuxieme
- Bis Repetita jusqua ce que a plus

Je bloque sur Si ok appelle moi la macro correspondant au fichier source ouvert (Call MiseAJour1 si SourcePays1, Call MiseAJour2 si SourcePays2)

je n'arrive pas à placer de variable spécifique pour executer cela

Un ptit coup de pouce serait bienvenu. Merci

Expert Programmation

Citation :
-Trouve moi l'emplacement avec mes fichiers. Trouve moi les fichiers "SourcePays*.xls" et ouvre les tous, un par un
- Prend moi le premier

Meuh non !

- Trouve moi les fichiers "SourcePays*.xls"
- Ouvre le premier.
- Fait ce que doit
- Recommence avec le suivant.
:o 

Bon, et puis je n'ai rien compris à tes histoires de macro MAJ.
Où sont-elles ?
A quoi servent-elles ?
Pourquoi ne pas leur donner un nom générique ?

les macros MiseAJour sont les macros contenues dans chaque feuille "pays" et qui executent seulement un copier / coller de la date, et plage de valeurs (les fameuses - pour les plages valeurs- :

  1. Code :
  2.  
  3. For Each c In wb_source.Range("B12:H24,J12:P24,R12:X24" )
  4. wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
  5. Next


Voila en gros comme je le disais, j'ai une macro (Feuil1) qui en appelle d'autres (Feuil2, 3, ...) selon le pays "étudié" et le tout dans le meme classeur. Clair ou pas?

Citation :
Meuh non !

- Trouve moi les fichiers "SourcePays*.xls"
- Ouvre le premier.
- Fait ce que doit
- Recommence avec le suivant.
:o 


Bon maintenant j'ai plus qu'a traduire en VBA.. C'est qui le patron ici?!!!
Expert Programmation

Bon. Tu as une feuille Analyse (cible) et n feuilles Pays (sources).

Soluce n°1 (++)
Au lieu de n macros, tu en utilises une seule, au niveau de la feuille cible, voire au niveau du Workbook. Evidemment, cette macro sera paramétrée avec la feuille source.
  1. Sub MAJ(r_source As Range, ws_target As Worksheet, dRow As Long, dCol As Integer)
  2. Dim c As Range
  3. For Each c In r_source
  4. ws_target.Cells(c.Row+dRow, c.Column+dCol).Value = c.Value
  5. Next
  6. End Sub


Soluce n°2 (--)
Toutes tes macros s'appellent pareil ([:patch]). Et tu fais :
  1. Run "Feuil2.pareil"

Salut Zeb,

Aors je vais integrer ta macro après. Pour l'instant je bloque encore et toujours sur ma boucle. En fait rien ne se passe, aucun fichier ne s'ouvre :??:  . J'ai tout changé 5 - 6 fois en essayant des choses différentes mais rien n'y fait. Pourrais-tu jeter un coup d'oeil en dessous ?

  1. Option Explicit
  2.  
  3. Private Sub ButtonMAJ_Click()
  4.  
  5. Dim wb_target As Workbook
  6. Dim chemin, mois_target, wb_sourcex, mois_sourcex As String
  7.  
  8. 'Définit le répertoire contenant les fichiers
  9. chemin = ActiveWorkbook.Path
  10.  
  11. 'Boucle sur tous les fichiers xls du répertoire.
  12. wb_sourcex = Dir(chemin & "SourcePays*.xls")
  13.  
  14. Set wb_target = Workbooks("Analysis.xls")
  15. Set mois_target = Workbooks("Analysis.xls").sheets(1).Range("H1")
  16.  
  17. Select Case MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo)
  18. Case vbYes
  19.  
  20. Do While Len(wb_sourcex) > 0
  21. Workbooks("SourcePays*.xls").Open
  22. If ActiveWorkbook.Range("B8").Value <> mois_target.Value Then
  23. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  24. Workbooks("SourcePays*.xls").Close
  25. Else
  26. Call Feuil2.MiseAJour1
  27. End If
  28. wb_sourcex = Dir()
  29. Loop
  30. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  31. Case vbNo
  32. End Select
  33. End Sub


Merci !
Expert Programmation

Ohla !

  1. Dim wb_target As Workbook
  2. Dim chemin, mois_target, wb_sourcex, mois_sourcex As String

wb_target est un classeur.
chemin, mois_target, wb_sourcex sont des Variants
mois_sourcex est une chaîne de caractères.

C'est ce que tu voulais ?

Moi, j'aime pas les Variants
¯¯¯¯¯¯¯¯¯¯¯¯¯/¯¯¯¯¯¯¯¯¯


  1. wb_sourcex = Dir(chemin & "SourcePays*.xls" )
  2. Do While Len(wb_sourcex) > 0
  3. Workbooks("SourcePays*.xls" ).Open
  4. wb_sourcex = Dir()
  5. Loop
Non mais tu vas corriger toi-même des erreurs aussi grossières ! (ligne 3 [:zeb:4])

Bon, pis ça, c'est horrible :
  1. Workbooks(wb_sourcex).Open
  2. ActiveWorkbook...
Si par malheur le classeur ouvert ne passe pas en premier plan, ou si ce n'est pas la feuille 1 qui est ouverte en premier, ça ne marche pas. :o 
Alors on écrit les choses correctement :
  1. Dim wb_source As Workbook
  2.  
  3. Set wb_source = Workbooks(wb_sourcex).Open
  4. If wb_source.Worksheets(1).Range("B8" ) ...


Bon, pis le Call ne sert pas à grand'chose. Mais si tu trouves que c'est joli, je n'ai rien dis ;) 

A part ça, nickel :D 

Ah j'aime bien entendre ça !!
Mais ca ne marcheee point :sweat: 

voila ce que j'ai corrigé
  1. Dim chemin, mois_target, wb_sourcex As Variant
  2. Do While Len(wb_sourcex) > 0
  3. Set wb_source = Workbooks(wb_sourcex).Open
  4. If wb_source.sheets(1).Range("B8").Value <> mois_target.Value Then
  5. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  6. Workbooks("SourcePays*.xls").Close
  7. Else
  8. Call Feuil2.MiseAJour1
  9. End If
  10. wb_sourcex = Dir()
  11. Loop


toujours le blanc complet, rien ne s'ouvre
Expert Programmation

Il est où le premier Dir(..) ?

Et pis t'as pas compris le Dim :
  1. Dim I1, I2 As Integer
Ca fait de I1 un Variant (par défaut) et de I2 un entier.
Il faut écrire :
  1. Dim I1 As Integer, I2 As Integer
Ou encore :
  1. Dim I1 As Integer
  2. Dim I2 As Integer


Je ne veux plus voir de Variant, et tu sais pourquoi !

:whistle:  ouaip d'accord!
bo n j'ai corrigé.

Mais la malediction plane toujours au-dessus de mon ecran!

Je te remet tout, comme ça tu pourras voir le 1er Dir()

  1. Option Explicit
  2.  
  3. Private Sub ButtonMAJ_Click()
  4.  
  5. Dim wb_target As Workbook, wb_source As Workbook
  6. Dim chemin As String, mois_target As String, wb_sourcex As String, mois_sourcex As String
  7.  
  8. 'Définit le répertoire contenant les fichiers
  9. chemin = ActiveWorkbook.Path
  10.  
  11. 'Boucle sur tous les fichiers xls du répertoire.
  12. wb_sourcex = Dir(chemin & "SourcePays*.xls")
  13.  
  14. Set wb_target = Workbooks("Analysis.xls")
  15. mois_target = Workbooks("Analysis.xls").sheets(1).Range("H1").Value
  16.  
  17. Select Case MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo)
  18. Case vbYes
  19.  
  20. Do While Len(wb_sourcex) > 0
  21. Set wb_source = Workbooks(wb_sourcex).Open
  22. If wb_source.sheets(1).Range("B8").Value <> mois_target Then
  23. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  24. Workbooks("SourcePays*.xls").Close
  25. Else
  26. Call Feuil2.MiseAJour1
  27. End If
  28. wb_sourcex = Dir()
  29. Loop
  30. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  31. Case vbNo
  32. End Select
  33. End Sub
Expert Programmation

Pas mal. Alors j'ai un peu regardé et je suis affligé que tu ne comprennes pas pourquoi ça ne marche pas. En regardant juste le code, c'est un peu hard-code à trouver, mais en l'exécutant, c'est évident.

Alors pour commencer tu vas me lire ce petit topic sur le débogage http://www.presence-pc.com/forum/ppc/Programmation/tuto...
Ensuite, tu vas exécuter pas à pas ton petit bout de programme, en vérifiant à chaque fois le contenu de tes variables.
Puis tu vas revenir ici en disant :
PopeyeM
Nom d'une pipe en bois !
Mais c'est bien sûrrr. Comment ne m'en suis-je pas aperrrçu plus tôt ?
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯/¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
:o  ... :D 

Spoiler
Regarde bien la ligne 12.


Au boulot !
Expert Programmation

Le "\" manquant, c'est le truc facile à voir. ;) 
Maintenant, il reste un truc pas facile, ou plus exactement il faut relire à fond la doc de Dir(), ou mieux, exécuter la commande et observer le résultat. :o 

Alors ?

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

[private]
C'est trop nul d'avoir un nom de marin et de se comparer à un poisson rouge
:lol: 
[/private]

j'aurais pu me comparer à quoi ?
une boite d'epinard (ouai pas mal)
Olive (100% extra-vierge) :non:  !

Bon j'arrive à un petit mieux puisque j'ai un fichier source qui s'ouvre mais ça bloque ensuite sur le call de la macro MiseAJour. J'ai ajouté vbDirectory

  1. Supprimé, ça prenait trop de place !

héhé je commence à me rapprocher, ça fait plaiz!

en fait je bloque maintenant sur une boucle que tu m'as ecrite, si tu te souviens:
Citation :
Code :

For Each c In wb_source.Range("B12:H24,J12:p 24,R12:X24" )
wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
Next


Donc la j'ai tout mis bout à bout et voila,

  1. Option Explicit
  2.  
  3. Private Sub ButtonMAJ_Click()
  4.  
  5. Dim wb_target As Workbook, wb_source As Workbook
  6. Dim chemin As String, mois_target As String, wb_sourcex As String, mois_sourcex As String
  7.  
  8. 'Définit le répertoire contenant les fichiers
  9. chemin = ActiveWorkbook.Path
  10.  
  11. 'Boucle sur tous les fichiers xls du répertoire.
  12. wb_sourcex = Dir(chemin & "\" & "SourcePays*.xls", vbDirectory)
  13.  
  14. Set wb_target = Workbooks("Analysis.xls")
  15. mois_target = Workbooks("Analysis.xls").sheets(1).Range("H1").Value
  16.  
  17. Select Case MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo)
  18. Case vbYes
  19.  
  20. Do While Len(wb_sourcex) > 0
  21. Set wb_source = Workbooks.Open(wb_sourcex)
  22. If wb_source.sheets(1).Range("B8").Value <> mois_target Then
  23. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  24. Workbooks("SourcePays*.xls").Close
  25. Else
  26. ' 1a. Copie de la date de mise à jour
  27.  
  28. wb_target.Worksheets(2).Range("B5").Value = wb_source.Worksheets(1).Range("A25").Value
  29.  
  30. With wb_target.Worksheets(2).Range("B5")
  31. .Font.ColorIndex = 3
  32. .Font.Size = 8
  33. .HorizontalAlignment = xlLeft
  34. End With
  35.  
  36. ' 1c. Copie des noms de régions correspondant aux bonnes données (par mesure de sécurité)
  37.  
  38. wb_target.Worksheets(2).Range("B8").Value = wb_source.Worksheets(1).Range("B10").Value
  39. wb_target.Worksheets(2).Range("J8").Value = wb_source.Worksheets(1).Range("J10").Value
  40. wb_target.Worksheets(2).Range("R8").Value = wb_source.Worksheets(1).Range("R10").Value
  41.  
  42. ' 1d. Copie des valeurs des plages
  43.  
  44. Dim c As Range
  45. For Each c In wb_source.Range("B12:H24,J12:P24,R12:X24")
  46. wb_target.Cells(c.Row - 2, c.Column).Value = c.Value
  47. Next
  48.  
  49. wb_source.Close
  50. End If
  51. wb_sourcex = Dir()
  52. Loop
  53. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  54. Case vbNo
  55. End Select
  56. End Sub


Donc pb ligne 45. Merci en tout cas pour le reste, meme si c'est loin d'etre parfait ça commence a marcher. c'est encourageant
Expert Programmation

La bonne syntaxe pour adresser des cellules, est la suivante :
Workbook.Worksheet.Range


Ligne 38 de ton code :
  1. wb_target.Worksheets(2).Range("B8" ).Value = wb_source.Worksheets(1).Range("B10" ).Value
C'est ok.

Lignes 45, 46 de ton code :
  1. wb_source.Range("B12:H24,J12:P24,R12:X24" )
  2. wb_target.Cells(c.Row - 2, c.Column).Value
Pour moi, il manque des trucs :o 

Tu me réécris correctement les lignes 22, 24 et tu me déplaces la ligne 44, s'il te plaît. C'est juste histoire d'atteindre la perfection.
:sol:  :D 

Nickel !!
lignes 22, 24 et 44 --> Done

lignes 45 46 je passe de:
  1. wb_source.Range("B12:H24,J12:P24,R12:X24" )
  2. wb_target.Cells(c.Row - 2, c.Column).Value


à
  1. wb_source.Worksheets(1).Range("B12:H24,J12:P24,R12:X24")
  2. wb_target.Worksheets("qqchose").Cells(c.Row - 2, c.Column).Value = c.Value


C'est ça??

Et pour atteindre la perfection :ange:  ,
je dois maintenant m'occuper de définir ce "qqchose" correspondant au nom du pays. Soit copie moi les données du mois du pays que tu etudies sur la feuille ayant le meme nom pays en onglet.

Comme ça, dans tout le code du précéédent message, je remplace Worksheets(2) par Worksheets(qqchose). Et laaa... :sol: 

Je suppose qu'il faut donc que je définisse une nouvelle variable, que je fasse un nom de fichier identique avec le d'onglet

  1. Dim onglet As String
  2. onglet = Left(wb_sourcex, Len(wb_sourcex) - 6)


Qu'est-ce que tu en penses?

D'autre part, si je veux que ma macro s'execute en "arrière-plan", je peux utiliser
  1. Application.ScreenUpdating = False
?
Expert Programmation

Le ScreenUpdating empêche Excel de rafraîchir l'affichage.
Il ne faut surtout pas oublier de le réactiver à la fin de la macro.

Ça devrait être bon, maintenant. :) 

Pour le screen updating je verrai plus tard.

Est-ce que le programmateur a la même démarche que l'artiste ?
Jamais satisfait de ce qu'il fait...parce que ça plante encore !! et j'aimerais aussi améliorer des choses (non, jamais je sors!) :D 

Avec mon histoire d'onglet, ça ne marche pas, je dois surement oublier d'activer le classeur, tout du moins, vba s'arrête sur le premier classeur ouvert --> donc les données sont copiées les unes sur les autres sur la même feuille !!

  1. Option Explicit
  2.  
  3. Private Sub ButtonMAJ_Click()
  4.  
  5. Dim wb_target As Workbook, wb_source As Workbook
  6. Dim chemin As String, mois_target As String, wb_sourcex As String, mois_sourcex As String, onglet As String
  7. Dim c As Range
  8.  
  9. 'Définit le répertoire contenant les fichiers
  10. chemin = ActiveWorkbook.Path
  11.  
  12. 'Boucle sur tous les fichiers xls du répertoire.
  13. wb_sourcex = Dir(chemin & "\" & "Pays*.xls", vbDirectory)
  14.  
  15. Set wb_target = Workbooks("Analysis.xls")
  16. mois_target = Workbooks("Analysis.xls").Worksheets(1).Range("H1").Value
  17.  
  18. Select Case MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo)
  19. Case vbYes
  20.  
  21. Do While Len(wb_sourcex) > 0
  22. Set wb_source = Workbooks.Open(wb_sourcex)
  23. onglet = Left(wb_sourcex, Len(wb_sourcex) - 4)
  24.  
  25. If wb_source.Worksheets(1).Range("B8").Value <> mois_target Then
  26. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  27. Workbooks(wb_sourcex).Close
  28. Else
  29.  
  30. ' 1a. Copie de la date de mise à jour
  31. wb_target.Worksheets(onglet).Range("B5").Value = wb_source.Worksheets(1).Range("A25").Value
  32.  
  33. With wb_target.Worksheets(onglet).Range("B5")
  34. .Font.ColorIndex = 3
  35. .Font.Size = 8
  36. .HorizontalAlignment = xlLeft
  37. End With
  38.  
  39. ' 1c. Copie des noms de régions correspondant aux bonnes données (par mesure de sécurité)
  40.  
  41. wb_target.Worksheets(onglet).Range("B8").Value = wb_source.Worksheets(1).Range("B10").Value
  42. wb_target.Worksheets(onglet).Range("J8").Value = wb_source.Worksheets(1).Range("J10").Value
  43. wb_target.Worksheets(onglet).Range("R8").Value = wb_source.Worksheets(1).Range("R10").Value
  44.  
  45. ' 1d. Copie des valeurs des plages
  46.  
  47. For Each c In wb_source.Worksheets(1).Range("B12:H24,J12:P24,R12:X24")wb_target.Worksheets(onglet).Cells(c.Row - 2, c.Column).Value = c.Value
  48. Next
  49.  
  50. wb_source.Close
  51. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  52. End If
  53. wb_sourcex = Dir()
  54. Loop
  55. Case vbNo
  56. End Select
  57. End Sub


Donc ça doit spasser au niveau de la definition de la variable.
Je poste mon code en entier, deja bien satisfait du travail, c'est pas gd-chose mais c'est déjà ça. Merci Zeb !!
Expert Programmation

Salut :hello: 

Bon alors. On va commencer tout de suite les hostilités.
Un programmateur, c'est ça :

Donc, non, je ne vois pas de rapport avec un artiste.

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

Dans quel classeur, et dans quel objet (feuille, ThisWorkbook, module) de ce classeur ta macro est-elle enregistrée ?

Ligne 13
NON ! :fou: 
(Ce Lundi ça commence bien :sarcastic:  )

D'abord, le nom de la variable wb_sourcex est préfixé par wb, on s'attend à avoir un objet WorkBook. Il s'agit d'un nom de fichier, trouve quelque chose de plus intelligent.

Ensuite, pourquoi as-tu passé le paramètre vbDirectory ?

Tertio, la fonction Dir() renvoie le nom du fichier, pas le chemin complet vers le fichier. L'étude demandée aurait due te le faire découvrir tout seul (alors, on ne fait pas ses devoirs [:zeb:4])

Ligne 15
ActiveWorkbook utilisé ligne 10 est-il différent de Workbooks("Analysis.xls" ) ?


Ligne 16
Utilise wb_target, nom d'un smiley !

Ligne 17
RAS

Ligne 18
Pour simplifier les choses, n'hésite pas à sortir de la procédure rapidement, plutôt que de traîner jusqu'au bout des structures d'instructions complexes :
  1. If MsgBox("Etes-vous sûr de vouloir charger les données de" & " " & mois_target & "?", vbYesNo) <> vbYes Then Exit Sub

Comme ça, tu vires le Select.

Ligne 19 (et suivantes)
IN-DEN-TA-TION [:marcus67]

Ligne 27
Utilise wb_source, nom d'un smiley ! (Ouh, qui m'énerve !!!)
Observe bien ton code. Tu as une structure If avec une partie Then et une partie Else. A la fin de chacune de ces partie, tu fermes le classeur. Et bien sors le du If :
  1. ' // Compliqué
  2. If wb_source.Worksheets(1).Range("B8").Value <> mois_target Then
  3. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  4. Workbooks(wb_sourcex).Close
  5. Else
  6. ...
  7. wb_source.Close
  8. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  9. End If
  10.  
  11. ' // Plus simple
  12. If wb_source.Worksheets(1).Range("B8").Value <> mois_target Then
  13. MsgBox "Le mois choisi ne correspond pas avec les données du rapport !", vbExclamation
  14. Else
  15. ...
  16. MsgBox "Vos données ont bien été mises à jour pour " & mois_target
  17. End If
  18. wb_source.Close


Ligne 25 (et suivantes)
Tu utilises beaucoup wb_source.Worksheets(1) et wb_target.Worksheets(onglet). N'hésite pas à te faire deux variables, ws_source et ws_target par exemple.

Ligne 47
Une petite erreur de copie je pense.

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

Voili, voilou :) 

salut salut !
programmateur <> programmeur, j'aurai du m'en douter :sweat: 

Bon alors, déjà, bonne nouvelle, ça marche comme je veux!
Maaaaaaiiis, je n'vais pas m'arreter en si bon chemin

Concernant les devoirs -maison:
- Dir() :
j'ai ajouté vbDirectory pensant que c'etait l'élélent qui faisait défaut.
j'ai rechangé le code pour donner :

  1. 'Définit le répertoire contenant les fichiers
  2. chemin = ActiveWorkbook.Path
  3. ChDir (chemin)
  4.  
  5. 'Boucle sur tous les fichiers xls du répertoire.
  6. wb_sourcex = Dir("Pays*.xls")


ligne 15, 16, 17, 19 et suivantes --> corrigé
ligne 25 et 27 de même.

Donc on peut dire que ça roule!! :sol: 

CEPENDANT, bien que ça marche, je n'ai pas encore testé sur mes "vrais" fichiers et j'ai 2 contraintes dont j'aimerais me débarasser assez rapidement:

1- nom d'onglet et nom du fichier source doivent être identiques, sinon a marche pu. Est-il possible de récuperer juste une partie du nom du fichier source, qui correspond in fine au nom de l'onglet ??

2- Mes tableaux ne contiennent pas tous la même quantité de valeurs à copier; soit, pour le pays1 je peux avoir
  1. For Each c In ws_source.Range("B12:H24,J12:P24")
  2. ws_target.Cells(c.Row - 2, c.Column).Value = c.Value
  3. Next

Et pour le pays 2, les zones B12:H24, J12:p 24, R12:X24, Z12:AF24 à copier.

Je vais donc devoir specifier dans mon code toutes ces zones, d'où une perte (minime je pense) d'efficacité, puisque ceci sera applicable à tous les fihiers source du repertoire, soit

  1. For Each c In ws_source.Range("B12:H24,J12:P24,R12:X24,Z12:AF24")
  2. ws_target.Cells(c.Row - 2, c.Column).Value = c.Value
  3. Next


Je pensais donc faire:
- compte-moi le nb de cellules non vides (contenant le nom des regions)
- copie moi alors toutes les valeurs en fonction du nb de régions (cad si 2régions comptés, copie juste les valeurs ("B12:H24,J12:p 24"), si 3 ...)

  1. Dim nbre_regions As Byte
  2. nbre_regions = qqchose ... !


c'est clair ou pas ?

merci merci!

Expert Programmation

  1. ' // Définit le répertoire contenant les fichiers
  2. chemin = ActiveWorkbook.Path
  3. ChDir (chemin)
  4.  
  5. Boucle sur tous les fichiers xls du répertoire.
  6. wb_sourcex = Dir("Pays*.xls" )
Y'a pas de parenthèse à ChDir. Pis c'est nul ! Pourquoi changes-tu de répertoire ? C'est mal. Ton programme doit laisser l'environnement de l'utilisateur intact, par principe : même chemin, même presse-papier, etc :
  1. chemin = ActiveWorkbook.Path
  2. wb_sourcex = chemin & "\" & Dir(chemin & "\" & "Pays*.xls" )


B12:H24,J12:P24,R12:X24,Z12:AF24
Mais non !
Tu te trompes de définition. En fait, tu as n zones de 7x13 cellules, toutes les 8 colonnes.

Soit c0, la cellule en haut à gauche de ta première zone. La cellule en bas à pour adresse la même que c0, décalé (offset) de 12 lignes et de 6 colonnes :
  1. Dim c0 As Range, c1 As Range
  2. Set c0 = ws_source.Range("B12").
  3. Set c1 = c0.Offset(12, 6)
  4.  
  5. For Each c In Range(c0, c1) ...


Bon, moi j'aime bien les nombres, alors j'utilise Cells() plutôt que Range() pour mes cellules :
  1. Dim i As long
  2. i = 2
  3. Set c0 = ws_source.Cells(12, i).
  4.  
  5. For Each c In Range(c0, c0.Offset(12, 6)) ...


Bon, maintenant, un peu de devoir à la maison. Etudie-moi la fonction
f(x)=x * 8 - 6

:D 

héhé.

J'ai changé la commande pour retrouver les fichiers dans le repetoire. Mais du coup j'ai eu bcp de mal apres avec mon nom de pays qui était modifié (rajout de "D:\Mes documents\" devant). Ma fonction Left ne marchait plus, j'ai du bidouillé ceci pour retrouver (en debug) onglet = "pays*"
  1. onglet = Mid(wb_sourcex, Len(wb_sourcex) - 8, 5)

pas trop cochon?

En tout cas, ça marche!

Ensuite, voila ce que j'ai commencé, en utilisant ce que tu m'as fourni; je souhaite faire le copier/coller en meme temps du nom region et des valeurs de(s) (la) zone(s) n s'y rapportant. C'est surement pas beau, Attention aux yeux ! :whistle: 
  1. Dim regionsx As Range, valeursx As Range
  2. Dim nb_regions As Byte, cptr As Byte
  3.  
  4. 'Determine le nb de regions pour le pays*
  5. nb_regions = (ws_source.Range("B10").End(xlToRight).Column + 6) / 8
  6.  
  7. Set regionsx = ws_source.Cells(10, 2 + (8 * nb_regions))
  8. Set valeursx = ws_source.Range(Cells(12, 2 + (8 * nb_regions)), Cells(24, 8 + (8 * nb_regions))).Value
  9.  
  10. For cptr = 0 To nb_regions - 1
  11. With ws_target
  12.  
  13. 'Copie des noms de régions
  14. .Range(Cells(8, 2 + (8 * nb_regions))).Value = regionsx
  15.  
  16. 'Copie des valeurs des plages
  17. .Range(Cells(10, 2 + (8 * nb_regions)), Cells(22, 8 + (8 * nb_regions))).Value = valeursx
  18. End With
  19. Next


La je bloque sur la ligne 7 .. !! Need a device !!!
Expert Programmation

Bon, alors je reviens sur ce que j'ai dit :

  1. ' // Pas bon
  2. chemin = ActiveWorkbook.Path
  3. wb_sourcex = chemin & "\" & Dir(chemin & "\" & "Pays*.xls" )
  4. onglet = Mid(wb_sourcex, Len(wb_sourcex) - 8, 5)
  5. Set wb_source = Workbooks.Open(wb_sourcex)
  6.  
  7. ' // Bien
  8. chemin = ActiveWorkbook.Path
  9. fichier = Dir(chemin & "\" & "Pays*.xls" )
  10. onglet = Left(fichier, x)
  11. Set wb_source = Workbooks.Open(chemin & "\" & fichier)


Ensuite, c'est d'un device ou d'un advice dont tu as besoin ? [:patch]

Evite de trop mettre de parenthèses, surtout quand la priorité mathématique ne le justifie pas. Il y en a assez comme ça avec celles des fonctions.

Ligne 8, tu te trompes. Les fonctions Cells dans le Range ne sont pas préfixées de leur feuille. Voici la bonne syntaxe :
  1. ' // Pas bon
  2. ws_source.Range(Cells(12, 2 + (8 * nb_regions)), Cells(24, 8 + (8 * nb_regions)))
  3.  
  4. ' // Bien
  5. Range(ws_source.Cells(12, 8 * nb_regions + 2), Cells(24, 8 * nb_regions + 8))
Comme par ailleurs tu as déjà une variable sur une cellule de l'ensemble, il peut être agréable de l'utiliser :
  1. ' // Pas bon
  2. ws_source.Range(Cells(12, 2 + (8 * nb_regions)), Cells(24, 8 + (8 * nb_regions)))
  3.  
  4. ' // Très bien
  5. Range(regionsx.Offset(2, 0), regionsx.Offset(2, 10))


valeursx est un Range, tu ne peux pas lui affecter une valeur !
  1. ' // Pas bon (on va finir par le savoir)
  2. Set valeursx = ws_source.Range(Cells(12, 2 + (8 * nb_regions)), Cells(24, 8 + (8 * nb_regions))).Value
  3.  
  4. ' // Excellent (ziva comment il se la pête !)
  5. Set valeursx = Range(regionsx.Offset(2, 0), regionsx.Offset(2, 10))


Ligne 14, tu fais un Range sur un Cells. Faudra que tu m'expliques l'intérêt :o  A la même ligne tu veux mettre une cellule dans une valeur, c'est pas logique. (VB le voit et met la valeur de regionsx dans la valeur de R(C(8,2+8*nr))).

Ligne 17, tu refais les mêmes erreurs.

Reprends-moi tout ça, avec une double boucle :
  1. For nb_regions
  2. Set c0 = Cells( ... nb_regions ... )
  3. For Each c In Range(c0, c0.Offset( ... ))
  4. ...
  5. Next
  6. Next


_____________________________

Ah bravo : Je lui dit d'étudier
f(x)=x * 8 - 6

il me sort
f(x)=(x-1) * 8 + 2

:pfff: 

.... :D 

Bonjour!

Arghh jte dirai pas que j'ai passé toute la nuit sur la macro parce que c'est pas vrai mais faisons comme si. Déjà en utilisant ça, pb de qualificateur incorrect pointant sur regionsx (alors que je l'annonce juste avant):
  1. '// Excellent
  2. Set valeursx = Range(regionsx.Offset(2, 0), regionsx.Offset(2, 10))


ensuite, moi pas réussir la dble boucle!
1- Faut-il que je rajoute une boucle (donc triple boucle! wouhou), une pour region, une pour la plage de valeurs et la dernière englobant les deux:
  1. For cptr = 0 To nb_regions
  2. cD1 = ws_source.Range("B10")
  3. cF1 = cD1 * nb_regions
  4. cD2 = ws_source.Range("B12")
  5. cF2 = cD2.Offset(12, 6) * nb_regions
  6.  
  7. For Each c In Range(cD1, cF1)
  8.  
  9. 'Copie des noms de régions
  10. Range(ws_target.Cells(8, 2 + (8 * nb_regions))) = regionsx
  11. Next
  12. For Each c In Range(cD2, cF2)
  13.  
  14. 'Copie des valeurs des plages
  15. Range(ws_target.Cells(10, 2 + 8 * nb_regions), Cells(22, 8 + 8 * nb_regions)) = valeursx
  16. Next
  17. Next

? je sèche un peu, un indice supplémentaire serait plus que cool !! Merci
Expert Programmation

  1. Set regionsx = ws_source.Cells(10, 2 + (8 * nb_regions))
  2. MsgBox "Vérification : " & regionsx.Address
  3. Set valeursx = Range(regionsx.Offset(2, 0), regionsx.Offset(2, 10))

Ça marche pas, ça ?

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

Alors jeune padawan, tu n'as pas de triple boucle. A aucun moment tu n'as une ligne de code imbriquée dans trois boucle. La ligne 10 est dans une double-boucle, la igne 15 dans une autre, avec un même For en commun.

Par contre, tu vas m'expliquer ton bordel, là (passe-moi l'expression).
Tu n'as rien compris à ce que je voulais te faire faire. Ben c'est que j'explique mal.

Ligne 2.
Qu'est-ce que cD1 ? Une cellule (Range) ? Alors où est le Set devant ? Et pourquoi cette variable ne varie pas avec cptr ?

Ligne 3.
Qu'est-ce que cF1 ? Une cellule ? Comment fais-tu pour multiplier une cellule (la cellule, pas le contenu, hein) ?

...

Bon, je te donne la soluce, mais promets-moi de bien l'étudier et de la comprendre :
  1. Dim cell_reference_source As Range
  2. Dim cell_reference_target As Range
  3. Dim cell As Range
  4. Dim nb_region As Integer
  5.  
  6. For nb_region = 0 To nb_regions - 1
  7. Set cell_reference_source = ws_source.Cells(nb_region * 8 + 8, 2)
  8. Set cell_reference_target = ws_target.Cells(nb_region * 8 + 6, 2)
  9.  
  10. cell_reference_target.Value = cell_reference_source.Value
  11. For Each cell In Range(cell_reference_source.Offset(0, 2), cell_reference_source.Offset(10, 2))
  12. wb_target.Cells(c.Row - 2, c.Column).Value = cell.Value
  13. Next
  14. Next


Quand tu auras tout compris, regarde un peu ça, tout en décalage :sol:  :
  1. Dim cell_s0 As Range
  2. Dim cell_t0 As Range
  3. Dim cell As Range
  4. Dim nb_region As Integer
  5.  
  6. For nb_region = 0 To nb_regions - 1
  7. Set cell_s0 = ws_source.Range("B8").Offset(0, nb_region * 8)
  8. Set cell_t0 = ws_target.Range("B6").Offset(0, nb_region * 8)
  9.  
  10. For Each cell In Union(cell_reference_source.Value, _
  11. Range(cell_reference_source.Offset(0, 2), _
  12. cell_reference_source.Offset(10, 2)))
  13. cell_t0.Offset(cell.Row - cell_s0.Row, _
  14. cell.Column - cell_s0.Row).Value = c.Value
  15. Next
  16. Next

woua! j'en demandais pas tant (surtout commencant à connaitre tes methodes pedagogique!) Mais tant mieux! Du coup je comprends pas tout en fait :sweat: 
Pas la definition mais plutot la structure en general..

Donc gros pb qui persiste, c'est la methode Range qui echoue pour la ligne 12 et donc 13..
  1. Dim regions_source As Range
  2. Dim valeurs_source As Range
  3. Dim regions_target As Range
  4. Dim valeurs_target As Range
  5. Dim nb_regions As Integer
  6.  
  7. 'Determine le nb de regions pour le pays*
  8. nb_regions = (ws_source.Range("B10").End(xlToRight).Column + 6) / 8
  9.  
  10. For nb_regions = 0 To nb_regions - 1
  11. 'Determine les adresses des plages à copier sur wb_target
  12. Set valeurs_source = Range(ws_source.Cells(12, nb_regions * 8 + 2), Cells(24, nb_regions * 8 + 8))
  13. Set valeurs_target = Range(ws_target.Cells(10, nb_regions * 8 + 2), Cells(22, nb_regions * 8 + 8))


Sinon je pense que niveau explications ça va !! J'avoue ne pas forcement être tres logique (ou deductif) pour les sciences dures!

De meme, quand je reprend ton code, vb bloque sur le range, ligne For Each cell in Range ...
  1. Dim cell_reference_source As Range
  2. Dim cell_reference_target As Range
  3. Dim cell As Range
  4.  
  5. For nb_regions = 0 To nb_regions - 1
  6. Set cell_reference_source = ws_source.Cells(10, nb_regions * 8 + 2)
  7. Set cell_reference_target = ws_target.Cells(8, nb_regions * 8 + 2)
  8.  
  9. cell_reference_target.Value = cell_reference_source.Value
  10. For Each cell In Range(cell_reference_source.Offset(0, 2), cell_reference_source.Offset(10, 2))
  11. wb_target.Cells(c.Row - 2, c.Column).Value = cell.Value
  12. Next
  13. Next


:??: 
Expert Programmation

Ouvre un nouveau classeur. [Ctrl+F11] et nous voilà en VB.
Soit la macro "pas bonne" suivante :
  1. Sub Epinard
  2. ' // Observons d'abord que le nom de la macro prouve que le code n'est pas bon :-)
  3. Dim Cellule As Range
  4. Set Cellule = Range( Worksheets("Feuil1").Range("A1"), Worksheets("Feuil2").Range("B2"))
  5. MsgBox Cellule.Address
  6. End Sub


[F5] et zou, c'est parti.....

" Ben pourquoi que ça plante-t'y donc ??? :( 
- Ah, bah voui, c'que chuis con.... "

Maintenant tes lignes 12 et 13, mieux regarde, vilain padawan.

sur cette macro on voit bien que la zone est sur 2 feuilles differentes mais sur la mienne et la tienne, on reste à chaque fois sur la meme feuille:
  1. For Each cell In Range(cell_reference_source.Offset(0, 2), cell_reference_source.Offset(10, 2))


  1. Set valeurs_source = Range(ws_source.Cells(12, nb_regions * 8 + 2), ws_source.Cells(24, nb_regions * 8 + 8))


ou serait-ce autre chose, une autre force.. ?? Range = Range ?

:pt1cable: 

Serieux, je ne vois pas!
Expert Programmation

Salut,

Mon message de 16:22:03 répondait au tien de 16:03:01, je n'avais pas lu celui de 16:15:46. Donc lignes 12 et 13, on avait bien le problème.

Là, je ne vois pas. A ton débogueur, mon gars :o 

  1. For Each cell In Range(cell_reference_source.Offset(0, 2), cell_reference_source.Offset(10, 2))
Si celle ligne plante, il faut tout vérifier, juste avant. Soit effectivement avec le débogueur et ses espions, soit avec de bêtes boîtes de message.

Je te fais la version bête :
  1. MsgBox "Cellule Ref " & cell_reference_source.Address & vbCrLf & _
  2. "Cellule 1 : " & cell_reference_source.Offset(0, 2).Address & vbCrLf & _
  3. "Cellule 2 : " & cell_reference_source.Offset(10, 2).Address & vbCrLf & _
  4. "Plage : " & Range(cell_reference_source.Offset(0, 2), cell_reference_source.Offset(10, 2)).Address


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

Citation :
une autre force
:lol:  ;) 

Hello. Ah ! au moment ou tu repondais je trouvais (1?) solution.
  1. For nb_regions = 0 To nb_regions + 1
  2. 'Determine les adresses des regions à copier sur wb_target
  3. Set regions_source = ws_source.Cells(10, nb_regions * 8 + 2)
  4. Set regions_target = ws_target.Cells(8, nb_regions * 8 + 2)
  5.  
  6. regions_target.Value = regions_source.Value
  7.  
  8. 'Determine les adresses des plages à copier sur wb_target
  9. Set valeurs_source = ActiveSheet.Range(ws_source.Cells(12, 2 + nb_regions * 8), ws_source.Cells(24, 8 + nb_regions * 8))
  10. Set valeurs_target = ws_target.Range(ws_target.Cells(10, nb_regions * 8 + 2), ws_target.Cells(22, nb_regions * 8 + 8))
  11.  
  12. valeurs_target.Value = valeurs_source.Value
  13. Next
En rajoutant activeSheet pour "mon" code, egalement pour le tien;
  1. Dim cell_reference_source As Range
  2. Dim cell_reference_target As Range
  3. Dim cell As Range
  4.  
  5. For nb_regions = 0 To nb_regions + 9
  6. Set cell_reference_source = ws_source.Cells(12, nb_regions * 8 + 2)
  7. Set cell_reference_target = ws_target.Cells(10, nb_regions * 8 + 2)
  8.  
  9. cell_reference_target.Value = cell_reference_source.Value
  10. For Each cell In ActiveSheet.Range(cell_reference_source.Offset(0, 0), cell_reference_source.Offset(12, 7))
  11. ws_target.Cells(cell.Row - 2, cell.Column).Value = cell.Value
  12. Next
  13. Next
et voila le boulot! :D 

Par contre, j'aimerais savoir 2 choses:
1- Pourquoi si je change le chiffre apres nb_region dans
  1. For nb_regions = 0 To nb_regions + 9
ça me change le nb de plages qui sont copiées/collées.. ? (-1 = 2plages, 0 = 3, +1 = 4,...)Le nb de plages à copier/coller ne devait pas être determiné en definissant nb_regions..??
  1. nb_regions = (ws_source.Range("B10").End(xlToRight).Column + 6) / 8
..a moins qu'il faille preciser les cellules non vides.. :??: 

2- la 1ere methode, que je trouve plus simple (et aussi plus claire pour ne rien te cacher!!) est-elle adequate? Avec les Offset, j'ai l'impression que c'est plus long..

Voila voila, en tout cas merci pour la soluce plus haut, ça m'a tout de même filé un bon coup de main. Maintenant je vais m'attaquer à d'autres petites améliorations ..

Héhé de la joie et du plaisir en perspective !! :pt1cable: 

Expert Programmation

Alors là, zéro pointé !
Il ne faut surtout pas mettre d'ActiveSheet, nulle part, jamais !

Et si ta macro tournant, tu changes de part, ou pour une raison quelconque, un autre classeur s'ouvre ? Voilà de quoi y remédier :
  1. Set valeurs_source = ws_source.Range(ws_source.Cells(12, 2 + nb_regions * 8), ws_source.Cells(24, 8 + nb_regions * 8))

(Comme on a fait pour ws_Target.Range, d'ailleurs)

Les deux méthodes sont équivalentes. Mais je trouve que la seconde, avec les décalages est plus élégante : elle suit le raisonnement humain :
  • Je pointe sur B6,
  • Je me décale vers la droite, vers le bas,
  • ...

    Je ne comprends pas pourquoi tu veux ajouter + 9 à ton nombre de régions. Si tu as n régions, il faut itérer de 0 à n-1, donc le code proposé devrait bien fonctionner :spamafote: 

    Par contre, je ne sais pas si ta méthode pour calculer le nombre de régions est bon.

    J'aurais tendance à dire que non. Ajouter 6 puis diviser par 8, ça sent la planture.
    Perso, je fais autrement pour trouver le dernier élément. Je vais à la dernière cellule de la feuille et je reviens sur la dernière. Ca évite de se planter à cause d'une cellule vide. Un exemple sur les lignes : ici, à transposer pour tes colonnes.

    Explique un peu comment est organisée ta ligne 10.

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

    Si tu estimes que ton problème est résolu, élis la moins mauvaise des réponses comme étant la meilleure, le sujet passera alors en [Résolu].

    Salut
    Citation :
    Alors là, zéro pointé !
    Il ne faut surtout pas mettre d'ActiveSheet, nulle part, jamais !

    aie aie aie! heureusement que je n'en avais mis qu'un seul! :D 
    Du coup, facile à retirer.

    Bon alors, je ne vais peut-être pas clôturer ce topic maintenant, car même si le resultat s'approche de ce que je souhaite, j'ai encore 2-3 bricoles qui vont peut-être necessiter un coup de main.. mais promis, j'y penserai une fois fini!

    j'ai changé la methode pour calculer le nb de region et ça marche très bien
    1. nb_regions = ((ws_source.Range("IV10").End(xlToLeft).Column + 7) - ws_source.Range("B10").Column) / 8


    D'autre part, je fais maintenant un zoom sur
    1. ''Determine les adresses des plages à copier sur wb_target
    2. Set valeurs_source = ws_source.Range(ws_source.Cells(12, 2 + nb_regions * 8), ws_source.Cells(24, 8 + nb_regions * 8))
    3. Set valeurs_target = ws_target.Range(ws_target.Cells(10, nb_regions * 8 + 2), ws_target.Cells(22, nb_regions * 8 + 8))


    Et je lui demande de:
    - dans la plage valeurs_target de ws_target, si les données de la colonne 4 (datant du mois précedent) sont = aux données de la colonne 4 de ws_source (du nouveau mois), efface-moi ces données (juste col 4) dans ws_target (je ne veux pas les montrer!) sinon fais ce que dois! J'ai donc fait
    1. Dim val_actn_source As Range, val_actn_target As Range
    2.  
    3. Set val_actn_source = ws_source.Range(ws_source.Cells(12, 3 + nb_regions * 8), ws_source.Cells(24, 3 + nb_regions * 8)) 'C12:C24
    4. Set val_actn_target = ws_target.Range(ws_target.Cells(10, 3 + nb_regions * 8), ws_target.Cells(22, 3 + nb_regions * 8)) 'C10:C22
    5.  
    6. For Each val_actn_target In ws_target
    7. If val_actn_target.Value = val_actn_source.Value Then
    8. 'copie colle valeurs & delete colonne 4
    9. valeurs_target.Value = valeurs_source.Value
    10. val_actn_target.Delete
    11. Else ...


    ai-je oublier qqch de grossier pour que ça ne marche pas?
    Une meilleure méthode ?

    Merci bien !

    Super;merci
    Alors pour reprendre en explication (et pas en code ;)  ):

    J'ai ma plage de données source (valeurs_source), dans laquelle se trouve une plage de données (C12:C24 soit val_actn_source)

    Je confronte cette plage à une autre se situant dans valeurs_target (C10:C22 soit val_actn_target)

    Si les chiffres sont identiques, cela veut dire que mes données n'ont pas été mises à jour par le système. Je ne veux donc pas qu'elles apparaissent dans ws_target. (de meme que 2 autres plages qui sont liées, D10:D 22, pourc1, et F10:F22,pourc2).

    Sinon, affect moi la valeurs des données des plages source aux plages target.

    J'ai fait ça mais je bloque encore :sweat: 
    1. Set val_actn_source = ws_source.Range(regions_source.Offset(2, 1), regions_source.Offset(14, 1))
    2. Set val_actn_target = ws_target.Range(regions_target.Offset(2, 1), regions_target.Offset(14, 1))
    3.  
    4. Set pourc1_target = ws_target.Range(regions_target.Offset(2, 2), regions_target.Offset(14, 2))
    5. Set pourc2_target = ws_target.Range(regions_target.Offset(2, 4), regions_target.Offset(14, 4))
    6.  
    7. If val_actn_target.Value = val_actn_source.Value Then
    8. For Each c In Union(val_actn_target, pourc1_target, pourc2_target)
    9. 'delete colonne 3,4,6
    10. c.ClearContent
    11. Next
    12. Else
    13. valeurs_target.Value = valeurs_source.Value
    14. End If

    à la ligne If, je veux comparer mes deuxplages, sont-elles identiques ou pas.
    MERCI Zeb

    Ps: tu auras remarqué que je me suis mis au Offset, sacré mode!!
    Expert Programmation

    Euh, si.

    Ta ligne 7 n'est pas bonne. Tu ne peux pas comparer les valeurs d'une plage aux valeurs d'une autre plage. Il faut le faire cellule par cellule.

    Sers-toi de ce que je t'explique dans la seconde partie de ce message.

    Je te propose même de créer une fonction de comparaison à part, dont voici un prototype pertinent :
    1. Function Verif_Egalite_Plage(zone_1 As Range, cellule_2 As Range) As Boolean

    La zone #1, c'est la zone bleu foncé de mon schéma, la cellule #2, c'en est la cellule vert foncé.

    c'est bien ce que je me disais.. (non, sans blague!) :whistle: 
    Alors j'ai repris le schema, mais apres plusieurs essais rien de bien ne sors.
    Je pense que je n'en comprend pas le sens profond..

    Donc
    1. Function Verif_Egalite_Plage(zone_1 As Range, cellule_2 As Range) As Boolean
    2.  
    3. Set zone_1 = ws_source.Range(ws_source.Cells(12, 3 + nb_regions * 8), ws_source.Cells(24, 3 + nb_regions * 8))
    4. Set cellule_2 = ws_target.Cells(10, 3 + nb_regions * 8)
    5. For Each c In zone_1
    6. cellule_2.Value = c.Value
    7. Next
    8. End Function

    Jusqu'à la ligne 4, ça devrait aller. Par contre apres, je n'arrive pas à savoir comment on intègre le décalé et où?
    - ma cellule_2 est l'adresse de la première des cases à remplir dans target.
    - Je me sers du décalé entre la cellule de reference source et la cellule en cours source .. mais quelle est l'adresse de la cellule en cours source?, ça devrait être la 1ère de la zone normalement ??

    Bon.. je recommence !
    1. For Each c In zone_1
    2. cellule_2.Offset(X, Y).Value = c.Value
    3. Next


    Le souci c'est qu'avec ça, la fonction reste sur la dernière valeur de la plage zone_1 ..
    Lassé par la pub ? Créez un compte