Copie sans écraser
Bonjour à tous,
Débutant autant qu'on peut l'être en macro je requière de l'aide auprès de vous.
Je souhaite créer une macro me permettant de copier une ligne en fonction d'une valeur de cellule dans une seconde feuille:
Feuille "Tableau", si la valeur de la colonne C est égale à "ok", déplacer vers feuille "Archives"
La copie et suppression marchent bien (en fait j'ai réussit à adapter à mon tableau ce que j'ai trouvé ci et la mais je n'ai aucune idée de la fonction de telle ou telle commande), par contre le problème est que chaque exécution de la macro vient écraser les lignes précédemment copier dans "Archives" au lieux d'ajouter à la suite.
Voilà le code:
Sub Archive()
Dim PlageUtile As Range
Dim Ligne As Range
Dim Origine As Worksheet
Dim Destination As Worksheet
Dim LigneDestination As Integer
Set Origine = Worksheets("Tableau")
Set Destination = Worksheets("Archives")
Set PlageUtile = Range(Origine.Cells(1, 1), Origine.Cells(1, 1).SpecialCells(xlLastCell))
LigneDestination = 1
For Each Ligne In PlageUtile.Rows
If Ligne.Cells(1, 3).Value = "ok" Then
Ligne.Copy Destination.Cells(LigneDestination, 1)
LigneDestination = LigneDestination + 1
Ligne.EntireRow.Delete
End If
Next
End Sub
J'imagine qu'il doit pas manquer grand chose mais je sèche complétement
Merci d'avance pour votre expertise!
Bonjour,
Si tu pouvais :
1) Eviter de sauter des lignes (ce qui fait scroller en permanence)
2) Indenter ton code
3) Le mettre sous balises Code dans le post
déjà, ça deviendrait lisible, sans trop d'effort.
Cordialement.
Voilà je pense que c'est mieux
Par contre je ne sais pas ce que veut dire "indenter".
Merci,
C'est beaucoup mieux !
Et si tu sais pas ce que veut dire "indenter", tu as pourtant indenté parfaitement dans les règles !
Ton code peut être amélioré (si tu le souhaites), mais commençons par le problème posé...
LigneDestination = Destination.Cells(Rows.Count, 1).End(xlUp).Row + 1
Cette modification te permettra de ne pas écraser ce qui précède.
Je conseille que ta feuille Archives soit doté d'une ligne d'en-tête au départ, c'est plus sûr, le résultat sera donc 2 la première fois, et ensuite cela prendra la ligne suivante...
Ca marche parfaitement
Merci pour la réponse (très très) rapide et chapeau pour l'efficacité!
Pourquoi pas améliorer le code, que proposes-tu?
Merci,
Bonjour,
Je reste très proche de ton code et opère juste quelques aménagements...
Travaillant uniquement sur le code, il convient de s'assurer que ce n'est pas en contradiction avec ta configuration.
Sub Archive()
Dim PlageUtile As Range, Ligne As Range, Destination As Worksheet
Dim LigneDestination As Integer, NbCol As Integer
Set Destination = Worksheets("Archives")
LigneDestination = Destination.Cells(Rows.Count, 1).End(xlUp).Row + 1
With Worksheets("Tableau")
Set PlageUtile = .Range(.Cells(1, 1), .Cells(1, 1).SpecialCells(xlCellTypeLastCell))
End With
NbCol = PlageUtile.Columns.Count
Application.ScreenUpdating = False
For Each Ligne In PlageUtile.Rows
If Ligne.Cells(1, 3).Value = "ok" Then
Destination.Cells(LigneDestination, 1).Resize(, NbCol).Value = Ligne.Value
LigneDestination = LigneDestination + 1
Ligne.Cells(1, 1).ClearContents
End If
Next Ligne
PlageUtile.Columns(1).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
1) Je garde tes noms de variables
Je supprime ta variable Origine, qui n'a guère d'utilité une fois définie PlageUtile... J'ajoute par contre une variable NbCol pour recueillir le nombre de colonnes de PlageUtile (voir plus loin utilisation).
2) Initialisation des variables : Destination, LigneDestination, PlageUtile et NbCol. Rien de différent...
3) Inhibition de la mise à jour de l'affichage (ScreenUpdating) : indispensable pour accélérer l'exécution du code, car tu opères des modifications se répercutant sur l'affichage.
4) Habituellement dans une configuration de ce type, opérant un transfert de données d'une feuille vers une autre, je mets la première sous bloc With et la seconde sous variable, ce qui apparaît à l'usage comme l'un des compromis les plus optimal.
Ici, j'ai voulu ton choix de définition préalable de la plage d'intervention, car il est aussi bon ! Et sa mise sous bloc With ne se justifiait pas dans la mesure où son utilisation dans une boucle For Each a un effet comparable de mise en mémoire par VBA.
En second lieu, je procède habituellement à une mise en tableau des lignes à transférer, pour éviter les opérations individuelles et ne faire qu'une affectation globale à la fin. Je ne l'ai pas fait ici car les conditions dans lesquelles monter le tableau ne me semblaient pas devoir apporter un gain indubitable... Ce serait éventuellement à tester sur un transfert d'une assez grande quantité de lignes pour pouvoir mesurer un effet qui deviendrait perceptible. (Note toutefois que l'utilisation de tableaux est l'un des principaux moyens pour rendre plus rapide l'exécution du code.)
Petite remarque à ce stade : pour quelqu'un qui se prétend débutant, je dois constater que tes choix ne sont pas spécifiquement des choix de débutant !
5) Petit changement notable : plus de copier-coller, on procède par affectation de valeurs du type PlageB.Value = PlageA.Value (les 2 plages étant de taille identique, et étant entendu que l'on n'a que des valeurs à transférer). D'où l'utilisation du nombre de colonnes pour dimensionner la plage de destination à la taille de la ligne source. Méthode à privilégier par rapport au copier-coller, dès lors qu'elle peut être appliquée, car plus rapide.
6) Autre changement : on ne supprime pas les lignes au fur et à mesure, on se contente d'effacer une cellule (en colonne A), opération plus légère, donc plus rapide, qui permettra la suppression globale des lignes à supprimer à la fin...
7) Suppression des lignes en utilisant SpecialCells sur la colonne on l'on a procéder à des effacements.
A tester après vérification...
Cordialement.
Bonjour,
J'ai testé ton code et tout marche parfaitement!
Pour le code que j'ai utilisé je l'ai tout simplement copier d'un post et adapté à mon fichier
Non pas que je n'aime pas les compliments mais je préfère les mériter ^^.
En tout cas merci bien pour ton expertise, je l’apprécie à ça juste valeur
Cdt,