🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Cells vs Range dans Excel — référencer des cellules par numéro (et pourquoi Cells(1, 2) est B1, pas A2)

|

VBA Cells vs Range dans Excel — référencer des cellules par numéro (et pourquoi Cells(1, 2) est B1, pas A2)

TL;DRCells, c'est Range adressé par des nombres. Range("A1") nomme une cellule avec une chaîne dans l'ordre où vous la lisez (la lettre de colonne, puis la ligne). Cells(ligne, colonne) nomme une seule cellule avec deux entiers dans l'ordre où Excel la stockela ligne d'abord, puis la colonne — d'où le fait que Cells(1, 2) soit B1, et non A2. Comme les deux coordonnées sont des nombres que vous pouvez calculer, Cells est la référence conçue pour les boucles. Employez Range pour les zones que vous saisissez par leur nom, Cells pour les positions que vous calculez, et Range(Cells(1, 1), Cells(n, k)) pour bâtir un bloc à partir d'angles calculés.

Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
' Range nomme une zone fixe ; Cells calcule une position, ligne d'abord.
ws.Range("A1").Value = "Header"          ' la facon humaine - une adresse saisie
ws.Cells(2, 1).Value = "First row"       ' ligne 2, colonne 1 = A2 (PAS B2)

Référencer des cellules est la première chose que fait toute macro, et Cells contre Range est le premier endroit où l'on trébuche. La confusion ne vient pas de ce que l'un vaudrait mieux que l'autre — c'est qu'ils adressent les cellules différemment, et que confondre l'ordre écrit en silence au mauvais endroit. Ce guide s'articule autour d'une seule idée qui rend tout le reste prévisible : Cells est le jumeau numérique de Range, et ses arguments vont d'abord par ligne. Une fois cette idée acquise, les motifs de boucle comme les bugs d'orientation inversée prennent tout leur sens.

Ce que vous allez apprendre

  • Le modèle mental — Cells est Range adressé par deux nombres au lieu d'une chaîne
  • La règle la plus importante — Cells(ligne, colonne), donc Cells(1, 2) est B1, pas A2
  • Bâtir un bloc à partir d'angles calculés avec Range(Cells(...), Cells(...))
  • Pourquoi un Cells nu, sans indice, désigne chaque cellule de la feuille
  • Indexer une plage existante avec rng.Cells(i) et son ordre ligne par ligne
  • Quand recourir à Range et quand recourir à Cells — et pourquoi ne pas le mettre en boucle

Le modèle mental : Cells est Range adressé par des nombres

Une référence de cellule doit répondre à une seule question — quelle cellule ? — et VBA vous offre deux façons d'y répondre. Range("A1") répond par une chaîne en notation tableur : la lettre de colonne d'abord, puis le numéro de ligne, exactement comme votre regard balaie la grille. Cells(1, 1) répond par deux entiers : la ligne, puis la colonne.

ws.Range("B3").Value = 10    ' adresse texte : colonne B, ligne 3
ws.Cells(3, 2).Value = 10    ' meme cellule, en nombres : ligne 3, colonne 2

Elles désignent la même cellule. La différence qui compte, c'est ce que vous pouvez faire de l'adresse : une chaîne comme "B3" est un texte figé, tandis que Cells(3, 2) est composé de deux nombres que vous pouvez calculer. C'est toute la raison d'être de Cells — c'est la référence que vous pouvez piloter depuis un compteur, un UBound ou une ligne repérée à l'exécution. Range sert à la zone que vous connaissez par son nom ; Cells sert à la position que vous déterminez dans le code.

La règle la plus importante : Cells est (ligne, colonne), donc Cells(1, 2) est B1

Voici la ligne qui piège tous ceux qui ont l'habitude de taper "A2". Les arguments vont d'abord la ligne, puis la colonne — on descend avant de traverser — soit l'inverse de l'ordre « lettre puis nombre » que vous lisez sur la feuille :

ws.Cells(1, 2).Value = "here"   ' ligne 1, colonne 2  =>  B1   (PAS A2)
ws.Cells(2, 1).Value = "there"  ' ligne 2, colonne 1  =>  A2

Si vous attendiez que Cells(1, 2) soit A2 parce que « A est la colonne 1 et 2 la ligne », vous l'avez lu dans l'ordre de la grille ; VBA le lit dans l'ordre de stockage. Un moyen mnémotechnique fiable : L avant C — ligne, puis colonne, le même ordre que la notation R1C1 et les indices de matrice. Inversez-le dans une boucle et chaque écriture atterrit décalée d'un axe, transposée sur la feuille, sans la moindre erreur pour vous avertir. Dans le doute, dites-le à voix haute à chaque fois : « ligne r, colonne c ».

L'argument de colonne accepte aussi une lettre sous forme de chaîne, ce qui est pratique quand vous connaissez la colonne mais calculez la ligne :

ws.Cells(lastRow + 1, "C").Value = total   ' la ligne est calculee, la colonne C est connue

Bâtir un bloc à partir d'angles calculés : Range(Cells, Cells)

Cells adresse une seule cellule ; seul, il ne peut donc pas décrire un bloc. L'idiome qui débloque les plages dynamiques consiste à passer deux appels Cells comme les angles d'un Range :

Dim lastRow As Long, lastCol As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row       ' bas de la colonne A
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
' Batir tout le bloc de donnees a partir de deux angles calcules :
Dim data As Range
Set data = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))   ' A1 : derniere cellule

C'est là tout l'intérêt d'apprendre Cells : Range("A1") seul ne peut pas prendre un coin inférieur droit calculé sans coller une chaîne ("A" & lastRow), ce qui casse dès que vos colonnes dépassent Z. Range(Cells(1, 1), Cells(lastRow, lastCol)) reste numérique et se moque bien de la largeur des données. À partir de là, vous pouvez remodeler la référence avec Resize ou laisser Excel trouver le bloc à votre place avec CurrentRegion.

Un Cells nu désigne toute la feuille

Cells sans indice n'est ni une erreur ni une cellule unique — c'est la collection de toutes les cellules de la feuille de calcul. C'est réellement utile pour les opérations à l'échelle de la feuille :

ws.Cells.ClearContents          ' efface toutes les valeurs de la feuille
ws.Cells.Font.Name = "Calibri"  ' definit la police partout d'un coup

Mais c'est aussi un piège : un Cells nu là où vous vouliez une cellule précise agit en silence sur les 1 048 576 × 16 384 cellules. Si une macro censée « mettre en forme une cellule » reformate toute la feuille, cherchez un Cells qui a perdu son indice. La bonne habitude est de toujours donner à Cells son (ligne, colonne), sauf si vous visez vraiment tout.

Cells au sein d'une plage, et l'indice linéaire

Cells n'est pas qu'une propriété de feuille de calcul — il fonctionne aussi relativement à une plage, où (1, 1) désigne le coin supérieur gauche de cette plage, et non A1 :

Dim blk As Range: Set blk = ws.Range("C5:F20")
blk.Cells(1, 1).Value = "top-left of the block"   ' C5, pas A1

Il existe aussi une forme à indice unique, Cells(i), qui parcourt les cellules dans l'ordre ligne par ligne — de gauche à droite sur une ligne, puis vers le bas jusqu'à la suivante :

blk.Cells(1).Value   ' C5   (premiere cellule)
blk.Cells(5).Value   ' C6   (quatre sur le bloc large de 4, puis passage a la ligne suivante)

La surprise ici, c'est le sens : Cells(i) compte en travers avant de descendre, si bien que dans un bloc de 4 colonnes, la cellule numéro 5 est le début de la deuxième ligne, pas la cinquième ligne. Si un parcours linéaire semble sauter au mauvais endroit, c'est presque toujours cet ordre ligne par ligne opposé à une attente colonne par colonne.

Range pour les zones, Cells pour les positions — et sans boucle

La règle claire n'est pas « préférez-en un ». C'est : employez Range pour les zones que vous nommez et Cells pour les positions que vous calculez. Une zone de rapport fixe, un bloc nommé, une ligne d'en-tête saisie une fois — c'est Range("A1:D1"). Une cellule dont vous calculez la ligne ou la colonne à l'exécution — c'est Cells(r, c). Ils se combinent : Range(Cells(...), Cells(...)) bâtit un bloc à la forme nommée à partir d'angles calculés.

La seule chose à éviter, c'est de recourir à Cells dans une boucle cellule par cellule quand il existe une opération sur toute la plage. Écrire For r = 2 To lastRow: ws.Cells(r, 3).Value = ... touche la feuille une fois par ligne et c'est la première cause de macros qui rampent. Le geste mûr consiste à se servir de Cells pour trouver les angles, à bâtir le Range et à agir sur tout le bloc en une fois — affecter un tableau à Range(...).Value, ou appeler une méthode native (voir WorksheetFunction). Cells sert à localiser le travail ; il ne doit pas servir à effectuer chaque unité de celui-ci.

Comment ExcelMaster aide

Cells contre Range cache plus de décisions qu'il n'y paraît : quel argument est la ligne, si un Cells nu vient de toucher toute la feuille, si un indice linéaire va en travers ou vers le bas, et si une boucle aurait dû être une seule écriture sur toute la plage. Chaque mauvais virage est silencieux — une valeur décalée d'un axe, une remise en forme de toute la feuille, une macro qui rampe.

ExcelMaster vous laisse plutôt décrire le résultat. Dites « remplis la colonne C d'un cumul jusqu'à la dernière ligne de données », et il trouve la dernière ligne, bâtit Range(Cells(2, 3), Cells(lastRow, 3)) et écrit les valeurs en une seule passe — arguments ligne d'abord corrects, aucun Cells accidentel sur toute la feuille, aucune boucle cellule par cellule. Vous gardez le classeur et le code ; vous vous épargnez la passe où les écritures ont atterri transposées.

Questions fréquentes

Quelle est la différence entre Cells et Range en VBA Excel ?

Les deux désignent des cellules, mais les adressent différemment. Range("A1") utilise une chaîne en notation tableur — la lettre de colonne puis la ligne. Cells(1, 1) utilise deux nombres — la ligne puis la colonne. Comme les arguments de Cells sont des nombres que vous pouvez calculer, Cells est ce que vous employez dans les boucles et pour les positions déterminées à l'exécution ; Range sert aux zones fixes ou nommées que vous saisissez par leur nom. Ils se combinent en Range(Cells(r1, c1), Cells(r2, c2)) pour bâtir un bloc à partir d'angles calculés.

Pourquoi Cells(1, 2) est-il la cellule B1 et non A2 ?

Parce que Cells prend ses arguments la ligne d'abord, la colonne ensuite — l'inverse de l'ordre « lettre puis nombre » que vous lisez sur la grille. Cells(1, 2) signifie ligne 1, colonne 2, soit B1. Cells(2, 1) signifie ligne 2, colonne 1, soit A2. Retenez « L avant C » (ligne, puis colonne), le même ordre que la notation R1C1.

Comment sélectionner une plage de cellules avec Cells en VBA ?

Passez deux appels Cells comme les angles d'un Range : Range(Cells(1, 1), Cells(10, 4)) correspond à A1:D10. C'est la manière standard de bâtir un bloc quand les angles sont calculés, par exemple Range(Cells(2, 1), Cells(lastRow, lastCol)). Qualifiez à la fois les Cells et le Range avec la même feuille de calcul, pour que la référence ne pointe pas vers la feuille qui se trouve être active.

Que fait Cells sans argument en VBA ?

Un Cells nu (sans indice) désigne chaque cellule de la feuille de calcul. Cells.ClearContents efface toute la feuille et Cells.Font.Size = 11 règle chaque cellule. C'est utile pour les changements à l'échelle de la feuille, mais cela signifie aussi qu'un Cells qui a perdu son indice (ligne, colonne) agira en silence sur toute la feuille — indexez-le donc toujours quand vous visez une cellule précise.

Puis-je utiliser une lettre de colonne avec Cells au lieu d'un nombre ?

Oui. L'argument de colonne accepte une chaîne, donc Cells(2, "B") équivaut à Cells(2, 2) (la cellule B2). L'argument de ligne, lui, doit être un nombre. Utiliser une lettre est pratique quand vous connaissez la colonne mais calculez la ligne, comme dans Cells(lastRow + 1, "C").

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 15/08/2026.

Guides associés : VBA Range · VBA Resize · VBA CurrentRegion · VBA Offset · VBA For Loop