code de copie

moilolo0404

Expert
#1
bonjour le forum,
je cherche comment on peu faire pour copier une ligne sur deux d'un tableau vers un autre tableau les une en dessous des autres ,quand j'essaie de le faire avec l'enregistreur de macro çà plante !
[B4:J1012 copier sur L4:T506 ] copie juste des valeur
merci de votre aide éventuel
 

magellan

Modérâleur
Staff
#2
bonjour le forum,
je cherche comment on peu faire pour copier une ligne sur deux d'un tableau vers un autre tableau les une en dessous des autres ,quand j'essaie de le faire avec l'enregistreur de macro çà plante !
[B4:J1012 copier sur L4:T506 ] copie juste des valeur
merci de votre aide éventuel
Bonjour,

cela va se jouer sur le numéro de ligne pair/impair je pense. Dans l'esprit ce sera une conditionnelle.
Code:
Sub test()
Sheets("Feuil1").Select
Dim cellule As Range
Dim i As Double
Dim j As Double
i = 0
For Each cellule In Range("A:A")

i = i + 1
If i Mod (2) = 0 Then
    j = j + 1
    Dim source As String
    Dim dest As String
    source = "A" + CStr(i)
    dest = "A" + CStr(j)
'Worksheets("Feuil2").Range("A"+CStr(i)).Value = Worksheets("Feuil1").Range("A"CStr(i)).Value
    Worksheets("Feuil2").Range(dest).Value = Worksheets("Feuil1").Range(source).Value
End If

Next cellule

End Sub
C'est bourrin et à l'arrache... cela mériterait d'être affiné.

Là pour info:
mod(2) -> uniquement les cellules paires
Source -> colonne plus '"numéro" de ligne
Dest -> colonne plus '"numéro" de ligne
"Feuil2" onglet destination
"Feuil1" onglet source.
 

moilolo0404

Expert
#3
bonjour ,
merci pour le code mes je n'y connais que peu de chose en codage et ce que je demander concerne une même feuille
merci pour votre aide
 

svoglimacci

check memory failed but no bug detected
#4
Salut :)
J'ai plus de temps que @magellan, je te dis ce que je trouve.
 

svoglimacci

check memory failed but no bug detected
#5
Voilà le code complet, commenté, à adapter bien entendu. J'espère que je ne me suis pas trompé (je débute toujours en VBA Excel tellement j'oublie tout à chaque fois).

Normalement on ne fait pas cela, on aide les gens à avancer d'eux même, c'est préférable pour des macros à venir mais là je ne pourrai pas forcément aider pas à pas.

Par contre, quelques conseils sur comment tu aurais du procéder (et je te promets, c'est comme cela que j'ai fait) :
- On enregistre des macros pour savoir comment faire.
- Mais on enregistre des choses simples. Par exemple, faire une sélection, la copier, la coller ailleurs. On s'arrête là et on va regarder pour comprendre comment Excel a fait cela.
- On procède pas à pas en fabricant son code. On se sert beaucoup de MsgBox qui affiche des infos (ou on se met en mode debug/breakpoints). Par exemple, on construit sa boucle en affichant dedans la valeur de i pour voir si elle avance. Sauf bien entendu si on maîtrise bien cela.
- On n'hésite pas à rechercher sur le net puis demander (ici ou ailleurs) les trucs qu'on n'obtiendra pas par une macro enregistrée comme "comment connaitre la dernière ligne d'une feuille" ou "Faire une boucle".

Si ça ne fonctionne pas où si tu as des questions, n'hésite pas.
Wala :)

Code:
Sub Macro1() ' Nom de la macro, mets ce que tu veux.
   
Dim i As Double ' i va parcourir la première plage
Dim j As Double ' j va parcourir la deuxième plage
Dim fin As Double ' fin est la dernière ligne de la première plage

Sheets("Feuil1").Select  ' On se positionne sur "feuille1", à toi d'adapter

i = 1 ' On va faire les lignes impaires. Pour avoir les lignes paires, mettre i = 2
j = 1 ' Normal, on va commencer à remplir la plage 2 à la ligne 1
fin = Range("A" & Rows.Count).End(xlUp).Row ' On trouve le numéro de la dernière ligne qui j'espère devrait être la dernière ligne de toute la page.
While (i <= fin) ' on boucle
    ' On sélectionne la partie qu'il nous faut. Moi je fais Ai:Ci, à toi d'adapter
    Range("A" + CStr(i) + ":" + "C" + CStr(i)).Select
    Selection.Copy ' On copie
    'On se positionne sur la première cellule de la ligne voulue de la plage 2. Je démarre de Ej, à toi d'adapter
    Range("E" + CStr(j)).Select
    ActiveSheet.Paste ' On colle
    i = i + 2 ' i avance de 2 en 2, normal, une ligne sur deux
    j = j + 1 ' j avance de 1 en 1, normal.
Wend ' Fin de boucle.

' On vire le cadre clignottant qui entoure la dernière sélection.
' Je ne sais pas pour les autres mais j'ai ça sur Excel 2007
Application.CutCopyMode = False

End Sub
 

moilolo0404

Expert
#6
bonjour,
merci pour le coup de pouce je vais regarder cela ,j'avait fait ça qui me reproduit le premiers tableau et me ralentie mon pc
merci de bien vouloir essayer de m'aider

Code:
Sub trie()
'

'

Sheets("trie").Select
Dim cellule As Range
Dim i As Double
Dim j As Double
i = 0
For Each cellule In Range("B4:J1015")

i = i + 1
If i Mod (2) = 0 Then
    j = j + 1
    Dim source As String
    Dim dest As String
    source = "(B4:J1015)" + CStr(i)
    dest = "(L4:T1015)" + CStr(j)
   'Worksheets("trie").Range("B4:J1012" + CStr(i)).Value = Worksheets("trie1").Range("L4:T506" + CStr(j)).Value
    Sheets("trie").Range("L4:T1015").Value = Sheets("trie").Range("B4:J1015").Value
End If

Next cellule


End Sub
 

moilolo0404

Expert
#7
bonjour Svoglimacci,

c'est cool ,ça fonctionnent ,seul petits soucis comment arrêter à la ligne 1015 svp
Code:
While (i <= 1015)
si je me suis pas tromper !!?
 
Dernière édition:

magellan

Modérâleur
Staff
#9
Perso je préfère le mod() (modulo) comme ça le test est forcément bon. ;)
 

moilolo0404

Expert
#10
bonjour magellan ,

perso je suis pas contre le fait d'apprendre plusieurs approche différente,si tu pouvais expliquer un peu ton code que je comprennent pourquoi je ne suis arrivée qu'a avoir une copie du tableau initial ...
merci pour votre aide très précieuse
 

svoglimacci

check memory failed but no bug detected
#11
bonjour Svoglimacci,

c'est cool ,ça fonctionnent ,seul petits soucis comment arrêter à la ligne 1015 svp
Code:
While (i <= 1015)
si je me suis pas tromper !!?
Comme l'a dit @magellan c'est impeccable comme test. En fait, j'ai mis (
Range("A" & Rows.Count).End(xlUp).Row ) en partant du principe que ton "1015" était une valeur d'exemple. Et mon expression donne en fait la dernière ligne de toute la page, ce qui effectivement s'avère faux dans ton cas.

Perso je préfère le mod() (modulo) comme ça le test est forcément bon. ;)
Si c'est à moi que tu écris et que c'est par rapport au fait de débuter par i=1 ou i=2 , le mod() est en effet bien plus élégant. Ce qui m'a ennuyé est du coup d'imbriquer aussi un bloc "If" et faire deux fois plus de boucles (boucles qui certes ne coutent en fait absolument aucun temps machine ni lecture). On peut tirer à pile ou face ;)
P.S. Non tu as raison. Mettre un bloc "If" (avec ici ton mod() ) permet de s'adapter à d'autres cas de figure comme "If i est un nombre premier" ou quelque autre test. Là, le i+2 est totalement à la ramasse.
 

moilolo0404

Expert
#12
bonjour svoglimacci,
pourrai tu me dire ce qu'il faudrait ajouter au code pour supprimé l'affichage lors du transfert des données
j'ai ajouter
Code:
Application.ScreenUpdating = False
après sub maintenant c'est ok

merci pou ton aide
 
Dernière édition:

magellan

Modérâleur
Staff
#13
Comme l'a dit @magellan c'est impeccable comme test. En fait, j'ai mis (
Range("A" & Rows.Count).End(xlUp).Row ) en partant du principe que ton "1015" était une valeur d'exemple. Et mon expression donne en fait la dernière ligne de toute la page, ce qui effectivement s'avère faux dans ton cas.

Si c'est à moi que tu écris et que c'est par rapport au fait de débuter par i=1 ou i=2 , le mod() est en effet bien plus élégant. Ce qui m'a ennuyé est du coup d'imbriquer aussi un bloc "If" et faire deux fois plus de boucles (boucles qui certes ne coutent en fait absolument aucun temps machine ni lecture). On peut tirer à pile ou face ;)
P.S. Non tu as raison. Mettre un bloc "If" (avec ici ton mod() ) permet de s'adapter à d'autres cas de figure comme "If i est un nombre premier" ou quelque autre test. Là, le i+2 est totalement à la ramasse.
Précisément: j'ai codé ça à l'arrache. Dans les faits j'aurais créé une librairie dédiée paramétrable avec en entrée
- La colonne source
- La colonne destination
- Le "pas" de décalage (typiquement les règles que tu énonces, ou encore 1 sur 3 etc etc)...

Me concernant ce n'est pas une question d'élégance en fait mais de lisibilité et d'efficacité du code. Je passe mes journées à faire du code, à réviser de l'existant et rien n'est plus exaspérant de voir des duplications de lignes, ou pire encore des "recherches dans des recherches". Par exemple, tu as une requête de base de données en amont, et au lieu de l'affiner voilà que le gus te fait une boucle dégueulasse pour retraiter le jeu de données... au lieu de préciser la requête avec des clauses complémentaires autrement plus précises et efficaces. Mieux encore, cela épargne du CPU (la BDD se chargeant des recherches et non une boucle immonde chargeant le processeur local), restreint le flux réseau (puisque ne ramenant que l'indispensable), et fin du fin cela réduit les bugs puisque si la requête est foireuse, elle sera la seule chose à modifier, là où une boucle pourra toujours trimbaler des cochonneries (tableaux trop grands, cas d'exclusions oubliés, jointures mal pensées...)
 

moilolo0404

Expert
#14
bonjour magellen,
te serai t'il possible d'aller au bout de ta démarche quand au code que tu ma proposé en le rendant fonctionnel et en le détaillant (commentaire d'explication ) dans le code que je puisse m'y retrouver ..
merci à vous pour votre aide
 

svoglimacci

check memory failed but no bug detected
#15
Me concernant ce n'est pas une question d'élégance en fait mais de lisibilité et d'efficacité du code. Je passe mes journées à faire du code, à réviser de l'existant et rien n'est plus exaspérant de voir des duplications de lignes, ou pire encore des "recherches dans des recherches".
C'est la mort. Lorsque cela enfle, ça s'appelle toujours un "plat de spaghettis" ? Quand à la duplication de code, je préfère ne pas en parler. C'est développer du code dans lequel on n'oserait pas soi-même mettre le nez un an après.
Honnêtement, mon habitude sur un code court et bien ciblé comme celui demandé par @moilolo0404 est de ne pas structurer à outrance, à part pour éviter que la même constante apparaisse en deux endroits. Après, si il apparaît que la condition (paire ou impaire) peut évoluer, que les limites peuvent-être autres que [4;1012] ou autres, la structuration s'impose.
bonjour magellen,
te serai t'il possible d'aller au bout de ta démarche quand au code que tu ma proposé en le rendant fonctionnel et en le détaillant (commentaire d'explication ) dans le code que je puisse m'y retrouver ..
Tu veux le code "@magellan" et le code "@svoglimacci" ? ;)
Tu sais, à ce que j'ai vu de l'esprit du forum, on ne donne normalement pas de code "tout fait". Là c'était court alors je l'ai fait, mais avec plein d'explications dans le code pour que tu comprennes tout. Si je t'ai bien compris, le code fonctionne, tu l'as même adapté.
Pourquoi alors veux-tu aussi la version de @magellan ? C'est pour comparer les bienfaits de l'une ou l'autre ou pour comprendre ses instructions ? Pour ce qui est des instructions, je te conseillerai vivement d'aller farfouiller sur le web, surtout chez Micro$oft :)
Quoi qu'il en soit je pense que @magellan est par ailleurs bien occupé(*). Il t'a donné de sacrées pistes, à toi maintenant de comprendre les pistes, de les bétonner pour en faire des routes, et faire des trottoirs pour éviter les sorties de routes ;)

Si je n'ai rien compris à tes demande, explique :D
(*) Edit : j'adore parler à la place que Magellan :D
 

moilolo0404

Expert
#16
bonjour,
les bien FAIT de chacune des proposition non ,çà n'est pas possible ,cela est
un peu dommage ,pour creuser c'est sur que ce sera le cas ,on à toussent une approche différente de la façon de faire ,d'orienter et de développé ,est en ce qui concerne magellanet je n'est pas compris simplement .. je suis loin d'avoir un niveau t'elle que le votre .... merci toute fois à vous deux et à toi pour des explication claire qui comme tu la dit ma permis de le complété et de l'adapte ps je regarderai pour les piste indiquer merci
 

svoglimacci

check memory failed but no bug detected
#17
bonjour,
les bien FAIT de chacune des proposition non ,çà n'est pas possible ,cela est
un peu dommage ,pour creuser c'est sur que ce sera le cas ,on à toussent une approche différente de la façon de faire ,d'orienter et de développé ,est en ce qui concerne magellanet je n'est pas compris simplement .. je suis loin d'avoir un niveau t'elle que le votre .... merci toute fois à vous deux et à toi pour des explication claire qui comme tu la dit ma permis de le complété et de l'adapte ps je regarderai pour les piste indiquer merci
Wow tu as écrit depuis un téléphone ? ;)
Je pense que mon dernier post était peut-être mal rédigé et que je t'ai agacé, je suis désolé ce n'était pas le but. Mais ce que j'y disais reste vrai : fais des recherches, la littérature du net déborde d'infos sur les fonctions sur lesquelles tu veux des infos. Recherche par exemple "VBA Excel Range"... Après, si tu ne comprends pas, viens demander ;)
 

magellan

Modérâleur
Staff
#18
Si je n'ai rien compris à tes demande, explique :D
(*) Edit : j'adore parler à la place que Magellan :D
Mon pauvre vieux... avoir l'idée de t'approprier mes cordes vocales, c'est comme demander à une cantatrice de s'essayer au death metal... :D
 

magellan

Modérâleur
Staff
#19
Code:
Sub test()
Sheets("Feuil1").Select
'On fait les déclarations de variables
Dim cellule As Range ' celle-ci pour la liste
Dim i As Double 'i pour le premier compteur de passage et savoir si c'est pair/impair
Dim j As Double 'j pour le compteur de lignes dans la colonne cible
i = 0

' A améliorer ici (la flemme et il est tard :D )
For Each cellule In Range("A:A") ' On prend chaque cellule de la colonne A et l'on boucle dessus

i = i + 1 'on compte les lignes une à une (à tous les passages)
If i Mod (2) = 0 Then 'Si la valeur est pair (le modulo est le reste d'une division j'y reviendrai ensuite)
    j = j + 1 ' alors j'incrémente le numéro de ligne de la colonne cible
    Dim source As String 'Je définis la source
    Dim dest As String ' Je définis la cible
    source = "A" + CStr(i) 'Je construis le nom de la source
    dest = "A" + CStr(j) 'Je construis le nom de la cible
    'Transfert de la valeur d une cellule à l autre via le nom de la feuille 1 et 2 et le nom/position de la cellule
    Worksheets("Feuil2").Range(dest).Value = Worksheets("Feuil1").Range(source).Value
End If

Next cellule
'Fin du code
End Sub
Bon là je ne fais que commenter vite fait mon code.
Pour l'expliquer plus clairement:
1° Je procède à la sélection de toute la colonne A (le range initial)
2° je boucle sur chaque cellule
3° Si le numéro incrémenté i est pair (modulo) j'incrémente la position de la cellule cible
Là j'explique
Premier passage pair: j'entre et je fais un j+1. Comme j commence à zéro, cela donne un.
donc la cellule cible est "A1" dans le feuillet "feuil2" (dans mon exemple
Et ainsi de suite
ligne 4 de feuil1: A2 sur feuil2
Etc etc.

Ce qui manque clairement dans le code
- Comment traiter les cellules vides
- Comment ne pas copier inutilement au-delà de la sélection utile (bouffe de la ressource en vain jusqu'à planter)
- Comment traiter (si on le souhaite) les éventuels doublons de valeurs
- Ajouter un éventuel affichage de progression (bargraph?)
- Envisager un bouton sur le fichier excel considéré pour que cela fasse le boulot au clic et non en debug
- Procéder à un affichage en fin d'exécution via une fenêtre d'alerte
- Afficher comme le propose @svoglimacci les cellules en cours de traitement.

Pour ce dernier point je suis circonspect: d'un point de vue esthétique et pédagogique pourquoi pas, à l'usage courant non merci, cela squatte de la ressource technique pour rien. Mais là comme on est sur une sorte de cours de codage...


Bref: copie le code que je t'ai filé pour voir les commentaires que j'ai mis, exécute en pas à pas via le mode débug, mets des points d'arrêt et observe l"évolution des variables. Mieux encore, trace visuellement sur un papier les résultats.

Perso :
j'adore ce bout de code de @svoglimacci
Code:
fin = Range("A" & Rows.Count).End(xlUp).Row ' On trouve le numéro de la dernière ligne qui j'espère devrait être la dernière ligne de toute la page.
While (i <= fin) ' on boucle
' ici à toi d'adapter
Wend ' Fin de boucle.
Il corrige le bug flagrant de surconsommation mémoire et de temps de mon code précédent. Mais comme tu es là pour apprendre, charge à toi d'inclure l'un sur l'autre pour en piger le fonctionnement... il a le mérite (petite piste) de ne pas aller traiter au-delà du nécessaire et de faire donc le minimum requis, ce qui est une excellente optimisation de ma proposition.
 

svoglimacci

check memory failed but no bug detected
#20
Vous devez vous inscrire ou vous connecter pour répondre ici.
Membres en ligne
  • Rougini
  • bastien.festinoni
  • longaripa
  • dedzix
  • SergioVE
  • Christobis
Derniers messages publiés
Statistiques globales
Discussions
866 641
Messages
8 070 799
Membres
1 577 185
Dernier membre
Rougini
Partager cette page
Haut