I. Introduction▲
Le déplacement au sein d'une feuille de calcul Excel est l'opération la plus courante lors de l'écriture ou de la lecture de données. Pour ce faire, on utilise l'objet Range.
L'optimisation du code passe nécessairement par une bonne compréhension des techniques présentées dans les chapitres qui suivent.
II. Style de référence A1▲
II-A. Présentation et limitation▲
Sous Excel, l'adresse d'une cellule est donnée par l'indice de la colonne et de la ligne. C'est la référence de la cellule. Il existe deux styles de référence sous Excel, que l'on nomme couramment A1 et R1C1 (ou L1C1 en français).
Dans le style A1, le premier indice correspond à l'indice des colonnes et est donné à l'aide de lettre de l'alphabet (A : première colonne, B : deuxième colonne, C : troisième colonne…). Lorsque l'on dépasse l'indice Z pour les colonnes, la notation Excel double alors la lettre (AA, AB, AC…). Le second indice donne le numéro de la ligne.
Avec le style R1C1, les indices des lignes et des colonnes sont donnés sous forme numérique exactement comme pour une matrice sous MATLAB. C'est donc ce style de référence qu'il nous faudrait privilégier pour transférer des données entre Excel et MATLAB.
Malheureusement, l'utilisation du style R1C1 n'est pas autorisée en argument de l'objet Range sous VBA. Le code suivant ne fonctionne donc pas sous MATLAB :
range = Excel.ActiveSheet.Range('R4C5'
);
Error using Interface.000208D8_0000_0000_C000_000000000046/Range
Error: Object returned error code: 0x800A03EC
Il existe heureusement des outils VBA qui vont nous permettre de contourner cette limitation.
II-B. Écriture « en dur » des plages▲
Pour obtenir une plage ne contenant qu'une seule cellule, on passe simplement son adresse à l'objet Range :
range = Excel.ActiveSheet.Range('B2'
);
La variable range contient désormais un objet Range qui peut être utilisé dans le reste du code.
Pour récupérer l'adresse de la cellule, on utilise la propriété Address de l'objet Range :
>> range = Excel.ActiveSheet.Range('B2'
);
>> range.Address
ans =
$B$2
Pour obtenir une plage contenant plusieurs cellules contiguës, on passe les adresses des cellules extrêmes à l'objet Range :
range = Excel.ActiveSheet.Range('A3:C6'
);
La variable range contient désormais l'adresse de la plage de cellules contiguës allant de A3 à C6.
L'objet Range accepte aussi en argument deux objets Range pour sélectionner une plage de cellules contiguës.
La syntaxe VBA est la suivante :
expression .Range
(
cell1, cell2)
Où cell1 et cell2 sont deux objets Range avec les adresses des cellules extrêmes.
L'exemple précédent aurait donc théoriquement pu s'écrire :
r(1) = Excel.ActiveSheet.Range('A3'
);
r(2) = Excel.ActiveSheet.Range('C6'
);
range = Excel.ActiveSheet.Range(r(1),r(2));
Malheureusement, cette commande ne fonctionne pas et renvoie un message d'erreur :
Error using Interface.000208D8_0000_0000_C000_000000000046/Range
Error: Object returned error code: 0x800A03EC
Il faut donc passer par une syntaxe particulière en utilisant la méthode get de MATLAB :
r(1) = Excel.ActiveSheet.Range('A3'
);
r(2) = Excel.ActiveSheet.Range('C6'
);
range = get(Excel.ActiveSheet,'Range'
,r(1),r(2));
ou encore :
range = Excel.ActiveSheet.get('Range'
,r(1),r(2));
II-C. Écriture dynamique des plages▲
Bien que les valeurs puissent être codées en dur sous MATLAB, il est plus souple de pouvoir écrire les plages de façon dynamique, généralement en fonction d'indices dans des boucles for-end.
On peut alors utiliser la fonction sprintf pour écrire les plages sous la forme d'une chaîne de caractères.
Pour une cellule seule, on utilise le modèle suivant :
range = sprintf('%c%d'
,'A'
+m,i);
où m et i sont des valeurs numériques entières telles que :
- m : nombre de colonnes de décalage par rapport à A (0 pour A, 1 pour B, 2 pour C…) ;
- i : numéro de la ligne.
Par exemple pour obtenir l'adresse de la cellule C4 :
>> range = sprintf('%c%d'
,'A'
+2,4)
range =
C4
Le code MATLAB suivant sélectionne la cellule C4 de la feuille active :
range = sprintf('%c%d'
,'A'
+2,4);
Excel.ActiveSheet.Range(range).Select
Le résultat est montré sur la figure suivante :
Pour une plage de cellules contiguës, on utilise le modèle suivant :
range = sprintf('%c%d:%c%d'
,'A'
+m,i,'A'
+n,j);
où m, n, i et j sont des valeurs numériques entières telles que :
- m : nombre de colonnes de décalage de la première cellule par rapport à A (0 pour A, 1 pour B, 2 pour C…) ;
- n : nombre de colonnes de décalage de la dernière cellule par rapport à A (0 pour A, 1 pour B, 2 pour C…) ;
- i : numéro de la ligne de la première cellule ;
- j : numéro de la ligne de la dernière cellule ;
Par exemple pour obtenir la plage de cellules B3:C6 :
>> range = sprintf('%c%d:%c%d'
,'A'
+1,3,'A'
+2,6)
range =
B3:C6
Le code MATLAB suivant sélectionne la plage de cellules B3:C6 de la feuille active :
range = sprintf('%c%d:%c%d'
,'A'
+1,3,'A'
+2,6)
Excel.ActiveSheet.Range(range).Select
Le résultat est montré sur la figure suivante:
Ces méthodes ont néanmoins le désavantage de devoir gérer la numérotation des colonnes lorsque les indices correspondants dépassent 26 (la lettre Z).
Comme nous l'avons vu en introduction, il faut alors doubler la lettre : AA1, AB1… Plusieurs contributions MATLAB existent sur le File Exchange pour vous aider à faire cette conversion.
Vous pouvez aussi utiliser la commande suivante pour convertir un indice de colonne N en notation A1 :
C = char([floor(N-1)/26+64 rem(N-1,26)+65]);
Par exemple, pour obtenir l'indice de la colonne qui suit Z :
>> N = 27;
>> C = char([floor(N-1)/26+64 rem(N-1,26)+65])
C =
AA
Cette astuce limite néanmoins les indices de colonne à ZZ.
III. Quelques propriétés de l'objet Range▲
III-A. La propriété Resize▲
La propriété Resize de l'objet Range permet de redimensionner une plage de cellules. Elle renvoie un objet Range. La syntaxe VBA de cette propriété est la suivante :
expression .Resize
(
RowSize, ColumnSize)
où RowSize et ColumnSize sont des valeurs numériques entières telles que :
- RowSize : nombre de lignes de la nouvelle plage ;
- ColumnSize : nombre de colonnes de la nouvelle plage.
On peut donc très facilement définir une plage de cellule en utilisant l'adresse de la cellule située dans le coin supérieur gauche et donnant les dimensions de la plage.
Par exemple, pour sélectionner la plage B3:C6, on peut simplement sélectionner la cellule B3 et utiliser la propriété Resize en mettant Rowsize à 2 et ColumnSize à 3.
Malheureusement, MATLAB n'accepte pas le modèle de syntaxe de VBA.
La commande suivante ne fonctionne pas :
>> range = Excel.ActiveSheet.Range('B3'
).Resize(3,2);
Index exceeds matrix dimensions.
Il faut alors utiliser la syntaxe suivante :
range = get(Excel.ActiveSheet.Range('B3'
),'Resize'
,3,2);
ou encore:
range = Excel.ActiveSheet.Range('B3'
).get('Resize'
,3,2);
Le résultat est montré sur la figure suivante :
III-B. La propriété Cells▲
Il est possible d'utiliser la propriété Cells d'un objet Range. Cette propriété renvoie un objet Range.
Voici la syntaxe VBA de cette propriété:
expression .Cells( m, n)
où expression est un objet Range contenant l'adresse d'une cellule de référence et avec :
- m : le numéro de la ligne de l'adresse de la cellule à partir de la cellule de référence ;
- n : le numéro de la colonne de l'adresse de la cellule à partir de la cellule de référence.
Par exemple, pour sélectionner la cellule C4 à partir de la cellule A1 :
>> range = Excel.ActiveSheet.Range('A1'
).get('Cells'
, 4, 3);
>> range.Address
ans =
$C$4
Il est possible de sélectionner la même cellule en changeant la cellule de référence et par conséquent les valeurs numériques.
Les lignes de code suivantes sélectionnent toute la même cellule C4 :
>> Excel.ActiveSheet.Range('B1'
).get('Cells'
, 4, 2).Address
ans =
$C$4
>> Excel.ActiveSheet.Range('C3'
).get('Cells'
, 2, 1).Address
ans =
$C$4
>> Excel.ActiveSheet.Range('D4'
).get('Cells'
, 1, 0).Address
ans =
$C$4
>> Excel.ActiveSheet.Range('F8'
).get('Cells'
, -3, -2).Address
ans =
$C$4
Il est possible de simplifier l'écriture si la cellule de référence est la cellule A1. Dans ce cas, la syntaxe devient :
range = Excel.ActiveSheet.get('Cells'
, 4, 3);
Pour obtenir une plage de cellules en référence R1C1, on procède comme ceci :
a = Excel.ActiveSheet.Range('A1'
).get('Cells'
, m1, n1);
b = Excel.ActiveSheet.Range('A1'
).get('Cells'
, m2, n2);
Excel.ActiveSheet.Range('A1'
).get('Range'
,a,b);
Avec:
- m1 : le numéro de la ligne de l'adresse de la première cellule de la plage ;
- n1 : le numéro de la colonne de l'adresse de la première cellule de la plage ;
- m2 : le numéro de la ligne de l'adresse de la dernière cellule de la plage ;
- n2 : le numéro de la colonne de l'adresse de la dernière cellule de la plage.
Par exemple, pour sélectionner les cellules de la plage B3:C6, on fait :
r(1) = Excel.ActiveSheet.Range('A1'
).get('Cells'
, 3, 2);
r(2) = Excel.ActiveSheet.Range('A1'
).get('Cells'
, 6, 3);
Excel.ActiveSheet.Range('A1'
).get('Range'
,r(1),r(2)).Select;
Ce qui donne bien:
On peut sélectionner l'ensemble des cellules d'une feuille en ne passant aucun argument à la propriété Cells.
Dans le code suivant, toutes les cellules de la feuille courante sont sélectionnées :
Excel.ActiveSheet.Cells
III-C. La propriété CurrentRegion▲
Pour sélectionner une plage de cellules contiguës à partir d'une seule adresse de cellules contenues dans cette plage, on peut se servir de la propriété CurrentRegion de l'objet Range.
Prenons l'exemple d'une feuille contenant un carré magique 3x3, comme le montre la figure suivante :
On peut sélectionner toutes les cellules contenant les valeurs en une seule ligne de commande comme ceci :
Excel.ActiveSheet.Range('B3'
).CurrentRegion.Select;
Ce qui donne bien:
La cellule de référence utilisée pour étendre la sélection peut être n'importe laquelle appartenant à la plage. Le code précédent aurait donné le même résultat avec B4, C3 ou D5 à la place de B3.
On aurait donc très bien pu sélectionner les mêmes cellules en faisant :
Excel.ActiveSheet.Range('D5'
).CurrentRegion.Select;
III-D. La propriété End▲
La propriété End renvoie l'adresse d'une cellule à partir d'une cellule de référence selon une direction donnée vers le haut, vers le bas, vers la droite ou vers la gauche (voir les constantes respectives xlUp, xlDown, xlToRight et XlToLeft de l'énumération XlDirection).
Son comportement dépend du contenu de la cellule de référence sur laquelle elle s'applique.
Si la cellule de référence est vide, la propriété End renvoie l'adresse de la première cellule non vide le long de la direction à partir de la cellule de référence spécifiée.
Dans l'exemple du carré magique, pour atteindre, à partir de la cellule B1, la première cellule non vide (donc B3) vers le bas, on fait :
>> range = Excel.ActiveSheet.Range('B1'
).End('xlDown'
);
>> range.Address
ans =
$B$3
Si la cellule de référence n'est pas vide, la propriété End renvoie l'adresse de la dernière cellule non vide le long de la direction à partir de la cellule de référence spécifiée.
Dans l'exemple du carré magique du chapitre précédent, pour atteindre, à partir de la cellule B3, la dernière cellule se situant sur la même ligne (donc D3), on peut faire :
>> range = Excel.ActiveSheet.Range('B3'
).End('xlToRight'
);
>> range.Address
ans =
$D$3
Il est possible de cumuler les déplacements. Par exemple, pour atteindre, toujours à partir de la cellule B3, la dernière cellule en bas à droite (donc D5), on peut faire :
>> range = Excel.ActiveSheet.Range('B3'
).End('xlToRight'
).End('xlDown'
);
>> range.Address
ans =
$D$5
IV. Les plages de cellules nommées▲
Pour améliorer la lisibilité du code, il est possible d'attribuer un nom à une plage. Il est alors possible d'utiliser ce nom plutôt que les indices de plages.
On donne une valeur à la propriété Name de l'objet Range concerné comme ceci :
Excel.ActiveSheet.Range('B3:D5'
).Name = 'magic'
;
On peut ensuite par exemple sélectionner la plage correspondante en faisant :
Excel.ActiveSheet.Range('magic'
).Select;
Ce qui donne bien :
V. Conclusion▲
Vous connaissez maintenant la plupart des techniques de déplacements au sein d'une feuille de calcul Excel à l'aide de l'objet Range.
L'utilisation des propriétés Resize, Cells, CurrentRegion et End vous permettra d'optimiser vos codes.
L'utilisation des plages nommées est une technique très efficace qu'il ne faut pas avoir peur d'utiliser.
Vous pouvez maintenant poursuivre votre lecture par l'article intitulé Contrôle d'Excel par MATLAB via Automation - Limites qui présente des informations essentielles pour tenir compte des limites de la méthode via Automation ainsi que des différences entre Excel et MATLAB.