Couper coller en boucle avec condition

Fermé
ryooutside86 Messages postés 3 Date d'inscription lundi 22 juin 2015 Statut Membre Dernière intervention 22 juin 2015 - 22 juin 2015 à 13:07
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 - 24 juin 2015 à 11:36
Bonjour,

Je suis archi débutante en vba et je suis confrontée à la remise en forme d'un fichier excel de plus de 2700 lignes...
Il s'agit d'une conversion d'un fichier csv (j'ignore si cela peut avoir son importance).
J'ai besoin de mettre en linéaire les info : 1 facture = 1 ligne or en l'état actuel du fichier 1 facture = 1 à 5 lignes. Je voudrais donc renvoyer les info des lignes 2 et 3 en ligne 1, sachant que les lignes 2 et 3 différent de la ligne 1 car les colonnes B à F sont vides.

Comment mettre en place une mise en forme automatique avec les conditions :
- si colonnes B à F vides sur 1 seule ligne alors couper les données des colonnes G à F et les coller sur ligne n-1 dans les colonnes O à S
- si colonnes B à F vides sur 2 lignes coller les colonnes G à F de la première ligne sur la ligne n-1 aux colonnes O à S et coller les colonnes G à F de la deuxième ligne sur la ligne n-2 dans les colonnes W à AB
- si les colonnes colonnes B à F vides sur 3 lignes coller les colonnes G à F de la première ligne sur la ligne n-1 aux colonnes O à S, coller les colonnes G à F de la deuxième ligne sur la ligne n-2 aux colonnes W à AB et coller les colonnes G à F de la colonne n-3 dans les colonnes AE à AJ
-...et ainsi de suite

N"hésitez pas à me faire savoir si ma demande manque de clarté.

Par avance un grand merci pour votre aide.

Cordialement


A voir également:

14 réponses

ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
22 juin 2015 à 15:08
Bonjour Ryooutside, bonjour le forum,

C'est clair mais... Un petit fichier exemple avec juste quelques lignes de ce que tu as dans un onglet et le résultat que tu souhaite dans un autre serait plus qu'utile...
0
ryooutside86 Messages postés 3 Date d'inscription lundi 22 juin 2015 Statut Membre Dernière intervention 22 juin 2015
22 juin 2015 à 15:42
Suite à la requête de Thautheme,

Je vous joins des images du fichier source, de la trame à employer et du résultat attendu.

N'hésitez pas à me faire savoir si la lisibilité est médiocre car le tableau étant large il est impossible d'avoir une vision d'ensemble lisible.
Est il possible de joindre un fichier excel ? Si oui, je vous invite à m'indiquer comment faire car pour l'heure, je n'ai pas trouvé comment procéder...



Un grand merci pour votre secours...
A bientôt
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
22 juin 2015 à 15:56
Bonjour Ryooutside, bonjour le forum,

pour joindre un fichier voir https://www.cjoint.com/ (par exemple)...


0
ryooutside86 Messages postés 3 Date d'inscription lundi 22 juin 2015 Statut Membre Dernière intervention 22 juin 2015
22 juin 2015 à 16:05
Voici le lien : https://www.cjoint.com/c/EFwodugIjJw

Merci beaucoup pour le tuyau Thautheme !!
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
23 juin 2015 à 00:26
Bonsoir Ryooutside, bonsoir le forum,

Le code ci-dessous fonctionne mais pas avec ton exemple qui comporte des lignes cachées. Je me suis basé sur ton exemple et je n'ai copié que les lignes visible dans un onglet que j'ai nommé Source (tu adapteras). L'onglet Source2 me sert uniquement à remettre les données originales dans l'onglet Source (j'ai rajouté quelques lignes pour pouvoir vérifier le code)...
Lance la macro et regarde le résultat dans l'onglet Destination. Évidemment, il suffit d'une ligne en plus (ou en moins), d'une colonne en plus (ou en moins) pour le code cesse de fonctionner correctement. C'est pourquoi je n'ai pas aimé l'exemple que tu as fourni...

Code commenté :

Sub Macro1()
Dim S As Worksheet 'déclare la variable S (onglet Source)
Dim D As Worksheet 'déclare la variable D (onglet Destination)
Dim PL As Range 'déclare la variable PL (PLage)
Dim DL As Integer 'déclare la variable DL (Dernière Ligne)
Dim TC As Variant 'déclare la variable TC (Tableau de Cellules)
Dim I As Integer 'déclare la variable I (Incrément)
Dim LD As Long 'déclare la variable LD (Ligne du Début)
Dim LF As Long 'déclare la variable LF (Ligne de Fin)
Dim NL As Long 'déclare la variable NL (Nombre de Lignes)
Dim DEST As Range 'déclare la variable DEST (cellule de DESTination)
Dim DC As Integer 'déclare la variable DC (DéCalage)

Set S = Sheets("Source") 'définit l'onglet source S (à adapter)
Set D = Sheets("Destination") 'définit l'onglet destination D (à adapter)
Set PL = S.Range("A1") 'définit (initialise) la plage PL
DL = S.Cells(Application.Rows.Count, 9).End(xlUp).Row 'définit la dernière ligne éditée DL de la colonne 9 (=I) de l'onglet S
TC = S.Range("A4:P" & DL) 'définit le tableau de cellules TC

'cette première boucle va supprimer les ligne vides
For I = 1 To UBound(TC, 1) 'boucle sur toutes les ligne I du tableau de cellules TC
    If Application.Sum(Application.Index(TC, I)) = 0 Then 'condition : si la somme de la ligne vaut 0
        'définit la plage PL (la ligne I+3 si PL ne contient qu'une seule cellule, sinon, l'union de PL et de la ligne I+3)
        Set PL = IIf(PL.Cells.Count = 1, Rows(I + 3), Application.Union(PL, Rows(I + 3)))
    End If 'fin de la condition
Next I 'prochaine ligne de la boucle
PL.Delete 'efface la plage PL (supprime les lignes vides)

DL = S.Cells(Application.Rows.Count, 9).End(xlUp).Row 'redéfinit la dernière ligne éditée de la colonne 9 (=I) de l'onglet S
TC = S.Range("A4:P" & DL) 'redéfinit le tableau de cellules TC
For I = 1 To UBound(TC, 1) 'boucle 1 : sur toutes les lignes I du tableau de cellules TC
    If TC(I, 1) <> "" Then 'condition : si la valeur ligne I colonne 1 de TC n'est pas vide
        Set DEST = D.Cells(Application.Rows.Count, 2).End(xlUp).Offset(1, 0) 'définit la cellule de destination DEST
        LD = I + 3 'définit la ligne de début LD
        LF = S.Cells(I + 3, 1).End(xlDown).Row - 1 'définit la ligne de fin LF
        If LF > DL Then LF = DL 'si LF est supérieur à DL, alors LF devient DL
        NL = LF - LD 'définit le nombre de ligne NL
        S.Cells(I + 3, 1).Copy DEST 'copie la cellule ligne I+3, colonne 1 dans DEST
        S.Cells(I + 3, 4).Resize(1, 4).Copy DEST.Offset(0, 1) 'copie les cellules ligne I+3 colonne 4 à 7 dans DEST décalée d'une colonne à droite
        For j = 1 To NL 'boucle 2 : de 1 au nombre de ligne NL
            DC = j * 7 + (j - 3) 'définit le décalage DC
            S.Cells(I + 3 + j, 9).Resize(1, 8).Copy DEST.Offset(0, DC) 'copie les cellules de la ligne et les colle dans DEST décalée de DC colonnes à droite
        Next j 'prochaine ligne de la boucle 2
    End If 'fin de la condition
Next I 'prochaine ligne de la boucle 1
End Sub


Le fichier :
http://www.cjoint.com/c/EFwwzsfxJgR
0
ryooutside86
23 juin 2015 à 11:19
Bonjour Thautheme, bonjour le forum,

Merci beaucoup Thautheme pour ta réactivité.

Je suis désolée de ne pas avoir choisi un exemple des plus probants....

Tu as bien fait de te regénérer un fichier source en supprimant les lignes masquées.

Pour ma part, je ne parviens pas à accèder à ton fichier joint. J'ai une page web illisible qui s'ouvre mais pas de fichier excel. Sais tu me dire pourquoi ?

Je te joins le fichier originel que tu aies la source véritable. J'espère que cela te facilitera la tâche... Tu noteras que la mise en forme est faite jusqu'à la ligne 645, il reste donc à traité de la ligne 646 à la ligne 2750 (2751 et 2752 ne nécessitant pas de traitement).

En espérant te donner toutes les infos requises.

Merci !!


A bientôt
0
PlacageGranby Messages postés 393 Date d'inscription mercredi 26 mars 2014 Statut Membre Dernière intervention 7 mars 2019 26
23 juin 2015 à 14:07
Bonjour,

J'ai le même problème avec cjoint depuis quelques temps. il ne propose pas non plus d'enregistrer le fichier par défaut. Un clic sur le lien ouvre le fichier excel avec un éditeur texte au lieu de excel, du coup, on voit seulement un langage machine incompréhensible.

La solution est de faire un bouton droit de souris sur le lien, et choisir :
"enregistrer la cible du lien"
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
23 juin 2015 à 11:47
Bonjour Ryooutside, bonjour le forum,

Désolé j'ai le même problème que toi pour le fichier. L'ennui est que je l'ai fait à la maison et là je suis au boulot. Je ne pourrai le remettre que ce soir...

Sinon, tu me dis que tu joins un fichier originel mais je ne le vois pas !...
0
ryooutside86
23 juin 2015 à 11:57
Avec mes excuses....
Voici le fichier :
http://www.cjoint.com/c/EFxjpBDWbww

A bientôt !!
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
Modifié par ThauTheme le 23/06/2015 à 14:44
Bonjour le fil, bonjour le forum,

La structure des données est complètement différente ! Dans ton premier fichier les séries de données étaient toujours décalées d'une ligne par rapport au Number et s'il y avait plusieurs séries elles étaient, elles aussi, décalées une ligne au-dessous. Là, ce n'est pas le cas. Il y a souvent 2 séries de données dans la même ligne.
La macro proposée ne peut pas fonctionner avec cette structure et j'avoue que j'hésite à me lancer dans une nouvelle usine à gaz sans être sûr de la structure définitive de ton fichier source.
  • Pourquoi il y a-t-il encore des ligne masquées ? Faudra-t-il toujours commencer à la ligne 35 ou bien est-ce aléatoire ?
  • Les lignes vides du premier fichier ont disparues. Cela signifie-t-il qu'il n'y en aura plus ?


Dans l'attente de tes réponses...




À plus,
ThauTheme
0
ryooutside86
23 juin 2015 à 15:48
Rebonjour,

Bon, je commence à percevoir le degré de subtilité de la chose....mes exemples ne sont pas satisfaisants, je vais vraiment tenter de présenter les choses de la manière la plus réaliste possible...

Concernant le fichier source :
- il faut intégrer ce fichier source dans la trame à utiliser du deuxième onglet
- les colonnes B, C et H ("Paid prior") sont à supprimer
- j'ai coloré en jaune le champ "Name" qui devra correspondre à la colonne 1 de la trame - les données "Name" doivent être copiées sur chaque ligne jusqu'au prochain changement de "name" et ainsi de suite
- les données "name" ont été modifiées pour préserver la confidentialité du fichier
- il y a bien un décalage des données pour une même ligne
- les lignes "debtor total" sont à supprimer
- il ne doit y avoir de lignes masquées
- les lignes vides au-dessus du corps du tableau seront toujours présentes
- Aucune ligne vide ne doit être conservée

Voici le lien du fichier à exploiter : http://www.cjoint.com/c/EFxnTB1Nugw

J'espère que ces éléments seront suffisamment exhaustif pour permettre de trouver la solution ultime...

Merci par avance de votre aide !!

A bientôt

PS : ne pas hésiter à me formuler vos questions, requêtes et autres remarques !!
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
23 juin 2015 à 16:23
Bonjour le fil, bonjour le forum,

Je regarde ça ce soir...
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
24 juin 2015 à 08:50
Bonjour le fil, bonjour le forum,

Attention ! Dans ton dernier exemple j'ai supprimé la ligne 4 de l'onglet Trame à utiliser. J'espère que ça ne pose pas de problème...
Dans le nettoyage de la source je demande au code de supprimer les 5 premières lignes (ligne 18 du code). Tu adapteras...

la macro fait :
- Copie de l'onglet Source
- suppression des lignes et colonnes inutiles
- Ajout d'une colonne au début des données
- revoie des données dans Trame à utiliser
- Suppression de la copie de l'onglet Source

Chez moi elle met environ 15 secondes sur l'exemple que tu as fourni...

Le code :

Sub Macro1()
Dim deb As Single 'déclare la variable deb (début du chronomètre)
Dim S As Worksheet 'déclare la variable S (onglet Source)
Dim T As Worksheet 'déclare la variable T (onglet Trame à Utiliser)
Dim DL As Long 'déclare la variable DL (Dernière Ligne)
Dim PL As Range 'déclare la variable PL (PLage)
Dim DEST As Range 'déclare la variable DEST (cellule de DESTination)
Dim LD As Long 'déclare la variable LD (Ligne de Début)
Dim LF As Long 'déclare la variable LF (Ligne de Fin)
Dim NL As Byte 'déclare la variable NL (Nombre de Lignes)
Dim fin As Single 'déclare la variable fin (fin du chronomètre)

deb = Timer 'lance le chronomètrage
Application.ScreenUpdating = False 'masque les rafraîchissements d'écran
Sheets("Source").Copy After:=Sheets("Source") 'fait une copie de l'onglet Source (cette copie sera supprimée à la fin de la macro)
Set S = Sheets("Source (2)") 'définit l'onglet S (la copie)
Set T = Sheets("Trame à utiliser") 'définit l'onglet T (à adapter)
S.Rows("1:5").Delete 'supprime les 5 premières lignes de l'onglet S (à adapter)
S.Range("B:B,C:C,H:H").Delete 'supprime les colonne B, C et H de l'onglet S
DL = S.Cells(Application.Rows.Count, 6).End(xlUp).End(xlUp).Row 'définit la dernière ligne contenant des données dans la colonne 6 (=F) de l'onglet S
S.Rows(DL + 1 & ":" & Application.Rows.Count).Delete 'supprime toutes les lignes en dessous de la dernière ligne DL
S.Columns(1).Insert 'insère un colonne avant les données
Set PL = S.UsedRange 'définit la plage PL
Set PL = PL.Offset(0, -1).Resize(PL.Rows.Count, PL.Columns.Count + 1) 'redéfinit la plage PL (en inclunant la 1ère colonne)

'*******************************
'suppression des lignes inutiles
'*******************************
For I = DL To 1 Step -1 'boucle inversée de la dernière ligne DL à la première
    'si le nombre de données contenues dans la ligne est nul, supprime la ligne et va à l'étiquette "suite"
    If Application.WorksheetFunction.CountA(PL.Rows(I)) = 0 Then S.Rows(I).Delete: GoTo suite
    'condition : si le nombre de données contenues dans la ligne est égal à un
    If Application.WorksheetFunction.CountA(PL.Rows(I)) = 1 Then
        S.Cells(I, 2).Copy Cells(I + 1, 1) 'coupe la valeur ligne I colonne 2 (=B) et la colle dans la ligne en dessous, colonne 1 (=A)
        S.Rows(I).Delete 'supprime la ligne
        GoTo suite 'va à l'étiquette "suite"
    End If 'fin de la condition
    'si la valeur en ligne I colonne 3 (=C) est égale à "Debtor Total", supprime la ligne
    If S.Cells(I, 3).Value = "Debtor Total" Then S.Rows(I).Delete
suite: 'étiquette
Next I 'prochaine ligne de la boucle
'*******************************

DL = S.Cells(Application.Rows.Count, 7).End(xlUp).Row 'redéfinit la dernière ligne éditée DL de la colonne 6 (=F) de l'onglet S
For I = 1 To DL 'boucle 1 : de 1 à DL
    Set DEST = T.Cells(Application.Rows.Count, 1).End(xlUp).Offset(1, 0) 'définit la cellule de destination DEST
    'définit la valeur de DEST (la valeur de la cellule ligne I, colonne 1 (=A) de l'onglet S si elle n'est pas vide
    'sinon, la valeur de la ligne au-dessus colonne 1 (=A) de l'onglet T
    DEST.Value = IIf(S.Cells(I, 1).Value <> "", S.Cells(I, 1).Value, DEST.Offset(-1, 0))
    LD = I 'définit la ligne de début LD
    LF = S.Cells(I, 2).End(xlDown).Row - 1 'définit la ligne de fin LF
    If LF > DL Then LF = DL 'si LF est supérieur à DL, alors LF devient DL (pour la dernière ligne)
    NL = LF - LD 'définit le nombre de lignes NL
    For J = 1 To NL 'boucle 2 : de 1 au nombre de ligne NL
        S.Cells(I, 2).Resize(1, 5).Copy DEST.Offset(0, 1) 'copie la première partie des données
        DC = J * 7 + (J - 2) 'définit le décalage DC
        'copie les données de la série les colle dans DEST décalée de DC colonnes à droite
        S.Cells(I + J, 7).Resize(1, 6).Copy DEST.Offset(0, DC)
    Next J 'prochaine ligne de la boucle 2
    I = I + NL 'redéfinit I
Next I 'prochaine ligne de la boucle 1
Application.DisplayAlerts = False 'masque les messages Excel
S.Delete 'supprime l'onglet S (la copie de l'onglet Source)
Application.DisplayAlerts = True 'affiche les messages Excel
Application.ScreenUpdating = True 'Affiche les rafraîchissements d'écran
fin = Timer - deb 'arrêtre le chronométrage
MsgBox "Données transférées en " & fin & " seconde !" 'message
End Sub


Le fichier zip (car sinon j'ai le même problème)
https://www.cjoint.com/c/EFygOBCSQlI

0
ryooutside86
24 juin 2015 à 11:18
Bonjour à tous,

Thauthème,

Un grand merci pour ton aide fructueuse !

La macro est concluante en 14 s. Quel bon travail !

Je serais curieuse de savoir combien de temps prend la codification d'une telle macro ?

Je suis en début de formation et je crois comprendre qu'il me reste beaucoup beaucoup de chemin à parcourir pour être ne mesure de générer moi-même ce type de macro...

Aurais tu des formations accélérées à préconiser ?

En tout cas ce fut un plaisir d'échanger avec toi

Encore merci Thautheme !

A bientôt
0
ThauTheme Messages postés 1442 Date d'inscription mardi 21 octobre 2014 Statut Membre Dernière intervention 29 juillet 2022 160
Modifié par ThauTheme le 24/06/2015 à 11:53
Bonjour le fil, bonjour le forum,

Royoutside, je ne peux malheureusement pas te conseiller de formation car je suis autodidacte et j'ai pratiquement tout appris dans un autre forum. Comme c'est pour moi une passion, je ne compte pas les heures. Avec le niveau que j'ai atteint au fil des ans, il m'a fallu 3 bonnes heures pour écrire le code que je t'ai proposé.
Ce code est loin d'être optimal mais je n'ai pas mieux a te proposer.

Je suis content que ça marche mais je te recommande de bien le tester avant de le considérer comme fiable à 100%...

[Édition]
Je viens de constater une erreur ligne 58 du code. Il faut remplacer :
S.Cells(I + J, 7).Resize(1, 6).Copy DEST.Offset(0, DC)

par :
S.Cells(I + J, 7).Resize(1, 8).Copy DEST.Offset(0, DC)


À plus,
ThauTheme
0