Voir le flux RSS

Pierre Fauconnier

VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée!

Noter ce billet
par , 12/01/2020 à 23h11 (168 Affichages)
Salut.

Parfois, sur les forums, on voit une notation qui peut paraître étrange aux "non initiés" (ceux qui ne savent pas, les ploucs, quoi)... En effet, la documentation de Microsoft nous enseigne qu'il y a deux syntaxes pour manipuler un objet Range: Range("a1").Value = 45 ou [a1].Value = 45...

Wouah, on a gagné 1/10 de seconde en saisissant [] au lieu de Range(""). Quelle superbe prouesse, quel gain de temps .

Tiens, au fait, remarquez qu'avec la notation raccourcie, il nous manque l'aide à la saisie. En effet, la notation classique nous propose les méthodes et propriétés du range, alors que la notation raccourcie ne nous aide pas du tout...

Nom : 2020-01-12_205724.png
Affichages : 48
Taille : 3,2 Ko

Nom : 2020-01-12_205803.png
Affichages : 45
Taille : 413 octets

Bah, les "initiés" (pas les simples ploucs, donc) vous diront que vous n'avez qu'à connaître vos méthodes et propriétés

Puisqu'on en parle, savez-vous pourquoi l'éditeur ne vous propose rien derrière la notation raccourcie? C'est tout simplement parce que, lors de la rédaction du code, l'éditeur ne sait pas ce qu'il y a dans les crochets (Tiens je me demande si les "initiés" savent ça). Le contenu de ceux-ci sera évalué (retenez ce mot) uniquement à l'exécution. En effet, il peut y avoir beaucoup de choses à l'intérieur des crochets...

Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Sub Test()
  Dim a3 As String
 
  a3 = "Au revoir"
  Debug.Print "1: " & [a1]
  Debug.Print "2: " & ["a1"]
  Debug.Print "3: " & [a1].Value
  Debug.Print "4: " & [a1].Address
  Debug.Print "5: " & [bonjour] ' formule nommée pointant vers A1... de la feuille active
  Debug.Print "6: " & [bonjour].Address
  Debug.Print "7: " & ["bonjour"]
  Debug.Print "8: " & [a2]
  Debug.Print "9: " & [a3]
  Debug.Print "9: " & [a1:j1].Columns.Count
  Debug.Print "10: " & [a1:j1].Column.Count
End Sub
 
Function a2() As String
  a2 = "Bonjour de la fonction a2"
End Function
 
Function a3() As Boolean
  a3 = True
End Function
Sub Test2()
  Dim a3 As String
End Sub

Voici l'exécution de ce code:
Nom : 2020-01-12_214223.png
Affichages : 45
Taille : 78,6 Ko

Aie Aie Aie... La ligne 11 pose un problème... On a oublié le "s" à ColumnS... Pourtant, avec la notation classique, la tentative d'exécution (ou la compilation du code) indique de suite qu'il y a une erreur, là où la notation raccourcie ne bloque qu'à l'exécution...
Nom : 2020-01-12_215139.png
Affichages : 46
Taille : 9,5 Ko

Dans l'exemple suivant, on remarque que la variable locale est prioritaire sur la fonction du module.
Nom : 2020-01-13_200302.png
Affichages : 31
Taille : 4,9 Ko

On remarque donc plusieurs choses:
  • La notation raccourcie ne pointe pas systématiquement vers une cellule ou une plage... Elle propose à VBA d'évaluer ce qu'il y a entre les crochets et de choisir à votre place ce qui semble être la valeur attendue. Ce sera un objet Range, l'évaluation d'une fonction, voire d'une variable, comme dans l'exemple ci-dessus. En fait, à l'exécution, VBA va chercher la notion qu'il manipule dans ce cas "au plus près de la ligne exécutée": variable locale, variable ou fonction de module, variable ou fonction d'un autre module, puis seulement dans Excel;
  • Les fonctions sont prioritaires sur les références de plages et de cellules (voir le test 8);
  • Les variables locales sont prioritaires sur les fonctions (voir le test 9);
  • La valeur entre crochets n'étant évaluée qu'à l'exécution, on se prive de la vérification du code que la compilation permet lorsque l'on utilise la notation classique;
  • La notation raccourcie impose l'adressage en hard coding car il est impossible de reconstituer l'adresse ou le nom de la plage/Cellule à l'intérieur des crochets.




Cette évaluation, possible uniquement à l'exécution, porte un nom : Late Binding (Liaison tardive). Et le Late Binding s'oppose au Early Binding (Liaison anticipée). La liaison anticipée permet à VBA de connaître (et de vérifier) le type de la donnée manipulée lors de la compilation, c'est-à-dire AVANT l'exécution, et donc de prévenir les problèmes qui pourraient se poser lorsque l'on assigne une valeur d'un mauvais type à une variable typée. La liaison tardive correspond à ne pas typer la variable. C'est un peu comme si au lieu de typer vos variables As Double, As String, As Range, vous les déclariez As Variant, voire même que vous omettiez le As Variant qui peut être implicite comme dans la ligne Dim A As String, B, C As Variant, D As Date ou B et C sont des Variant.

Or, la communauté des développeurs (pas les "initiés", donc, mais les professionnels du développement VBA) s'accorde pour préférer un typage explicite des variables, afin de limiter les erreurs à l'exécution. L'utilisation de la syntaxe raccourcie [A1] n'est donc, vraiment pas, une bonne pratique et ne devrait jamais figurer dans du code professionnel.

Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Viadeo Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Twitter Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Google Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Facebook Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Digg Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Delicious Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog MySpace Envoyer le billet « VBA-Excel: Notation raccourcie d'une plage, une fausse bonne idée! » dans le blog Yahoo

Commentaires

  1. Avatar de Qwazerty
    • |
    • permalink
    Salut Pierre

    C'est une notion qui me semble essentielle.
    D'ailleurs la notation range("A1") est bien souvent trop juste également à mon gout et devrait être accompagnée à minima de la feuille si on utilise le CodeName et au mieux de l'ensemble Classeur.Feuille.Range.

    Je vois très souvent des codes proposés sur les forums qui négligent cette aspect là... et bien souvent ces mêmes codes sont mal structurés, car souvent issu de l'enregistreur, provoquant des lenteurs d'exécution.
    L'ensemble des deux (absence d'antécédent et lenteur) laisse tout loisir à l'utilisateur de changer de feuille voir de classeur durant l'exécution du code...
    Là où ThisWorkbook.Worksheet("Feuil1").Range("A1").Value = "Test" fait le boulot sans histoire, Range("A1").Value = "Test" met un beau bor*el dans la feuille et/ou le classeur passé(e) au premier plan.

    VB est très verbeux, les gens veulent souvent s'épargner du code ou du moins alléger leur code mais je pense que c'est bien souvent un mauvaise idée. (je passe sur l'utilisation des ":" pour tout assembler sur une ligne)
    Il est préférable, toujours à mon avis, d'utiliser une structure With ... End With ou encore utiliser une variable pour pointer la feuille ou le range sur lequel on veut travailler, on allège ainsi le code sans perdre en précision et sans prendre le risque de massacrer une autre feuille.
    Sachant qu'il n'est pas possible d'utiliser Ctrl+Z pour rattraper les dégâts et imaginez si en plus la macro fait un point de sauvegarde du classeur actif.....

    Je te souhaite une bonne soirée
    ++
    Qwaz