2 fichiers, copie de certaines colonne vers 1 fichier résumé

Ouiiiiiii ça avance ! ça avance ! (grâce à toi Migou )

Sur la sous procédure copie, j'ai éditer de cette façon:

    Private Sub lancer_copie()

        Dim i As Long
        i = 6  ' numéro de la ligne sur laquelle on viendra inscrire les données

        wkb_AA.Worksheets("Feuil1").Activate  'on travaille sur le classeurAA
        Call copie("N°voiture", 2, i)  'appelle de la sous procédure copie("chaine",numéro de colonne dans classeurCC,numéro de ligne)
        Call copie("nombredeporte", 4, 6)  'appelle la sous procédure copie pour la colonne "nombre de porte" l'envoyant en 4eme colonne sur la 6eme ligne

        wkb_BB.Worksheets("Feuil1").Activate 'idem
        Call copie("N°voiture", 2, i)
        Call copie("ventes", 1, 6)
        Call copie("origine", 3, 6)

    End Sub

Ça semble fonctionnait ( mais mettre 2 fois dans le code la ligne qui est en commun sur le classeurAA et BB fait qu'elle se superpose l'une après l'autre. Donc je n'en garderais qu'une sur les 2 si je dis pas top de bêtise).

Et j'ai supprimé l'incrémentation via la variable "j", tu confirme que pour le résultat attendu j'ai bien fais ?

Je suis super contente parce que j'ai enfin assimiler (je crois le fonctionnement des procédures) que tu t'efforces de m'expliquer depuis 2 pages ^^

J'aurais bien quelques petits trucs supplémentaires a demander, mais j'attends de voir si tu es toujours d'attaques. Ce qui risque de me tracasser maintenant c'est la méthodo sur la sauvegarde que je voudrais obtenir (cf. mon petit post du dessus ).

Merci mille fois !

Jenny a écrit :

Le nombre de lignes sur les 2 fichiers est similaires, et la seul colonne que ces 2 fichiers aient en commun est la colonne "N° voiture " (présente en col 1 pour ClasseurBB, et présente en col3 pour classeurAA) pour le reste toutes les colonnes sont différentes mais il y a bien une correspondance entre les données puisque le "N°voiture" est ordonné de la même façon sur les 2 fichier.

Sur ce point il faut que tu sois certaine d'avoir toujours les mêmes numéros de voiture, le même nombre de voiture et qu'ils soient ordonnés de la même façon sur tes 2 fichiers. Si c'est le cas alors ça change effectivement ce que j'avais fait, j'avais mal compris la correspondance entre les 2 fichiers.

En revanche si tu n'en n'es pas certaine ça change tout, puisqu'on ne peut plus se contenter de juxtaposer les données des 2 feuilles. Il faut alors faire la copie sur une des feuilles, puis pour la deuxième faire une recherche ligne par ligne du numéro de voiture et coller la cellule au numéo de voiture correspondant.

Si tu optes pour le deuxième cas qui est de loin le plus sûr (ça permet d'éviter des erreurs dont tu ne t'apercevrais que trop tard) commence par trier tes données par numéro de voiture pour gagner du temps d'exécution. L'algorithme serait du type :

- Je trie les données de tous les classeurs puis

- Je copie les données de classeurAA vers classeur CC puis

- Pour chaque colonne de BB alors

  • Pour chaque ligne (cellule) de BB alors
  • Je récupère le numéro voiture
  • Je me positionne sur CC et je cherche le numéro voiture
  • Quand je trouve le numéro de voiture sur CC alors je colle dans la colonne correspondante
Jenny a écrit :

A chaque fois que je lance la macro, j'aimerais qu'il soit crée un nouveau fichier (donc que la macro me demande dans une boîte de dialogue "enregistrer sous: ....nom.....") qui reprend la structure de mon masque et qui soit allimenté par les donnée contenu dans les 2 fichiers classeurs sources (AA et BB). De cette façon je peux après un temps X faire un retour en allant ouvrir un des fichiers stocké dans un dossier et crée il y a plusieurs semaines (j’intitulerais par exemple les fichier: Analyse_semaine1 , Analyse_semaine2, Analyse_semaine3, etc...)

Pourquoi s'embêter à créer un nouveau fichier ? Ce que j'ai rédigé sur mon dernier post fonctionne très bien. On travaille toujours sur le classeurCC, on effectue tout les traitements sur ce même classeur sans enregistrer. Puis à la fin de l'exécution de la macro on lance le saveas filename pour enregistrer sous un autre nom de fichier.

Ainsi le classeurCC reste intact.

Pour choisir toi-même où le sauvegarder il te faut remplacer la ligne qui contient le SaveAs :

ThisWorkbook.SaveAs ThisWorkbook.Path & "\Final.xls"

par celle_ci :

Application.Dialogs(xldialogsaveas).Show
Jenny a écrit :

Ça semble fonctionnait ( mais mettre 2 fois dans le code la ligne qui est en commun sur le classeurAA et BB fait qu'elle se superpose l'une après l'autre

Bah oui du coup, je pensais que tu voulais le coller en dessous. Le i ne sert plus à rien puisque tu copies toujours sur la même ligne :

Private Sub lancer_copie()

    wkb_AA.Worksheets("Feuil1").Activate
    Call copie("N°voiture", 2)
    Call copie("nombredeporte", 4)

    wkb_BB.Worksheets("Feuil1").Activate
    Call copie("ventes", 1)
    Call copie("origine", 3)

End Sub

Private Sub copie(ByVal chaine As String, ByVal numcol As Byte)

    Dim valeur As String

    For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

    valeur = Replace(Cells(4, colonne).Value, " ", "")

        If valeur = chaine Then
            Range(Cells(5, colonne), Cells(Range("A" & Rows.Count).End(xlUp).Row, colonne)).Copy _
            ThisWorkbook.Worksheets("Feuil1").Cells(6, numcol)
            Exit For
        End If

    Next

End Sub

C'est plus agréable à l'oeuil 8)

J'aurais bien quelques petits trucs supplémentaires a demander, mais j'attends de voir si tu es toujours d'attaques. Ce qui risque de me tracasser maintenant c'est la méthodo sur la sauvegarde que je voudrais obtenir (cf. mon petit post du dessus   ).

Normalement c'est bon (cf dessus également) mais si tu as des questions tu peux les poser quand même.

Re-coucou ,

Je viens de vérifier mes 2 fichiers sources, et il y bien concordance des 2 colonnes sur chaque tables (j'ai coupé l'une d'entre elles que j'ai juxtaposé à coté de l'autre pour vérifier et tout concorde). Ouffff, ça m'évite l'opération de tri

Grâce à toi j'ai une base solide, j'adore ce type d’architecture où la macro lance des procédures qu'on crées les unes à la suites des autres.

J'ai 2 petites dernières turpitudes dont je te parlais un peu plus haut :

1) Si je souhaite retravailler les données, est-ce qu'il me suffit de créer une nouvelle sous procédure juste après la procédure de copie, et avant celle de l’enregistrement j'imagine ? Par exemple, je souhaite diviser le nombre de porte par 2 (même si c'est un non sens, juste pour l'exemple ), il me faudrait créer :

 Private Sub divison_porte (ByVal chaine As String, ByVal numcol As Byte) 
 Range("nombredeporte",4).Select
GoSub div2

Si le code est bon, la hiérarchisation du script complet serait-il :

a) Macro qui lance toutes les sous procédures les unes à la suite des autres

b) procédure de copie des données sources vers classeurCC (bilan)

c) procédure de manipulation des données directement sur CC

d) enregistrement d'une copie du classeurCC

J'ai juste quelque doute sur cette logique et la place du 3eme point notamment ?

2) partant sur le fait que je puisse intercaller des sous procédure de manipulation des données, admettons que je veuille rejeter vers un nouvelle onglet les voitures dont l'origine est péruvienne, le script donnerait-il quelque chose de semblable :

Private Sub table_rejet(ByVal chaine As String, ByVal numcol As Byte)

 Dim origine As String

 For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column
   If origine = "Pérou" Then
             ... action d'exclure chaque ligne dans son intégrité vers un onglet appeler "rejets" (sur ce même classeur)
                Exit For
            End If

        Next

    End Sub

L'onglet rejet aurait exactement la même structure que l'onglet Feuille1, du coup je suis en train de me demander si on pourrait pas utiliser à nouveau procédure_copie vers l'onglet rejet pour les voiture dont l'origine est péruvienne ?

Pardon d'ajouter une nouvelle contrariété au cas

Et sincère remerciements pour l'aide apportée

Je te conseille de créer une nouvelle sous-routine de copie, ton traitement est différent donc il n'y a pas de raison de réutiliser la même.

La hierarchisation de ton code serait bonne mais j'ai du mal à voir où tu veux en venir avec cette histoire de divisions de portes.

Le mieux est que tu essaies de le faire puis que tu m'envoies tes fichiers pour que je corrige si nécessaire. Là tu as modifié du code et je n'ai pas accès à ce que tu as fait depuis.

A+

Coucou Migou ,

Je m'y suis prise toute la journée avec tout les supports dont je dispose et surtout avec tes explications, et je commence à sortir la tête de l'eau !!

Voilà le script tel qu'il est pour le moment :

    Dim wkb_AA As Workbook, wkb_BB As Workbook
'-----------------------------------------------------------------------------------------------------------
    Sub completer()

        Application.ScreenUpdating = False 'accélère l'exécution du code de la  macro en désactivant le rafraich. écran

        Dim position As Worksheet 'variable position en tant que feuille
        Set position = ThisWorkbook.ActiveSheet 'initialise la variable objet "position" pour qu'elle pointe vers la feuille active de ce claseur

        nettoyer  'toutes les sous procédures qui seront appelées une par une dans ma macro
        ouvrir_fichiers 'idem
        lancer_copie 'idem
        enregistrer_copie 'idem

        position.Activate 'feuille de calcul "position" activée.

    End Sub

'-----------------------------------------------------------------------------------------------------------------

    Private Sub nettoyer()

        Range(Cells(6, 1), Cells(6, 4)).Select 'selectionne la plage de données à cleaner
        Range(Selection, Selection.End(xlDown)).Clear 'supprime l'objet range défini au dessus entierement

    End Sub

'-----------------------------------------------------------------------------------------------------------------
    Private Sub ouvrir_fichiers()

        Set wkb_AA = Workbooks.Open(ThisWorkbook.Path & "\ClasseurAA.xls") 'ouvre les 2 classeurs
        Set wkb_BB = Workbooks.Open(ThisWorkbook.Path & "\ClasseurBB.xls")

    End Sub

'-----------------------------------------------------------------------------------------------------------------
    Private Sub lancer_copie()  'Je pense avoir intégrée ci dessous le max de colonne, si j'en ai oubliées c'est par distraction (cette étape est bien assimilée pour moi)

        wkb_AA.Worksheets("Feuil1").Activate
        Call copie("N°voiture", 2)
        Call copie("nombredeporte", 4)
        call copie("poids",12)

        wkb_BB.Worksheets("Feuil1").Activate
        Call copie("ventes", 1)
        Call copie("origine", 3)
        Call copie("prix", 9)
        Call copie("codedéfaut", 10)

    End Sub

'-----------------------------------------------------------------------------------------------------------------
    Private Sub copie(ByVal chaine As String, ByVal numcol As Byte)

        Dim valeur As String

        For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

        valeur = Replace(Cells(4, colonne).Value, " ", "")

            If valeur = chaine Then
                Range(Cells(5, colonne), Cells(Range("A" & Rows.Count).End(xlUp).Row, colonne)).Copy _
                ThisWorkbook.Worksheets("Feuil1").Cells(6, numcol)
                Exit For
            End If

        Next

    End Sub

'-----------------------------------------------------------------------------------------------------------------
    Private Sub enregistrer_copie()

        Application.DisplayAlerts = False

        FermerClasseur ("ClasseurAA.xls")
        FermerClasseur ("ClasseurBB.xls")

        Application.Dialogs(xlDialogSaveAs).Show  'ouvre une boite de dialogue "enregistrer sous"

        Application.DisplayAlerts = True

    End Sub
'-----------------------------------------------------------------------------------------------------------------
    Sub FermerClasseur(nomclasseur As String)
    On Error Resume Next
        Workbooks(nomclasseur).Close False
    End Sub

Pour les opérations de traitement qui me reste à faire, j'ai réédité le contenu de mes 3 classeurs (qui sont attachés à ce poste) pour que ça soit moins confus que lors de mes dernières tentatives ( ). J'ai aussi à compléter le code en suivant la logique du script que tu m'as initié.

Il me reste quelques opérations de traitement (j'ai bien une idée de la façon de concevoir ça mais il reste à faire)

1) LA première opération c'est d'envoyer les véhicules qui ont pour "origine" (colonne4, ClasseurBB) le Pérou dans l'onglet rejets du ClasseurCC. L'onglet contiendrait exactement les mêmes intitulés des colonnes que sur la feuille1 (même masque, mais leurs simple présence dans l'onglet rejets suffirait au lecteur pour comprendre que les données s'y trouvant valent : origine = "Pérou")

D’après tes dire je dois refaire une sous procédure de copie mais qui serait propre à l'onglet rejets.

Donc ... j'me lance :

- Sachant que la colonne "origine" (colonne4, ClasseurBB) apparait que sur le classeurBB, je ne peux pas lui dire d'aller extraire les lignes du classeurCC.worksheet("Feuil1") contenant origine = "Pérou" pour les envoyer sur l'onglet rejets.

- Je dois donc lui dire d'aller sur (colonne4, ClasseurBB) et de renvoyer toutes les lignes contenant origine="Pérou" (mais il faudrait que l'onglet rejet conserve le même masque que l'onglet "Feuille1" de ce ClasseurCC, ce qui m'oblige de nouveau à une selection et assignation des colonnes comme nous l'avions fait pour la copie des colonnes dans la procédure "lancer_copie" ?

- Je devrais donc créer une sous procédure "copie_rejets" qui irait chercher les éléments des lignes associées à la valeur origine= "Pérou" sur le ClasseursBB.

- Je me rend compte que là va se poser le problème de solidarisation des lignes, je peux pas extraire 3 lignes Pérou de ma base sans leur associer les autres infos(N°voiture, vente, etc..) par lignes qui les concerne.... Peut être qu'un .EntireRow fonctionnerait mais le soucis c'est que je n'ai besoin que de certaines colonnes (onglet rejets doit être similaire à l'onglet feuille 1 du ClasseurCC).

- La grosse tuile c'est que la colonne "origine" existe uniquement sur le ClasseurBB, et que sur "l'onglet rejet" figure des éléments des 2 classeurs AA et BB. Mais une seule colonne est commune aux 2 classeurs, c'est la colonne "N°voiture" (colonne 3 pour AA, et colonne 2 pour BB). J'imagine la complexité de la chose mais peut-on faire un lien entre les 2 tables en se servant de la colonne pivot "N°voiture" pour afficher les colonnes qui ne concerne que les voiture rejetées parce que origine= "Pérou" ?

  

        Private Sub copie_rejets(ByVal chaine As String, ByVal numcol As Byte)

        Dim valeur As String

        For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

        valeur = Replace(Cells(4, colonne).Value, " ", "")

            If valeur = chaine Then
                Range(Cells(5, colonne), Cells(Range("A" & Rows.Count).End(xlUp).Row, colonne)).Copy _
                ThisWorkbook.Worksheets("Table rejets").Cells(6, numcol)
                Exit For
            End If

        Next

    End Sub

J'avais prévu ceci dans la foulée, mais je ne sais pas où faire figurer l'instruction conditionnelle (IF origine="Pérou" THEN on copie les éléments des colonnes associées à cette ligne qui contient Pérou dans l'onglet rejets) :

        Private Sub lancer_copie_rejets()

        wkb_AA.Worksheets("Table Rejets").Activate
        Call copie_rejets("N°voiture", 2)
        Call copie_rejets("nombredeporte", 4)
        Call copie_rejets("poids", 12)

        wkb_BB.Worksheets("Table Rejets").Activate
        Call copie_rejets("ventes", 1)
        Call copie_rejets("origine", 3)  'redondant car dans l’onglet rejets se trouverait que les voiture qui ont pour origine le Pérou
        Call copie_rejets("prix", 9)
        Call copie_rejets("codedéfaut", 10)

    End Sub

Et ma macro appellerait les procédure suivantes :

    Dim wkb_AA As Workbook, wkb_BB As Workbook

    Sub completer()

        Application.ScreenUpdating = False 'accélère l'exécution du code de la  macro

        Dim position As Worksheet 'variable position en tant que feuille
       Set position = ThisWorkbook.ActiveSheet 'initialise la variable position comme feuille active

        nettoyer  'toutes les sous procédures qui seront appelées une par une dans ma macro
       ouvrir_fichiers 
       lancer_copie 
         lancer_copie_rejets 'c'est là qu'on lance la copie des rejets vers ClasseurCC.worksheet("Table rejet")
       enregistrer_copie 'idem

        position.Activate 'feuille de calcul "position" activée.

    End Sub
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2) La suite est liée à un remaniement/conversion des données, mettons que je veuille par exemple convertir la colonne poids(colonne 11, ClasseurCC, 1er onglet) de kg à tonne. J'ai juste à créer une sous procédure et l’appeler dans ma macro principale juste avant la sous procédure qui enregistre ?
Private Sub convertir_tonnes() 'on nomme la sous procédure
Range("K:K").Select 'conversion sur toute la colonne "poids"
GoSub div1000

'passage de kilo à tonne

Ce qui ferait pour ma macro principale si on suppose que je désire ajouter d'autres procédures de manipulation de donnée une structure de ce genre ? :

    nettoyer  'toutes les sous procédures qui seront appelées une par une dans ma macro
       ouvrir_fichiers 'idem
       lancer_copie 'idem
        copie_des_rejets  
        convertir_tonnes 
        convertir_prix_£   
        ....etc....
       enregistrer_copie 'idem
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3) Sur mon ClasseurAA j'ai un code produit (colonne 6) qui en réalité est une longue chaine de caractère qui contient les données de 3 colonnes sur le ClasseurCC.
  • Les 4 premiers caractères réfèrent un "code vendeur" en classeurCC (colonne5).
  • Les 2 caractères suivants réfèrent une "norme véhicule" en classeurCC (colonne6).
  • Les 3 derniers caractères réfèrent la "vitesse maxi" classeurCC (colonne5).

Je vais donc devoir créer une nouvelle procédure qui split les valeurs de "code produit" (colonne6, ClasseurAA) en 3 chaines pour les envoyer respectivement dans "code vendeur", "norme véhicule", "vitesse maxi" (3 colonnes autonomes) du classeur classeurCC .

Avec l'enregistreur de macro j'ai lancé une fonction GAUCHE(Cells;nombre de caractère sur la gauche à extraire), pour voir le code généré, mais je suis complétement perdue sur l'adresse des cellules à attribuer. Puis comme c'est une fonction que j'utilise peut être que je devrais créer non pas une sous procédure, mais plutôt une sous fonction en utilisant les fonctions d’extraction de type mid, instr, right, left... Bref, je suis à la dérive ...

Et si par exemple je veux convertir la vitesse maxi de km/h =====> mètres/sec (il me suffit de lancer une sous procédure de conversion comme je l'ai fait pour le point 2, ou est ce qu'il est préférable de le faire pendant l'intégration des données?

  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4) J'ai le cas inverse que je pensais pouvoir solutionner avec l'opérateur de concaténation (&), mais là encore je ne sais pas si je dois créer une nouvelle procédure, et surtout à quelle moment l'intégrer dans la séquence d'appel des procédure de ma macro "principale".

La Longueur (m) et Largeur (m) (colonne 7 et 8 du ClasseurAA) devrait être rapatriées dans une unique colonne en ClasseurCC (colonne8) et séparées l'une de l'autre par la lettre "x". J'ai donc essayée dans procédure de copie de faire comme suit :

    Private Sub lancer_copie()

        wkb_AA.Worksheets("Feuil1").Activate
        Call copie("N°voiture", 2)
        Call copie("nombredeporte", 4)
        Call copie("poids", 12)
        Call copie("Longueur(m)" & " " & "x" & " " & "Largeur(m)", 8)

    End Sub

Mais ça ne donne aucun résultat

  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5) Le dernier traitement qui me turlupine, il faudrait qu'une sous procédure détecte que si sur le classeurCC la valeur du "code défaut" (colonne 10; ClasseurCC; Feuil 1) est égale à 2 ... alors, il envoie dans la colonne intitulée "ristourne" de ce même classeur (colonne 11 ClasseurCC) la valeur "prix" ((colonne 9 ClasseurCC) +250.

Mon intuition me dit de créer une sous procédure avec du conditionnelle. Mais dois-je me baser sur la même syntaxe que la boucle de copie ?

If code défaut="2" then ristourne="prix+250"

En fait ce qui m'embête le plus, c'est cette histoire de valeurs stockée dans la mémoire et puis les résultats sont traités avant d'être copiés, ou si les données sont copiées/collées par l'instruction et ensuite on travaille dessus.

Euhhh, j'ai conscience que ça fait beaucoup d'un coup, mais c'est vraiment les dernières difficultés qui me reste, et je suis tellement contente d'avoir put adapter la méthodologie que tu m'a proposée vers des cas plus concrets avec des paramètres différents de nos exemples (et en plus ça donne des résultats tangible ! ) .

Enfin, je l'ai déjà dit, mais merci beaucoup et très sincèrement

Je continue de me pencher sur le code voir ce que je peux apporter déjà

34classeurbb.zip (16.40 Ko)
35classeuraa.zip (18.02 Ko)

Salut Jenny, je regarde ça dès que j'ai le temps. Ce sera probablement mercredi soir. A+

Coucou Migou ,

Merci de ne pas m'avoir abandonnée (même si tu as déjà beaucoup fais).

J'ai réédité mon post pour rendre les questions plus claires, les infos sur les valeurs sont localisées entres parenthèses, et les données sont plus inéligibles.

Je continue à travailler d’arrachepied mes scripts, et j’espère pouvoir intégrer la méthodologie que tu me proposera sur les données que je traite en parallèle (pour le moments ça fonctionne du tonnerre, je suis parvenue à tout refaire et je documente tout ce que je fais pour que ça me sois encore plus profitable).

Euh, oui je suis une fille très bavarde ....

Merci encore ! (comme ça c'est dit )

1) LA première opération c'est d'envoyer les véhicules qui ont pour "origine" (colonne4, ClasseurBB) le Pérou dans l'onglet rejets du ClasseurCC. L'onglet contiendrait exactement les mêmes intitulés des colonnes que sur la feuille1 (même masque, mais leurs simple présence dans l'onglet rejets suffirait au lecteur pour comprendre que les données s'y trouvant valent : origine = "Pérou")

D’après tes dire je dois refaire une sous procédure de copie mais qui serait propre à l'onglet rejets.

Je pars du principe que les numéros de voitures sont uniques, ce qui n'est pas ton cas et pose mais je suppose que c'est une erreur dans les fichiers que tu m'envoies. Le raisonnement sera le suivant :

1) Identification de la colonne contenant le numéro de voiture sur le classeur BB.

2) Identification de la colonne contenant l'origine des voitures sur le classeur BB

2) Filtrage automatique des données sur le classeur BB pour ne conserver que les péruvienne.

3) Copie les données non filtrées sur le classeur CC.

4) Suppression du filtre.

On se retrouve donc avec les numéros de voitures péruviennes en colonne 2 du classeur CC. On va s'en servir pour récupérer les informations complémentaires sur AA.

1) identification de la colonne contenant les numéros de voiture dans AA

2) Identification de la colonne contenant les ventes dans AA

3) On parcours les numéros de voitures dans CC puis, pour chaque numéro de voiture ...

4) ... On parcours La colonne numéro de voiture dans AA.

5) S'il y a jointure / correspondance, on copie les infos qui nous intéressent

Voilà le code, j'ai tout mis dans la même Sub pour éviter de te perdre mais tu peux le découper si tu trouves trop lourd) :

    Dim wkb_AA As Workbook, wkb_BB As Workbook

    Sub completer()

        Application.ScreenUpdating = False 'accélère l'exécution du code de la  macro

        Dim position As Worksheet 'variable position en tant que feuille
        Set position = ThisWorkbook.ActiveSheet 'initialise la variable position comme feuille active

        nettoyer  'toutes les sous procédures qui seront appellées une par une dans ma macro
        ouvrir_fichiers 'idem
        'lancer_copie 'idem
        traiter_rejets
        'enregistrer_copie 'idem

        position.Activate 'feuille de calcul "position" activée.

    End Sub

    Private Sub nettoyer()

        Range(Cells(6, 1), Cells(6, 4)).Select 'selectionne la plage de données à cleaner
        Range(Selection, Selection.End(xlDown)).Clear 'supprime l'objet range défini au dessus entierement

    End Sub

    Private Sub ouvrir_fichiers()

        Set wkb_AA = Workbooks.Open(ThisWorkbook.Path & "\ClasseurAA.xls") 'ouvre les 2 classeurs
        Set wkb_BB = Workbooks.Open(ThisWorkbook.Path & "\ClasseurBB.xls")

    End Sub

    Private Sub lancer_copie()

        wkb_AA.Worksheets("Feuil1").Activate
        Call copie("N°voiture", 2)
        Call copie("nombredeporte", 4)
        Call copie("poids", 12)

        wkb_BB.Worksheets("Feuil1").Activate
        Call copie("ventes", 1)
        Call copie("origine", 3)
        Call copie("prix", 9)
        Call copie("codedéfaut", 10)

    End Sub

    Private Sub copie(ByVal chaine As String, ByVal numcol As Byte)

        Dim valeur As String

        For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

        valeur = Replace(Cells(4, colonne).Value, " ", "")

            If valeur = chaine Then
                Range(Cells(5, colonne), Cells(Range("A" & Rows.Count).End(xlUp).Row, colonne)).Copy _
                ThisWorkbook.Worksheets("Feuil1").Cells(6, numcol)
                Exit For
            End If

        Next

    End Sub

    Private Sub traiter_rejets()

        ' Première étape : récupération des données de BB

        Dim valeur As String, num As String
        Dim origine As Byte, numero As Byte, ventes As Byte, nombreDePortes As Byte
        orgine = 0: numero = 0: ventes = 0: nombreDePortes = 0
        valeur = "": num = ""

        wkb_BB.Activate

        For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

            valeur = Replace(Cells(4, colonne).Value, " ", "")
            If valeur = "N°voiture" Then numero = colonne
            If valeur = "origine" Then origine = colonne
            If valeur = "ventes" Then ventes = colonne
            If Not origine = 0 And Not numero = 0 And not ventes =0 Then Exit For

        Next

        Range(Cells(4, 1), Cells(4, 1).End(xlToRight)).AutoFilter origine, "Pérou"

        Range(Cells(5, numero), Cells(Range("A" & Rows.Count).End(xlUp).Row, numero)).Copy _
        ThisWorkbook.Worksheets("Table Rejets").Cells(6, 1)

        Range(Cells(5, numero), Cells(Range("A" & Rows.Count).End(xlUp).Row, numero)).Copy _
        ThisWorkbook.Worksheets("Table Rejets").Cells(6, 2)

        Range(Cells(5, origine), Cells(Range("A" & Rows.Count).End(xlUp).Row, origine)).Copy _
        ThisWorkbook.Worksheets("Table Rejets").Cells(6, 3)

        Range(Cells(4, 1), Cells(4, 1).End(xlToRight)).AutoFilter

        ' Seconde étape : récupération des données de AA

        wkb_AA.Activate

        numero = 0
        For colonne = 1 To Cells(4, Cells.Columns.Count).End(xlToLeft).Column

            valeur = Replace(Cells(4, colonne).Value, " ", "")
            If valeur = "nombredeporte" Then nombreDePortes = colonne
            If valeur = "N°voiture" Then numero = colonne
            If Not nombreDePortes = 0 And Not numero = 0 Then Exit For

        Next

        ThisWorkbook.Worksheets("Table Rejets").Activate

        For Each cell_CC In Range(Cells(6, 2), Cells(Range("B" & Rows.Count).End(xlUp).Row, 2))

            num = Replace(cell_CC.Value, " ", "")
            wkb_AA.Activate

            For Each cell_AA In Range(Cells(5, numero), Cells(Range("A" & Rows.Count).End(xlUp).Row, numero))

                If Replace(cell_AA.Value, " ", "") = num Then
                    Cells(cell_AA.Row, nombreDePortes).Copy ThisWorkbook.Worksheets("Table Rejets").Cells(cell_CC.Row, 4)
                    Exit For
                End If

            Next

            ThisWorkbook.Worksheets("Table Rejets").Activate

        Next

    End Sub

    Private Sub enregistrer_copie()

        Application.DisplayAlerts = False

        FermerClasseur ("ClasseurAA.xls")
        FermerClasseur ("ClasseurBB.xls")

        Application.Dialogs(xlDialogSaveAs).Show 'permet de créer un nouveau fichier enregistrer sous

        Application.DisplayAlerts = True

    End Sub

    Sub FermerClasseur(nomclasseur As String)
    On Error Resume Next
        Workbooks(nomclasseur).Close False
    End Sub

Attention : comme tu as des voitures qui ont le même numéro mais un nombre de portes différent, mon code te renvoies la première voiture rencontrée.

J'ai voulu codé ça sans me prendre la tête mais s'il s'avère que tu as plusieurs milliers de ligne dans ton vrai fichier, mon code (la partie récup des données de AA) pourra s'avérer assez lent. Pour l'optimiser tu peux faire un filtre sur les numéros de voiture qui t'intéressent de sorte à avoir immédiatement le nombre de porte.

2) La suite est liée à un remaniement/conversion des données, mettons que je veuille par exemple convertir la colonne poids(colonne 11, ClasseurCC, 1er onglet) de kg à tonne. J'ai juste à créer une sous procédure et l’appeler dans ma macro principale juste avant la sous procédure qui enregistre ?

Séléctionne ta plage et fait une boucle :

For Each cell In Range(TaPlage)
    cell.Value = cell.Value / 1000
Next

-Les 4 premiers caractères réfèrent un "code vendeur" en classeurCC (colonne5).

  • Les 2 caractères suivants réfèrent une "norme véhicule" en classeurCC (colonne6).
  • Les 3 derniers caractères réfèrent la "vitesse maxi" classeurCC (colonne5).

De mémoire, ça doit donner ça :

code_vendeur = Left(chaine, 4)
norme_vehicule = Mid(chaine, 5, 2)
vitesse_max = Right(chaine, 2)

La Longueur (m) et Largeur (m) (colonne 7 et 8 du ClasseurAA) devrait être rapatriées dans une unique colonne en ClasseurCC (colonne8) et séparées l'une de l'autre par la lettre "x". J'ai donc essayée dans procédure de copie de faire comme suit :

Aucune chance que ça marche comme ça, créé toi une nouvelle Sub. Pour concaténer c'est effectivement un & :

cellule1.value = cellule2.value & cellule3.value 

5) Le dernier traitement qui me turlupine, il faudrait qu'une sous procédure détecte que si sur le classeurCC la valeur du "code défaut" (colonne 10; ClasseurCC; Feuil 1) est égale à 2 ... alors, il envoie dans la colonne intitulée "ristourne" de ce même classeur (colonne 11 ClasseurCC) la valeur "prix" ((colonne 9 ClasseurCC) +250.

Mon intuition me dit de créer une sous procédure avec du conditionnelle. Mais dois-je me baser sur la même syntaxe que la boucle de copie ?

Oui

En fait ce qui m'embête le plus, c'est cette histoire de valeurs stockée dans la mémoire et puis les résultats sont traités avant d'être copiés, ou si les données sont copiées/collées par l'instruction et ensuite on travaille dessus.

Il n'est pas toujours nécessaire travailler avec des variables. Par exemple pour reprendre des prix et ristournes tu peux faire une boucle qui incrémente la ligne et se contente de :

If cells(ligne, 9).Value = 2 then Cells(ligne, 8).Value = Cells(ligne, 8).Value + Cells(ligne,10).value

(Je met les numéros de colonnes un peu au hasard)

Ou plus rapide, inscrire la formule dans la cellule et utilisée la poignée de recopie (possible via VBA).

A+

Coucou Migou et merci d'être revenu à ma rescousse ,

Je travaille sur les éléments que tu m'as apportés depuis que tu as posté, donc j'accuse un peu la fatigue et ce que je fais ne tourne pas comme ça devrait.

Je me penche à nouveau sur tout ça à la première heure demain matin (et plus fraiche) .

Merci pour tout,

Jenny

Je dois être bien chiante en revenant ainsi à la charge, mais j'aimerais tellement que cette macro fonctionne

Tout ça pour dire que je suis encore en galère, et je croise les doigts pour que tu es encore la patience de t'occuper de mon cas.

1) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------

J'ai repris le script pour exclure les voitures qui ont pour origines "Pérou" est malheureusement ça ne tourne pas chez moi. J'ai relevée une erreur dans un intitulé mais même en corrigeant, rien n'y fait. La sous procédure copie toutes les voitures dans l’onglet rejets (d'ailleurs ça n'est pas une erreur, on peut très bien avoir plusieurs voitures avec le même numéro, l'important c'est de détecter "Pérou" est d'exclure la ligne") .

Est-ce qu'on ne pourrait pas faire plus simplement avec ta permission:

- Si j'ajoute la colonne "origine" dans mon classeurCC, j'alimente cette colonne avec la sous procédure de copie conventionnelle (que je maitrise bien maintenant), on lui dit alors de fouiller ligne par ligne le classeurCC Feuil1, puis dès qu'il détecte la ligne "origine"= "Pérou", il l'envoie vers l'onglet rejet de ce même classeur. Une fois qu'il à tout exclut, on lui demande de cacher la colonne "origine" sur les 2 classeurs.

C'est pas très jojo, mais même en m'y reprenant toute l'après midi, et essayant de comprendre et commentant le script via tri, je ne m'en sors pas

2) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

Une bonne nouvelle pour la suite , Youpiii !!!

La procédure de conversion fonctionne magnifiquement bien, j’ai testé ca sur pleins d’autres colonnes et de type de données, rien à redire. Le script manque d’élégance mais les résultats sont bons (j’y ai même ajouté un Selection.NumberFormat = "0.0..etc…" pour peaufiner).

 
  Private Sub conversion()
    Range("L6").Select
    For Each cell In Range(Selection, Selection.End(xlDown))
        cell.Value = cell.Value / 1000
    Next
    End Sub

Par contre et assez bizarrement la procédure de conversion ne fonctionne pas avant la sous procédure d’enregistrement des données. Mais elle tourne impeccablement après l’enregistrement. C'est pas un peu ambigu d’un point de vu logique ?

3) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

Pour l’extraction de caractère du « code produit » vers 3 colonnes, j’ai tenté de le faire directement dans la procédure de copie intitulée (Private Sub lancer_copie) sous cette forme là :

 
    Private Sub lancer_copie()

        wkb_AA.Worksheets("Feuil1").Activate
        Call copie("N°voiture", 2)
        Call copie("nombredeporte", 4)
        …..... etc...
        Call copie("codevendeur" = Left("code produit", 4), 5)

Mais la colonne reste vide (sans doute normal puisque la procédure attends le titre d’une colonne source pour lancer la copie).

Donc j’ai rapatriée via la procédure de copie la colonne « code produit » (Classeur AA colonne 6) telle qu’elle est vers le fichier CC. En espérant ensuite pouvoir retravailler le contenu de la colonne en créant une procédure de Left sur la colonne, mais la colonne reste désespérément identique.

    Private Sub split_1()
            Range("E6").Select
            For Each cell In Range(Selection, Selection.End(xlDown)).Select
            code_vendeur = Left(Selection, 4)
            Next
    End Sub

4) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------

Pour l’opération de jonction, je n’ai pas plus de résultat. Je pense que je fais la confusion en pensant que « cell » désigne une cellule alors qu’il s’agit plutôt d’une variable qui doit être déclarée. Du coup j’ai une erreur script sans savoir comment solutionner.

Private Sub joindre()
Range("H6").Select
For Each cell In Range(Selection, Selection.End(xlDown)).Select
 wkb_CC.Worksheets("Feuil1").Cells(6, 8).Value = wkb_AA.Worksheets("Feuil1").Cells(5, 8).Value & _
 wkb_AA.Worksheets("Feuil1").Cells(5, 8).Value
 Next
 End Sub 

5)---------------------------------------------------------------------------------------------------------------------------------------------------------------------

Pour le traitement conditionnel (si code défaut = 2 alors la « ristourne » vaux « prix » + 250).

Je fais la sous procédure suivante que je lance à partir de la macro principale. Mais là encore les résultats ne sont pas probants et rien ne se passe... .. Je pense que la sélection et les déplacements ligne par ligne me sont fatals dans tous mes scripts.

Private Sub recalcul()
 Range("K6").Select
 For Each cells In Range(Selection, Selection.End(xlDown)).Select
 If cells(ligne, 10).Value = 2 Then cells(ligne, 11).Value = cells(ligne, 9).Value + 250
 Next
 End Sub

Je ne sais pas si tu aura encore le temps et la volonté de t'occuper de moi, mais sans vouloir insister sur les sentiments ça me permettrais de trouver enfin le sommeil.

Enfin .. merci encore

Jenny

Hop, juste un p'tit mot pour dire que le script de tri et de copie fonctionne maintenant parfaitement bien chez moi, et sur tout mes cas d'application. Je continue de plancher sur les points suivants.

Merci encore,

Jenny.

J'ai repris le script pour exclure les voitures qui ont pour origines "Pérou" est malheureusement ça ne tourne pas chez moi. J'ai relevée une erreur dans un intitulé mais même en corrigeant, rien n'y fait. La sous procédure copie toutes les voitures dans l’onglet rejets (d'ailleurs ça n'est pas une erreur, on peut très bien avoir plusieurs voitures avec le même numéro, l'important c'est de détecter "Pérou" est d'exclure la ligne") .

Sauf qu'au moment où tu vas récupérer le nombre de portes à partir des numéros de voitures fraîchement copiés, on se retrouve a avoir des voitures qui ont le même numéro mais un nombre de portes différents. On est censé renvoyé quoi du coup ? Mon code comme je te l'ai dit, renvoie le nombre de portes de la première voiture trouvée et passe au numéro de voiture suivant.

La procédure de conversion fonctionne magnifiquement bien, j’ai testé ca sur pleins d’autres colonnes et de type de données, rien à redire. Le script manque d’élégance mais les résultats sont bons (j’y ai même ajouté un Selection.NumberFormat = "0.0..etc…" pour peaufiner).

Fais particulièrement attention quand tu manipules Selection.End(xlDown), si tu as des cellules vides il est possible que la sélection n'aille pas réellement jusqu'à la dernière ligne. Pour résoudre le problème tu peux te faire une fonction qui renvoie le numéro de la dernière ligne, basée sur une colonne qui sera à coup sur pleine.

Call copie("codevendeur" = Left("code produit", 4), 5)

Cela n'a strictement aucun sens.

Donc j’ai rapatriée via la procédure de copie la colonne « code produit » (Classeur AA colonne 6) telle qu’elle est vers le fichier CC. En espérant ensuite pouvoir retravailler le contenu de la colonne en créant une procédure de Left sur la colonne, mais la colonne reste désespérément identique.

    Private Sub split_1()
            Range("E6").Select
            For Each cell In Range(Selection, Selection.End(xlDown)).Select
            code_vendeur = Left(Selection, 4)
            Next
    End Sub

Normal, la c'est ta variable qui prend la valeur de la sélection, mais à aucun moment tu n'écris le résultat dans la cellule. Il est donc perdu dès que tu attaque le tour de boucle suivant.

Je n'ai pas excel sous la main donc le code est à tester :

    Private Sub split_1()
            Range("E6").Select
            For Each cell In Range(Selection, Selection.End(xlDown)).Select
            cell.value = Left(cell.value, 4)
            Next
    End Sub

Pour tes problèmes de déplacement par ligne, va faire un tour du côté des tutoriaux VBA sur les boucles. Toi tu mélanges les boucles For et les boucles For each, c'est normal que ça ne donne rien.

Hello, et merci pour ton post

Oui je me rends compte des lacunes que j'ai (un peu moins maintenant que j'y travaille jours et nuit, mais il me reste à faire c'est évident). Je fais les choses au plus simples quit à utiliser des subterfuge telles que des colonnes temporaire que je masque en fin de procédure. C'est pas très jolie mais le résultats et là (à quelques secondes près d’exécution ).

Merci pour ta mise en garde sur la sélection de mes plages, je pense avoir repéré une façon de faire qui permet d'aller tout en bas de la feuille pour ensuite remonter chercher la première cellule rencontrée en remontant qui est non vide. Ça doit être ça si je dis pas de bêtise :

 Cells(.Rows.Count, 1).End(xlUp).Row

ou sinon :

Range([A1], [A65535].End(xlUp)

Pour le reste j'ai su traiter la moitié des cas qui me bloquaient, et ceux qui restent en suspens, ... j'y travaille dur

Sincère remerciement à toi pour tout le temps que tu m'a accordé sur ces 4 pages et plus

Jenny.

Rechercher des sujets similaires à "fichiers copie certaines colonne fichier resume"