Copier si condition remplie et boucle Do while en VBA

Bonjour à tous et toutes,

Voilà je suis débutant en vba et je n'arrive pas à faire une macro pour recopier certaines cellules d'un fichier à un autre.

Pour expliquer simplement, je voudrais copier la cellule A2 de la feuille "compil" du premier fichier dans la colonne C de la feuille "Actions BO" du second fichier, dernière cellule vide si dans la colonne D j'ai du texte sur la même ligne.

Ensuite je voudrais faire une boucle do while pour copier la cellule A2 tant que j'ai du texte sur la ligne suivante en colonne D.

Evidemment, la boucle s'arrête si ce n'est pas le cas.

Bon j'espère avoir été clair dans ma question et je vous remercie par avance pour votre aide, moi cela fait un moment que je tourne autour du sujet et rien à faire je ne trouve pas !

Merci bien à ceux qui prendront le temps de me répondre.

Bonne journée

YOGHI

Bonjour,

Je crains que non !

Un mic-mac pas très clair entre C et D... et "dernière cellule vide", ce sera probablement celle qui porte le numéro 1048576 !

On dit boucle Do... Loop [While est une option dans cette boucle] [ça on pouvait rectifier d'office ! ]

On copie la cellule A2 tant qu'il y a du texte... en D3 ! si personne enlève le texte (et on voit pas comment, une fois démarré), on va copier inlassablement, et on verra rien, puisqu'on ne met rien nulle part.................. Il faut souhaiter pas de texte pour éviter de démarrer. Il n'est pas précisé où est A2, donc on a une chance.

Et sans fichier pour illustrer, on a le temps d'attendre.

Cordialement.

Bonjour M Ferrand,

C'est sarcastique comme réponse mais au moins je vais pouvoir préciser certaines choses :

Je dois copier une date "A2'" dans la colonne C voir fichier image ci-dessous

fichier exemple

quand la colonne D est non vide et quand la colonne C est vide,

Ensuite refaire cette copie tant que la colonne D contient du texte.

Les 2 problèmes que je rencontre sont la recherche de la dernière cellule vide en colonne C pour lancer le test de la colonne D non vide et ensuite comment imbriquer ma boucle do while dans la première.

En fait je n'ai pas la syntaxe et la coordination logique des 2 procédures !

Je me doute que vous trouvais ça ridicule et votre aide me serait bien utile

Encore merci

YOGHI

Bonjour,

D'abord, le terme "copier" est inadéquat (il est d'ailleurs inadéquat dans au moins la moitié des cas où on l'emploie). C'est le plus souvent sans grande conséquence, mais il est bon de le savoir. Copier implique qu'ensuite il faille coller, car copier consiste à transférer ce qu'on copie dans le presse-papier de Windows et on colle ensuite le contenu de ce presse-papier. En ce qui concerne une plage donc, si l'on peut éviter de transiter par le presse-papier, on gagnera du temps et VBA le permet.

Quelle que soit la solution utilisée dans ton cas (affecter la valeur d'une cellule à d'autres), il apparaît donc inutile de copier.

1re question : déterminer quelle est la dernière cellule utilisée dans une colonne (ou la première non utilisée) : la méthode la plus utilisée pour cela, et utilisable dès lors que le reste de la colonne est vide, est la propriété Range.End(xlUp)...

With Worksheets("x")
    i = .Range("C" & .Rows.Count).End(xlUp).Row

[NB- Il faut toujours qualifier ses expressions, si l'on veut que son code soit précis et ne risque aucune dérive selon le contexte d'exécution : une plage appartient toujours à une seule feuille, le préciser dès le départ plutôt que laisser VBA chercher quelle feuille ! On est sûr qu'il la trouvera toujours, et on gagne de toute façon le temps qu'il aurait mis à la déterminer.]

Ci-dessus, on obtient donc dans la variable i [ne pas omettre de déclarer ses variables...] le numéro de la dernière ligne utilisée en C.

Pour obtenir celui de la suivante (première vide), il suffisait de faire +1 ! On ne le fait pas parce qu'on est subtil !!

A ce stade, 2 méthodes pour poursuivre : celle que tu préconises, soit servir cellule par cellule en vérifiant la condition. Utilisation d'une boucle : on peut faire avec divers types de boucles, mais en effet la boucle Do... Loop est la mieux adaptée dans ce cas.

[J'insiste sur Do... Loop ! Car cette boucle admet 5 options de définition des conditions de sortie : While appliquée à Do ou à Loop (en début ou fin de boucle) et Until pareillement appliquée à Do ou Loop, ce qui fait 4 ; la 5e c'est sans condition de sortie : c'est à dire que l'on ne peut alors en sortir que par une instruction Exit Do à l'intérieur de la boucle.]

Dans ton cas, si dès la ligne i+1 la condition n'est pas remplie, il faut interrompre, donc test en début de boucle. On poursuit donc ainsi :

    Do While .Range("D" & i + 1) <> ""
        i = i + 1
        .Range("C" & i) = .Range("A2")
    Loop
End With

Si à la ligne suivante D contient une valeur, on incrémente i (n° de ligne), et on affecte la valeur de A2 en C sur cette ligne. La boucle s'arrête automatiquement quand la condition n'est plus remplie.

Mais on peut faire mieux !

De la même façon qu'on a déterminé la dernière ligne utilisée en C, on peut le faire en D. La différence entre ces deux numéros de lignes définit le nombre de cellules qu'on a à servir avec A2. Et au lieu d'affecter cellule par cellule on peut faire une affectation globale à la plage ainsi délimitée :

    n = .Range("D" & .Rows.Count).End(xlUp).Row - i
    If n > 0 Then .Range("C" & i + 1).Resize(n).Value = .Range("A2")
End With

On teste alors bien sûr que n ne soit pas nul, ce qui déclencherait alors une erreur puisque aucune affectation à faire dans ce cas.

Nb- Les gains sur une opération ne sont en général pas sensibles (quelques millisecondes tout au plus), ils le deviennent éventuellement par la répétition, mais il convient autant que possible de ne jamais les négliger, l'ensemble du programme n'en fonctionnera que mieux...

Te reste plus qu'à insérer tes codes IATA en B !

Cordialement.

Bonjour Mferrand,

Un grand grand merci pour vos explications, j'ai donc tout compilé dans le code ci dessous :

Sub copiedate  ()
Dim i as Integer
With Workbooks  ("Tracker BO.xlsm").Worksheets ("Actions BO")

          i=.Range ("C" &.Rows.Count).End (xlUp).Row
          Do While .Range ("D" & i+1) <> ""
                 i=i+1
                 .Range ("C" & i)= .Range (Workbooks ("Check-list BO en cours.xlsm").Worksheets ("Export").Range("A2"))
           Loop
End With
End Sub

Bon, le problème c'est que je ne voie rien se recopier dans la colonne C, j'imagine que j'oublie quelque chose dans mon code ou que ma syntaxe n'est pas la bonne. J'ai aussi essayé de remplacer le do while par un do until avec .Range ("D" & i+1) ="" en condition.

Bref, peut être que le fait de recopier une cellule d'un autre classeur pose problème, pourtant j'ai bien fait attention que le classeur soit ouvert en même temps.

Sinon il n'y a pas d'erreur de compilation du code, et pour le coup je ne voie vraiment pas quoi changer ?

Si vous avez un conseil ou une idée pour remédier à mon soucis je serais ravi, merci par avance

Cordialement,

YOGHI

Ceci :

.Range (Workbooks ("Check-list BO en cours.xlsm").Worksheets ("Export").Range("A2"))

est une énomité !

Mais commence par me dire où tu as copié le code collé dans le post ! L'aspect n'est pas conforme à celui qu'il a dans un module.

Et si la valeur à affecter provient d'un autre classeur, tu as sans doute intérêt à la recueillir dans une variable, et utiliser la varaible lors de l'affectation. Cela simplifie l'écriture...

Mferrand,

Je vais détailler toutes les lignes de mon code pour essayer de répondre à votre question

Sub copiedate  ()
Dim i as Integer  'je définie i comme étant un nombre entier'
With Workbooks  ("Tracker BO.xlsm").Worksheets ("Actions BO") 'je spécifie le classeur et la feuille concernée par l'action à venir'

          i=.Range ("C" &.Rows.Count).End (xlUp).Row 'position du curseur dans la dernière ligne non vide de la colonne C'
          Do While .Range ("D" & i+1) <> ""  'fonction faire tant que colonne D et ligne +1 sont différents de vide'
                 i=i+1     ' incrément de la boucle '
                 .Range ("C" & i)= .Range (Workbooks ("Check-list BO en cours.xlsm").Worksheets ("Export").Range("A2")) 'je recopie la cellule A2 de mon autre classeur tant que la condition est vraie'
           Loop 'clôture de la boucle '
End With 'clôture with'
End Sub

On peut dire que j'ai aménagé le

With Worksheets("x") 
i = .Range ("C".Rows.Count).End (xlUp).Row

Pour le faire coller à ma feuille Excel, à savoir Worksheets ("Actions BO") et en plus je rajoute le Workbooks. Bref j'ai supposé que le x était le paramètre adaptable.

Ensuite, comme le A2 à recopier en colonne C n'est pas sur la même feuille, j'ai pensé spécifier l'emplacement exact avec Workbooks.Worksheets.Range or je ne suis pas vraiment sur de moi sur ce coup, peut être devrais-je écrire workbooks ("x").worksheets ("1").cells(2, 1).value ; j'avoue ne pas savoir ! Sinon je le transforme en variable (As Range).

Cordialement

x représentait un nom de feuille que j'ignorais...

Mais j'ai posé une première question, à laquelle tu ne réponds pas !

Observe le code ci-dessous :

Sub copiedate()
    With Workbooks("Tracker BO.xlsm").Worksheets("Action BO")
        i = .Range("C" & .Rows.Count).....

Hormis que le mien est indenté et non le tien (ce que je t'encourage plus que vivement à faire en permanence...), ces 3 lignes, collées à partir d'une copie dans un module, devraient être strictement identiques aux tiennes, or cela diffère par les espacements, qui sont justement régulés par VBA...

Je redemande donc : d'où provient le code collé dans ton post ?

Oui, je crois comprendre ce que vous me demandez,

En fait j'écris le code dans les commentaires avec une tablette, il se peut que des espaces soient insérés quand je valide une expression ou même quand j'écris. Je ne fais pas de copie coller de mon pc vers le site excel-pratique, je recopie tout à la main en fait !

Du coup quand j'ai écrit l'expression de i j'ai sûrement mis des espaces alors qu'il n'y en a pas, désolé !

Ensuite sur Excel effectivement, il n'y a pas ce problème.

Cordialement

La macro est dans Tracker... à ce que j'ai compris. Dans ce cas :

Sub copiedate()
    Dim i%, d As Range
    Set d = Workbooks("Check-list BO en cours.xlsm").Worksheets("Export").Range("A2")
    With ThisWorkbook.Worksheets("Actions BO")
        i = .Range("C" & .Rows.Count).End(xlUp).Row
        Do While .Range("D" & i + 1) <> ""
            i = i + 1
            .Range("C" & i) = d.Value
        Loop
    End With
End Sub

Mais même si tu ne choisis pas la solution la plus efficace, cela ne te dispense pas d'indenter ton code.

Merci beaucoup Mferrand, la macro marche à la perfection

Cordialement

Rechercher des sujets similaires à "copier condition remplie boucle while vba"