Se connecter avec
S'enregistrer | Connectez-vous

Macro Excel: sélection d'un tableau selon sa longueur variable

Dernière réponse : dans Programmation

Bonjour à tous,

Je suis en train de tenter de créer une macro pour mon travail. Le but est de copier un tableau et de le mettre dans une autre feuille (entre autre). Le souci est que le nombre de lignes de mon tableau est variable. Pour l'instant, en enregistrant ma macro grâce à l'utilitaire d'Excel j'obtiens le code suivant :
  1. Range("A3").Select
  2. Range(Selection, Selection.End(xlDown)).Select
  3. Range("A3:C24").Select


Cela ne me convient pas, car j'aimerais que C24 puisse aussi être C12, C87 ou encore C2398, etc... selon le nombre de lignes de mon tableau.

De la même manière, je cherche à sélectionner une seule colonne (ex : A3:A24) selon le nombre de lignes remplies qui est variable.

Merci d'avance de votre aide !
Lassé par la pub ? Créez un compte

Meilleure solution

Expert Programmation

Salut,

Se servir de l'enregistreur et adapter le code obtenu est une excellente chose. Mais l'on est vite limité si l'on ne connaît pas ni le VB, ni les objets VBA spécifiques à Excel.

Je t'invite tout d'abord à lire cet article : http://www.presence-pc.com/forum/ppc/Programmation/vous...

Revenons à ton code.
Tu sélectionnes telle cellule à seule fin de t'en servir pour définir telle autre. C'est peu productif. Par principe, dès que tu vois le code suivant :
  1. Object.Select
  2. Slection.Action
Transforme-le directement en :
  1. Object.Action

Ça fait, pour les deux premières lignes de ton code :
  1. Range(Range("A3" ), Range("A3" ).End(xlDown)).Select


Bon, là encore, il y a un Select. Je parie que tu ne peux rien sélectionner, mais juste référencer la zone.

Voici un exemple pour copier une zone, tel que l'enregistreur le code :
  1. Range("A1:B3").Select
  2. Selection.Copy
  3. Sheets("Feuil2").Activate
  4. Range("C4").Select
  5. ActiveSheet.Paste
  6. Application.CutCopyMode = False

Que c'est laid : D'une part on sélectionne des tas de cellules pour rien, il suffisait de les désigner sans les sélectionner, et d'autre part, on abuse du presse-papier qui est une zone de mémoire à disposition de l'utilisateur, certainement pas des programmes. Imagine que plusieurs programmes, pour leur besoin interne, passent par le presse-papier en même temps. Quelle pagaille en perspective !

Donc supprimons et les sélections et l'usage du presse-papier :
  1. Range("A1:B3").Copy Sheets("Feuil2").Range("C4")

Et oui, c'est tout. Bon, quand on jongle avec plusieurs feuilles, il est de bon ton de les préciser à chaque fois, en ne considérant que les feuilles de calcul, de surcroît :
  1. Worksheets("Feuil2").Range("A1:B3").Copy Worksheets("Feuil2").Range("C4")


Revenons maintenant à ton cas. Tu veux copier une zone de la feuille 1 (hypothèse) qui commence à une cellule donnée (A3), qui finit vers le bas dès qu'on trouve une ligne vide (End(xlDown)) vers une cellule (X42 - hypothèse) de la feuille 2 (hypothèse).

C'est parti :
  1. Worksheets("Feuil1").Range(Worksheets("Feuil1").Range("A3"), Worksheets("Feuil1").Range("A3").End(xlDown)).Copy Worksheets("Feuil2").Range("X12")


Bon, c'est un peu lourd comme écriture ! On va alléger ça en mettant des variables :
  1. Dim ws_source As Worksheets
  2. Dim ws_target As Worksheets
  3. Dim cell_source_1er As Range
  4. Dim cell_source_der As Range
  5. Dim cell_target As Range777
  6.  
  7. Set ws_source = Worksheets("Feuil1")
  8. Set ws_target = Worksheets("Feuil2")
  9.  
  10. Set cell_source_1er = ws_source.Range("A3")
  11. Set cell_source_der = cell_source_1er.End(xlDown)
  12. Set cell_target = ws_target.Range("X12")
  13.  
  14. ws_source.Range(cell_prems, cell_source_der).Copy cell_target


En étudiant ce code, tu conviendras que la préparation est un peu laborieuse, mais dans un programme un peu plus long, d'un part ce sera plus facile à relire, et d'autre part, il est fort probable que tu n'ais pas à refaire certains calculs.

Cela t'aide-t-il ?

En effet, ça m'aide ! Merci pour ta réponse claire et bien expliquée.

Quant au lien que tu m'as donné, je l'ai trouvé après avoir posté et j'ai déjà commencé à en appliquer le premier conseil : découper ma grosse macro en plusieurs petites macros dont je peux comprendre le code. :) 

Petite question supplémentaire (désolé si j'abuse de ta gentillesse et de celle des autres sur le forum, si je n'obtiens pas de réponse je persévérerai de mon côté :whistle:  ) : comment pourrait-on faire en sorte de copier également la colonne B et C en même temps ? Je veux dire par là étendre la zone à copier à deux colonnes vers la droite.

Par exemple, si mon tableau descend jusqu'à la ligne 24 j'aimerais pouvoir copier les cellules (A3:C24) en une seule fois...

Encore merci pour toutes tes explications !
Expert Programmation

Salut,

Petite réponse supplémentaire :
1°) Tu n'abuses pas ;) 
2°) La zone à copier est définie par les deux cellules cell_source_1er et cell_source_der.
Vois ce que nous avons définit :
  1. MsgBox ws_source.Range(cell_prems, cell_source_der).Address


Il faudrait donc décaler de deux colonnes d'une des deux bornes (un décalage se dit offset en anglais).

En VB aussi :
  1. Set cell_source_1er = ws_source.Range("A3" )
  2. Set cell_source_der = cell_source_1er.End(xlDown).Offset(0, 2)
  3.  
  4. MsgBox ws_source.Range(cell_prems, cell_source_der).Address
Lassé par la pub ? Créez un compte