TL;DR —
Cells, c'estRangeadressé 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 stocke — la ligne d'abord, puis la colonne — d'où le fait queCells(1, 2)soit B1, et non A2. Comme les deux coordonnées sont des nombres que vous pouvez calculer,Cellsest la référence conçue pour les boucles. EmployezRangepour les zones que vous saisissez par leur nom,Cellspour les positions que vous calculez, etRange(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 —
CellsestRangeadressé par deux nombres au lieu d'une chaîne - La règle la plus importante —
Cells(ligne, colonne), doncCells(1, 2)est B1, pas A2 - Bâtir un bloc à partir d'angles calculés avec
Range(Cells(...), Cells(...)) - Pourquoi un
Cellsnu, 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 à
Rangeet 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
