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

VBA Offset dans Excel — se déplacer relativement à une cellule (Offset contre Resize et le piège du décalage d'une unité)

|

VBA Offset dans Excel — se déplacer relativement à une cellule (Offset contre Resize et le piège du décalage d'une unité)

TL;DRrng.Offset(rowDelta, colDelta) renvoie une nouvelle plage décalée d'autant de lignes et de colonnes par rapport à rng. C'est un pas, pas un lieu : elle conserve la même taille, ne modifie pas rng et ne sélectionne rien. Les deux nombres sont relatifsOffset(1, 0) avance d'une ligne vers le bas, Offset(0, 0) est la cellule elle-même, et les valeurs négatives montent ou vont à gauche. Offset déplace ; Resize change la taille. Combinez-les et vous obtenez l'idiome de plage le plus utile de tout VBA : data.Offset(1).Resize(data.Rows.Count - 1) — « tout sauf l'en-tête ».

Offset est la façon dont une macro dit « la cellule à côté de celle que je viens de trouver ». Vous avez localisé une correspondance, un total, un en-tête — et vous voulez maintenant lire ou écrire la cellule une colonne plus loin ou une ligne plus bas. Ce déplacement relatif est toute la raison d'être d'Offset, et cela devient un réflexe dès que vous cessez de lire les arguments comme des coordonnées pour les lire comme des pas.

Ce que vous allez apprendre

  • Le modèle mental : Offset est un pas relatif, pas une adresse absolue
  • Le piège du décalage d'une unité — pourquoi Offset(1, 1) atterrit sur B2, pas sur A1
  • Offset conserve la taille ; Resize la change — et pourquoi les deux vous sont généralement nécessaires
  • L'idiome de saut d'en-tête Offset(1).Resize(n - 1), expliqué
  • En quoi Range.Offset (VBA) diffère de la fonction OFFSET() de la feuille de calcul

Le modèle mental : Offset est un pas, pas un lieu

Tenez-vous sur une cellule. Offset(rowsDown, colsRight) fait autant de pas et vous remet la cellule (ou le bloc) où vous atterrissez — une plage toute neuve. L'originale reste intacte. Parce que le déplacement est relatif, le même Offset(1, 0) signifie « une ligne vers le bas », que vous partiez de A1 ou de Z500.

Sub OffsetSteps()
    Debug.Print Range("B2").Offset(1, 0).Address   ' -> $B$3   (une ligne vers le bas)
    Debug.Print Range("B2").Offset(0, 1).Address   ' -> $C$2   (une colonne vers la droite)
    Debug.Print Range("B2").Offset(-1, 0).Address  ' -> $B$1   (une ligne vers le haut)
    Debug.Print Range("B2").Offset(0, 0).Address   ' -> $B$2   (aucun déplacement)
End Sub

Remarquez que Offset(0, 0) est la cellule elle-même. C'est le signe que ce sont des deltas, pas des positions. Si vous voulez une cellule absolue, ne calculez pas un décalage depuis A1 — utilisez Cells(row, col). Offset sert au « relatif à quelque chose que je possède déjà ».

La règle qui piège les débutants : le décalage d'une unité

Le bug d'Offset numéro un, c'est de lire les arguments comme une coordonnée. Offset(1, 1) ne signifie pas la cellule A1 ni « ligne 1, colonne 1 ». Cela signifie une ligne vers le bas et une colonne vers la droite depuis l'ancre. Depuis A1, on atterrit sur B2.

Range("A1").Offset(1, 1).Address   ' -> $B$2, PAS $A$1
Range("A1").Offset(0, 0).Address   ' -> $A$1

Prononcez les deux arguments à voix haute, « bas, droite », à chaque fois, et le bug disparaît. Cela explique aussi le motif de boucle classique : pour écrire un résultat à côté de chaque ligne trouvée, vous décalez du compteur de boucle, et la première ligne utilise Offset(0, …), pas Offset(1, …).

La distinction qui perturbe tout le monde : Offset déplace, Resize change la taille

Offset ne change jamais la taille d'une plage — il fait glisser la forme entière. Déplacez une colonne de dix cellules et vous obtenez une colonne de dix cellules ailleurs :

Range("A1:A10").Offset(0, 1).Address   ' -> $B$1:$B$10   (10 cellules, déplacées à droite)

Pour changer la taille d'une plage, il faut une autre méthode, Resize(rows, cols), qui redessine le bloc à partir de sa cellule en haut à gauche :

Range("A1").Resize(5, 2).Address       ' -> $A$1:$B$5   (5 lignes, 2 colonnes)

Ce sont les deux moitiés de l'arithmétique des plages : Offset choisit , Resize choisit quelle taille. Vous les combinez sans cesse — le plus souvent pour retirer une ligne d'en-tête.

L'idiome à mémoriser : sauter l'en-tête avec Offset + Resize

Vous avez un tableau, en-tête compris, et vous ne voulez que le corps des données. Décalez d'une ligne vers le bas pour quitter l'en-tête — mais Offset seul conserve la même hauteur, si bien que la plage dépasse désormais d'une ligne sous les données. Resize la rétrécit de cette ligne :

Sub DataBodyOnly()
    Dim tbl As Range, body As Range
    Set tbl = Range("A1").CurrentRegion          ' en-tête + données
    Set body = tbl.Offset(1).Resize(tbl.Rows.Count - 1)
    body.Select                                  ' lignes de données seules, sans en-tête
End Sub

Offset(1) (le delta de colonne vaut 0 par défaut) fait glisser tout le bloc d'une ligne vers le bas ; Resize(tbl.Rows.Count - 1) rogne la ligne du bas qui dépasse désormais. Le résultat, c'est le corps des données sans l'en-tête — exactement la plage que vous voulez trier, copier ou effacer. Cette unique ligne remplace bien des constructions manuelles de chaînes A2:A. Pour trouver tbl sans coder en dur, voyez comment trouver la dernière ligne et CurrentRegion.

Le piège du bord de la feuille

Parce qu'Offset est relatif, franchir le bord de la feuille est une erreur, pas un plafonnement silencieux :

Range("A1").Offset(-1, 0)   ' erreur d'exécution 1004 — impossible de remonter au-dessus de la ligne 1

Si une macro remonte ou va à gauche près du coin supérieur gauche (fréquent lors de la recherche d'en-têtes), protégez le déplacement ou vérifiez rng.Row > 1 avant de décaler vers le haut.

La méthode Offset contre la fonction OFFSET de la feuille

Elles partagent un nom et la même idée, mais ce ne sont pas le même outil. La fonction de feuille de calcul OFFSET() vit dans une cellule, est volatile (elle se recalcule à chaque changement, ce qui peut ralentir un classeur) et renvoie une valeur ou une référence pour une formule. Range.Offset est une méthode VBA : elle renvoie un objet Range, n'est pas volatile, et ne s'exécute que lorsque votre code s'exécute. Si vous écrivez une macro, utilisez la méthode ; ne recourez à la fonction de feuille que lorsqu'il vous faut une référence vivante, qui se met à jour toute seule, à l'intérieur d'une formule.

Comment ExcelMaster aide

Le code chargé d'Offset construit d'ordinaire une seule chose : un résultat placé relativement à quelque chose que vous avez trouvé — un indicateur à côté de chaque correspondance, un cumul une colonne plus loin, une valeur copiée depuis la ligne sous une étiquette. ExcelMaster prend cette intention en langage courant — « à côté de chaque facture en retard, écris le nombre de jours de retard » — et génère la logique de référence relative, pour que vous n'ayez ni à compter les deltas à la main ni à déboguer un décalage d'une unité.

Vous écrirez encore Offset au cœur d'une boucle de macro serrée. Mais pour la tâche quotidienne « place un résultat à côté de chaque ligne », décrire l'emplacement est plus rapide et moins risqué que de raisonner sur (1, 0) contre (0, 1).

Questions fréquentes

Que fait Offset en VBA ?

rng.Offset(rowDelta, colDelta) renvoie une nouvelle plage décalée d'autant de lignes et de colonnes par rapport à rng, en conservant la même taille. C'est un déplacement relatif : Offset(1, 0) avance d'une ligne vers le bas, Offset(0, 1) d'une colonne vers la droite, et les nombres négatifs montent ou vont à gauche. Il ne modifie ni ne sélectionne la plage d'origine.

Pourquoi Offset(1, 1) ne renvoie-t-il pas la cellule A1 ?

Parce que les arguments sont des deltas, pas des coordonnées. Offset(1, 1) signifie une ligne vers le bas et une colonne vers la droite depuis la cellule d'ancrage, donc Range("A1").Offset(1, 1) vaut B2. Utilisez Cells(row, col) quand vous voulez une cellule absolue plutôt qu'un pas relatif.

Quelle est la différence entre Offset et Resize ?

Offset déplace une plage sans changer sa taille ; Resize(rows, cols) change la taille depuis la cellule en haut à gauche, sans la déplacer. On les combine souvent — rng.Offset(1).Resize(rng.Rows.Count - 1) saute une ligne d'en-tête en descendant d'une ligne et en rétrécissant d'une.

Comment sauter la ligne d'en-tête avec Offset ?

Utilisez table.Offset(1).Resize(table.Rows.Count - 1). Offset(1) déplace le bloc sous l'en-tête ; Resize rogne la ligne qui dépasse désormais du bas, ne laissant que le corps des données.

VBA Range.Offset est-il identique à la fonction OFFSET de la feuille de calcul ?

Non. Range.Offset est une méthode VBA qui renvoie un objet Range et n'est pas volatile. La fonction de feuille OFFSET() vit dans une cellule, est volatile (elle se recalcule sans cesse) et renvoie une valeur ou une référence pour les formules. Utilisez la méthode dans les macros ; réservez la fonction aux références vivantes dans les formules.

Testé dans

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

Guides associés : VBA Last Row · VBA UsedRange contre CurrentRegion · VBA Range · Fonction OFFSET (feuille de calcul)