Macro copier / coller ligne sur autre feuille selon condition

  • Auteur de la discussion cafiniou13
  • Date de début

cafiniou13

Habitué
Bonjour,

Je cherche à copier des lignes en respectant une condition et les coller dans une autre feuille.
J’ai eu beau lire et relire à travers les forums des solutions proposées, je suis tellement nulle en VBA, qu’il y a toujours quelque chose qui cloche quand j’essaye d’appliquer une solution à mon fichier.
Please HELP !!

Voici quelques infos sur le classeur concerné
La feuille source : Liste intégrale (disons LI)
La feuille où je souhaite copier les données : Renouvellement (disons RE)
Dans la feuille source j’ai 11 colonnes : Code / Langue / Raison sociale / Tél / Fax / Email / Date agrément / Année Renouvellement (disons iAR)/ Certification ISO / Validité ISO / Nouveau certificat
Je souhaite copier toutes les lignes dont l’année de renouvellement est 2007 (ou année en cours si possible, de façon à ne pas changer la macro chaque année) et les coller dans la feuille « Renouvellement » (en ligne 2 – la ligne 1 étant réservée aux titres)
Au départ mon tableau source est trié sur le critère raison sociale et je souhaite retrouver cet ordre après le copier / coller

Merci d’avance à ceux qui se pencheront sur le problème
 

zeb

Modérateur
Mais si on peut trouver ça sur ce forum.

Exemple :
En particulier cette réponse :

Il y a un certain nombre de choses à adapter, bien sûr.
 

cafiniou13

Habitué
Je me penche sur ce qui été fait et j'essaye de mettre en application.
Si j'ai des problèmes, je reviens vers toi, en espérant que cela ne t'ennui pas.
 

cafiniou13

Habitué
Je suis en train de faire le point sur les différentes réponses faites sur une question de copier dans le forum.
Peux-tu me dire ce que signifie
"Dim ligneH As Long
ligneH = 1"
en tête de code.
Ma question est très certainement simpliste, mais j'avoue débarquer dans le VBA et j'ai vraiment envie de comprendre ce que j'écris, pur pouvoir appliquer à d'autre cas le fait de copier ou extraire des données en fonction de conditions particulière.
Merci d'avance
 

zeb

Modérateur
Ta question est effectivement simple et digne d'un très grand débutant !
(C'est un état qui ne dure pas et par lequel nous sommes tous passés)

Cela ne m'ennuye pas de répondre aux gens de bonne volonté.
(Pour prouver ta bonne volonté, s'il en était besoin, utilise la balise
Code:
 pour présenter même deux lignes)

Avant de te répondre, j'aimerais que tu mettes ton curseur sur le mot [b]Dim[/b], que tu appuyes sur [F1] et que tu lises TOUT ce qui s'affiche ;)

A te lire.
 

cafiniou13

Habitué
Bon j'avoue ne pas tout avoir compris, mais j'ai découvert des choses intéressantes.
Désolée, mais je vais encore posée une question digne d'un grand débutant des forums (mais c'est aussi le cas) : je veux bien utiliser la balise
Code:
, mais comment tu fais ?
STP ne baisse pas les bras en lisant ce message, je suis sûre qu'une fois que je serai mise sur les rails je devrai y arriver.
Cela fait plusieurs jours que je lis les macros des autres pour essayer de comprendre l'esprit du VBA (uniquement dans le cadre de mon exemple, pour l'instant).
NB : j'ai d'ailleurs remarqué que tu répondais souvent et assidument aux débutants VBA
 

zeb

Modérateur
Voui, je réponds aux débutants, même les grands, en VB, en forum, et autres (Je suis bien obligé, je suis un des modos ;) )
Mais as-tu remarqué que je faisais trouver une solution avant de de donner la mienne ;) Tu vas subir le même sort [:nyghost]

Alors, pour la balise
Code:
, une visite au règlement t'aurait fait le plus grand bien :
[img]http://site.voila.fr/zulu-echo-bravo/img/balisecodeppc_ok.png[/img]


Alors, et ce résultat pour Dim ?
 

cafiniou13

Habitué
Bon j'avoue j'ai un peu honte, mais il faut bien un début à tout !!
Merci pour le code, en fait je viens de comprendre qu'en utilisant la réponse rapide on n'avait pas la barre d'outil pour le code ! Ha ! :pt1cable:

Pour la question sur le Dim, j'ai compris que cela servait à déclarer des données et nottament leur format (je ne sais pas si ma réponse est très claire?)
En fait ma question était plus sur quand utilise-t-on "As Long" et j'ai fait comme tu m'as dit! F1 cela marche bien ! Lol

Bon j'ai tout de même essayé d'avancé sur mon pb de copier coller, voici ce que j'ai écrit (tu reconnaitras ta pates, j'ai pioché dans d'autres réponses que tu as faites). Sauf que bien évidemment cela ne marche pas.
[cpp]
Private Sub CommandButton1_Click()
Dim iLI As Integer
Dim iRE As Integer
Dim LI As Worksheet
Dim RE As Worksheet

Set LI = Worksheets("Liste intégrale")
Set RE = Worksheets("Renouvellement")

iRE = 2

For iLI = 3 To 10000
If LI.Cells(iLI, 9).Text = "2007" Then
LI.Range("iLI:iLI").Copy RE.Range(iRE, 1).Paste
iRE = iRE + 1
End If
Next
Application.CutCopyMode = False
End Sub
[/cpp]

L'erreur est sur la ligne 14 :
"La méthode 'Range' de l'objet '_Worksheet' a échouée"
On est bien d'accord que lorsque dans la feuille Liste intégrale (LI) au niveau de la colonne 9, le texte 2007 apparait, je veux copier la ligne correspondante et la coller dans la feuille Renouvellement (RE). Et ceux pour toute les lignes du tableaux

Aller dis moi qu'il ne manque pas grand chose pour y arriver !
 

zeb

Modérateur
Et non. C'est plein d'erreurs ;)

Un numéro de ligne, sous Excel, va de 1 à 65536.
Un Integer, sous VBA, va de -32769 à 32768.
Donc un numéro de ligne n'est forcément pas un Integer.
Le type de données entier supérieur est Long.

Comment, tu n'utilises que la plage 3:10000 ? Qu'est-ce que ça peut me faire ? Tu vas revenir en me disant que ça ne marche pas si tu as un peu plus de données la prochaine fois !

Toutes les autres erreurs sont concentrées La ligne 14 !!!!!!

Cells prend en paramètre la ligne et la colonne sous forme d'entier et renvoie une plage de cellules d'une seule cellule.
Range prend en paramètre un ou deux ranges, ou une adresse sous forme de chaîne et renvoie une plage de plusieurs cellules.

Donc, RE.Range(iRE, 1) est faux. Il faut mettre Cells à la place.

Si iLi = 3, alors "iLI:iLI" = .... "iLI:iLI" ! :D :D
Pour avoir 3 si il y a 3 dans iLi, il faut utiliser iLi, pas "iLi".
Comment faire pour avoir "3:3" en partant de iLi = 3 ?
Comme ça :[fixed]iLi & ":" & iLi[/fixed]

Qu'est-ce que ce .Paste vient faire là ? Vire-moi ça de là. Et si tu veux savoir pourquoi, relis la doc ( [F1] ) sur Copy.

Perso, quand je donne un exemple sur ce site (je ne le fais pas dans mes macros ;) ) je l'écris comme ça pour fixer les idées :
[fixed]Range( <départ> ).Copy Destination:=<arrivée>[/fixed]même si la syntaxe suivante est juste[fixed]Range( <départ> ).Copy <arrivée>[/fixed]

Ultime erreur, ligne 19. Qu'est-ce que ce CutCopyMode fait là. Vire-moi ça de là.

C'est tout :)
 

cafiniou13

Habitué
Bonjour,

Désolée de ne pas t'avoir répondu hier , mais j'ai du partir précipitamment.
Je m'y suis donc remise ce soir et EUREKA :bounce: !!!!!!!! après avoir modifié tout ce que tu m'as dit cela fonctionne parfaitement. :pt1cable:
Je pense que tu peux t'attribuer la palme de la patience !!
En tous les cas GRAND MERCI à toi pour ton royal coup de main!!!!!
Je dois appliquer cette macro à d'autres fichiers un peu plus complexes (et c'est non plus du copier / coller que je dois faire, mais de l'extraction de données vers une autre feuille). Si j'ai un problème, j'espère que tu ne vois pas d'inconvénient à ce que je revienne vers toi.
Au plaisir de te retrouver sur le forum.... :hello:
 

cafiniou13

Habitué
Bonjour,

J'ai de nouveau besoin de votre lumière pour une macro assez proche du copier / coller décrit ci-dessus, sauf que c'est pour faire du couper / coller.
Je suis donc repartie de la macro précédente et j'ai remplacé copy par cut ce qui donne (nb les données ont aussi changées) :
[cpp]Private Sub CommandButton1_Click()
Dim iR As Long
Dim iAV As Long
Dim R As Worksheet
Dim AV As Worksheet

Set R = Worksheets("Revue")
Set AV = Worksheets("Actions validées")

iAV = 17

For iR = 17 To 65536
If R.Cells(iR, 6).Text = "V - Validé" Then
R.Range(iR & ":" & iR).Cut AV.Cells(iAV, 1)
iAV = iAV + 1
End If
Next
End Sub
[/cpp]

Jusque là tout marche parfaitement, mais je voudrai apporter 3 modif que je ne sais pas du tout comment intégrer :
- tout d'abord je souhaiterai que les lignes coupées de la feuille "Revue" (puis coller dans l'autre) soit supprimées, de façon à ne pas avoir de ligne vide dans la feuille "Revue". J'ai essayer d'insérer "Delete Shift:=xlUp" entre les lignes 14 et 15, mais visiblement c'est pas bon!
- ensuite il faudrait non plus que je colle systématique à partir de la ligne 17 de la feuille "Actions validées", mais à partir de la première ligne vide, après la ligne 16 (les lignes de 1 à 16 étant utilisé pour faire un en-tête de page où certaines lignes sont vides)
- dernier point, celui qui à mes yeux me paraît le plus compliquer, je souhaiterai écrire la date de l'action couper / coller sur chaque ligne concernée dans la colonne 5 (sur une des 2 feuilles ou sur les 2, selon ce qui est le plus simple). Pour ce point j'avais essayé avec la formule : MAINTENANT(), mais la date se remet à jour à chaque fois que je lance la macro, alors que je veux conserver la date de l'action.

J'espère que mes explications sont suffisamment claires.
Merci d'avance à ceux qui plancheront sur mon cas.
 

zeb

Modérateur
Ton idée de "Delete Shift:=xlUp" (Message pour KangOl: Moi aussi je veux une balise [ CODE ] inline :cry: ) est excellente !

Il faut juste se demander sur quoi faire cette suppression :
■ Sur la cellule ? -> R.Delete ...
■ Sur la ligne ? -> R.Range(iR & ":" & iR).Delete ...


Quant aux lignes vides, cf


MAINTENANT, essaie ce petit bout de programme là :
Code:
Sub SuperMacroVachementInteressante
    MsgBox Now
End Sub
 

cafiniou13

Habitué
- Pour la supression des lignes tout va bien, sauf que, si 2 lignes successives ont la mention "validée" dans la colonne 6, seule la 1ère ligne et extraite de la feuille source puis coller dans la feuille "actions validées"

- Pour atteindre la 1ère ligne vide de la feuille destinatrice, j'ai du faire un meli-melo car au lieu de coller dans la première ligne vide, la macro regarde quelle est la première ligne vide de la feuille source (par exemple ligne 25) et colle dans la feuille destinatrice à la ligne 25 alors que la 1ère ligne vide est par ex. la 20.

Voici le nouveau code

[cpp]Private Sub CommandButton1_Click()
Dim iPR As Long
Dim iAV As Long
Dim PR As Worksheet
Dim AV As Worksheet

Set PR = Worksheets("Préparation prochaine REVUE")
Set AV = Worksheets("Actions validées")

iAV = Range("A16").End(xlDown).Row + 1

For iPR = 17 To 65536
If PR.Cells(iPR, 6).Text = "V - Validé" Then
PR.Range(iPR & ":" & iPR).Cut AV.Cells(iAV, 1)
PR.Range(iPR & ":" & iPR).Delete Shift:=xlUp
iAV = iAV + 1
End If
Next
End Sub
[/cpp]

Pour le dernier point cité, la macro que tu me proposes me donne la date et heure à laquelle je lance la macro, mais ne me permet pas la saisie automatique (colonne 5) de la date sur chaque ligne qui a été basculée dans la feuille destinatrice.
 

zeb

Modérateur
- Pour la supression des lignes tout va bien, sauf que, si 2 lignes successives ont la mention "validée" dans la colonne 6, seule la 1ère ligne et extraite de la feuille source puis coller dans la feuille "actions validées"
Rhooo, je suis désolé. J'ai honte de moi :( L'explication et la soluce au même endroit que tout à l'heure :


Pour ton méli-mélo, c'est exactement ce qu'il faut faire. Bravo. (C'est ça, programmer ;) ) Je suis fier de toi. Peut-être que préciser la feuille (AV.Range...) serait judicieux, ligne 10 ;)


Pour mettre une valeur dans une case, alors là, j'ai honte pour toi !!!! Tu ne sais pas mettre la valeur de New dans la case iAV x 5 ?
 

zeb

Modérateur
Pour ta suppresion, je te propose quelque chose d'autre. Remonter "à l'envers" comme dans le tuto est possible, mais pas très judicieux dans ton cas. Je te propose plutôt de marquer les lignes à supprimer puis de faire une seconde passe pour nettoyer :

Code:
const A_SUPPRIMER = "D - A SUPPRIMER"

Application.ScreenUpdating = False
' // Copie

For iPR = 17 To 65536
    If PR.Cells(iPR, 6).Text = "V - Validé" Then
        PR.Range(iPR & ":" & iPR).Copy AV.Cells(iAV, 1)
        PR.Cells(iPR, 6).Value = A_SUPPRIMER
        PR.Cells(iPR, 6).Interior.ColorIndex = 3
    	PR.Cells(iPR, 6).Font.ColorIndex = 6
        AV.Cells(iAV, 6).Value = "Validé le " & Date
        iAV = iAV + 1
        Application.StatusBar = "Copie: " & (iPR - 17) * 100 \ (65536 - 17) & "%"
    End If
Next

' // Admirer le travail :)
Application.ScreenUpdating = True
PR.Select
Do While True
    If MsgBox("Alors, c'est biau ?", vbYesNo) = VbYes Then Exit Do
Loop 
Application.ScreenUpdating = False

' // Nettoyage - A l'envers :)
For iPR = 65536 To 17 Step - 1
    If PR.Cells(iPR, 6).Text = A_SUPPRIMER Then
        PR.Range(iPR & ":" & iPR).Delete Shift:=xlUp        
        Application.StatusBar = "Copie: " & (65536 - iPR + 17) * 100 \ (65536 - 17) & "%"
    End If
Next
Application.StatusBar = False
Application.ScreenUpdating = True
 

cafiniou13

Habitué
Pour mettre une valeur dans une case, alors là, j'ai honte pour toi !!!! Tu ne sais pas mettre la valeur de New dans la case iAV x 5 ?

J'ai effectivement honte, mais je ne sais pas faire et je sais encore moins ce qu'est la valeur New. Mais rappelle toi, je débutante VBA

Cela dit est-ce que ma question de départ était clair ou faut-il que je donne un ex. pour que tu puisses m'aider ?
 

zeb

Modérateur
Le code à suivre est maintenant disponible. :) (Tu pourrais attendre que je finisse avant de fondre en larmes en te martellant la poitrine en criant "je suis débutante" :cry: )

Alors, lignes 3, 14, 19, 24, 30, 34, j'utilise deux fonctions que je te demande d'aller voir dans l'aide. C'est juste pour faire beau, et ça ne sert à rien, c'est donc indispensable :)

La valeur de New c'est la valeur que renvoie New. Pour la connaître, faire MsgBox New :o (C'est pratique, c'est ce que tu cherches à faire.)

Pour info, la valeur de la case iAV x 5 de la feuille AV s'écrit AV.Cells(iAV, 5).Value avec tes variables correctement positionnées. Il n'y a plus qu'à y mettre New dedans !!!!!!!

Les lignes 18 à 24 sont évidemment inutiles.
Pour le reste, essaie de bien tout comprendre.
 

cafiniou13

Habitué
Désolée, j'ai répondu trop vite la fois précédente.
Bon je viens d'intégrer le code que tu m'as transmis, mais j'ai une erreur d'exécution '1004' à ligne 9 de ton code.
Est-ce que cela pourrait être du au fait que dans les cellules de la colonne 6 il y a une liste déroulante (crée à partir de Données / Validation / Liste)
Cela dit j'ai essayé de changer de n° de colonne (la 7 étant vide) ou de rajouter "A_SUPPRIMER" dans la liste déroulante, j'ai toujours le même message d'erreur.
As-tu une idée du type de problème ?
 

Freeman23

Expert
Par hasard tu n'aurais pas vérouiller la feuille ?

Sinon tu peux essayer de supprimer le .text et retesté.
Essaie aussi de mettre la ligne 9 en commentaire voir si la ligne 10 passe.

Sinon pour l'histoire de la date c'est bien la fonction now qu'il faut utiliser mais tu ne dois ajouter dans une cellule que si celle ci est vide.

Il faut bien voir que mettre =maintenant() dans une cellule affecte une fonction qui est calculé à chaque ouverture/rafraichissement. Alors que mettre le résultat de now ( ou maintenant) renseigne le résultat qui sera fixe dans le temps.

Code:
if cells(i,j) = "" then 
   cells(i,j) = now 'affecte la date actu à la cellule
end if
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 126
Messages
6 717 807
Membres
1 586 365
Dernier membre
matiOs1
Partager cette page
Haut