Se connecter avec
S'enregistrer | Connectez-vous

Copier ligne si une cellule dans celle-ci est non-nulle, entre deux feuilles de calcul - macro

Dernière réponse : dans Programmation
Partagez

Bonjour à tous,

Premièrement, je tiens à préciser que je n'ai aucune formation autre qu'un peu d'essai erreur sur vba...

Mon but est de réussir à isoler rapidement les lignes qui contiennent des éléments et de copier celles-ci sur une autre feuille de calcul. Dans mon classeur, je peux savoir directement si la ligne est vide en ne regardant que les valeurs de la colonne H. Si H est nulle (en fait elle vaut "", donc 0), alors la ligne est vide et elle n'est pas à copier. Mon code, ci-bas, fonctionne, mais il est beaucoup trop lent... J'aimerais donc bien que vous m'aidiez à l'optimiser.

À noter que copier seulement les colonnes A à M selon la valeur de la colonne H pourrait suffire.

  1. Sub Bouton1_Clic()
  2.  
  3. Dim Lig As Long
  4. Dim Col As String
  5. Dim NbrLig As Long
  6. Dim NumLig As Long
  7.  
  8. Sheets("COPIER ICI LES CELLULES NONVIDE").Activate ' feuille de destination
  9.  
  10. Col = "H" ' colonne de la donnée non vide à tester
  11. NumLig = 2
  12. With Sheets("Produit à copier") ' feuille source
  13. NbrLig = .Cells(65536, Col).End(xlUp).Row
  14. For Lig = 3 To NbrLig
  15. If .Cells(Lig, Col).Value <> "" Then
  16. .Cells(Lig, Col).EntireRow.Copy
  17. NumLig = NumLig + 1
  18. Cells(NumLig, 1).Select
  19. ActiveSheet.Paste
  20. End If
  21. Next
  22. End With
  23.  
  24. End Sub


Merci beaucoup de l'aide apportée!

Bon y a pas de solution miracle, tu est déjà sur la bonne voie.

qq point pour accélerer:

1) évite le presse papier (en plus éthiquement c'est mieux) (en faisant "gnagna. copy target" ça copie sans utiliser le presse papier)
2) Coupe l'update de l'écran au début de ta procedure (application.screenupdating = false) puis après la boucle, réactive le.
3) si tu as peu de ligne vide une bonne solution serait de copier l'ensemble de la feuille(c'est instantanée), puis de supprimer les lignes après la copie (ça c'est lent, comme la copie d'une seule ligne).

Voila si tu as plus de question, aucun souci.

Edit: un exemple de ce que ça peut donner:

  1. Dim Lig As Long
  2. Dim Col As String
  3. Dim NbrLig As Long
  4. Dim NumLig As Long
  5. Dim target As Range
  6.  
  7. 'Sheets("COPIER ICI LES CELLULES NONVIDE").Activate ' feuille de destination
  8. Application.ScreenUpdating = False
  9. Col = "H" ' colonne de la donnée non vide à tester
  10. NumLig = 2
  11. Set target = Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(2, 1)
  12. With Sheets("Produit à copier") ' feuille source
  13. NbrLig = .Cells(65536, Col).End(xlUp).Row
  14. .Range("A3:M" & NbrLig).Copy target
  15. NbrLig = Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(65536, Col).End(xlUp).Row
  16. For Lig = NbrLig To 2 Step -1
  17.  
  18. If Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(Lig, Col).Value = "" Then
  19. Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(Lig, Col).EntireRow.Delete
  20. End If
  21. Next
  22. Application.ScreenUpdating = True
  23. End With
  • drul a édité ce message

Ton probleme me perturbait, alors, j'ai un peu chercher,

La meilleure solution est de passer par une mémoire tampon et d'écrire toutes les données d'un coup !

  1. Sub Bouton1_Clic()
  2.  
  3. Dim Lig As Long
  4. Dim Col As String
  5. Dim NbrLig As Long
  6. Dim NumLig As Long
  7. Dim target As Range
  8. Dim testbuffer As Variant
  9. Dim j As Long
  10.  
  11. Col = "H" ' colonne de la donnée non vide à tester
  12. NumLig = 0
  13. Set target = Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(2, 1)
  14. With Sheets("Produit à copier") ' feuille source
  15. NbrLig = .Cells(65536, Col).End(xlUp).Row
  16.  
  17. ReDim testbuffer(NbrLig, 13)
  18.  
  19. For Lig = 3 To NbrLig
  20.  
  21. If .Cells(Lig, Col).Value <> "" Then
  22. For j = 1 To 13
  23. testbuffer(NumLig, j - 1) = .Cells(Lig, j).Value
  24. Next
  25. NumLig = NumLig + 1
  26. End If
  27. Next
  28. Sheets("COPIER ICI LES CELLULES NONVIDE").Range("A2:M" & NumLig).Value = testbuffer
  29. End With
  30. End Sub


P.S. il y surement moyen d'optimiser un peu ... (on peut surement copier toute la ligne d'un coup dans le buffer sans faire une deuxième boucle, mais j'ai plus le temps de chercher).

drul a dit :
Ton probleme me perturbait, alors, j'ai un peu chercher,

La meilleure solution est de passer par une mémoire tampon et d'écrire toutes les données d'un coup !

  1. Sub Bouton1_Clic()
  2.  
  3. Dim Lig As Long
  4. Dim Col As String
  5. Dim NbrLig As Long
  6. Dim NumLig As Long
  7. Dim target As Range
  8. Dim testbuffer As Variant
  9. Dim j As Long
  10.  
  11. Col = "H" ' colonne de la donnée non vide à tester
  12. NumLig = 0
  13. Set target = Sheets("COPIER ICI LES CELLULES NONVIDE").Cells(2, 1)
  14. With Sheets("Produit à copier") ' feuille source
  15. NbrLig = .Cells(65536, Col).End(xlUp).Row
  16.  
  17. ReDim testbuffer(NbrLig, 13)
  18.  
  19. For Lig = 3 To NbrLig
  20.  
  21. If .Cells(Lig, Col).Value <> "" Then
  22. For j = 1 To 13
  23. testbuffer(NumLig, j - 1) = .Cells(Lig, j).Value
  24. Next
  25. NumLig = NumLig + 1
  26. End If
  27. Next
  28. Sheets("COPIER ICI LES CELLULES NONVIDE").Range("A2:M" & NumLig).Value = testbuffer
  29. End With
  30. End Sub


P.S. il y surement moyen d'optimiser un peu ... (on peut surement copier toute la ligne d'un coup dans le buffer sans faire une deuxième boucle, mais j'ai plus le temps de chercher).


Ces codes sont effectivement beaucoup plus rapide que les miens! (le mien copiait 2 lignes à la seconde et j'ai 10000 lignes) Avec ceux-ci, j'obtiens le résultat en 5-6 secondes. Le dernier est effectivement un peu plus rapide que le premier.

Après quelques tests, j'ai remarqué par contre un petit problème. La commande copie toutes les lignes requises, sauf la première et la dernière ligne...

Pourrais-tu m'aider là-dessus s'il te plait?

Outre cela, superbe réponse, merci!
Contenus similaires

Pour faire apparaître la première ligne, je n'ai eu qu'à changer à la ligne 19 le 3 pour un 2.

19. For Lig = 2 To NbrLig

Reste à trouver pour faire apparaître la dernière ligne...

en ligne 28 essaye de mettre "numlig + 1"

Edit le deuxième code a surtout l'avantage d'être constant en vitesse. Avec le premier, si beaucoup de ligne sont vide, ils deviendra très lent.
  • drul a édité ce message

drul a dit :
en ligne 28 essaye de mettre "numlig + 1"

Edit le deuxième code a surtout l'avantage d'être constant en vitesse. Avec le premier, si beaucoup de ligne sont vide, ils deviendra très lent.


Voilà, le document fonctionne parfaitement!

Merci beaucoup!

Damn, faut qu'un modo la rajoute, mais je crains que zeb ou un autre modo ne soit pas la ces temps ... (en fait ça fait un bail que je n'ai pas vu d'autre modo que zeb par ici).

Si jamais c'est à la création du topic que peut choisir si tu veux ou non attribuer des points ...
Posez votre question