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 à 22h11 (555 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 : 246
Taille : 3,2 Ko

Nom : 2020-01-12_205803.png
Affichages : 241
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 . Apparemment, ils sont infoutus de se rendre compte qu'ils doivent donc saisir le code à la main, ce qui fait qu'au final, ils "tapent" souvent plus de code que ce qu'ils ont économisé avec leur syntaxe "d'initié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
Sub Test()
  Dim a3 As String
 
  a3 = "Bonjour de la variable a3"
  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 "10: " & [a1:j1].Columns.Count
  Debug.Print "11: " & [a1:j1].Column.Count
End Sub
 
Function A2() As String
 A2 = "T'as l'bonjour d'A2"
End Function
 
Function a3() As String
  a3 = "T'as l'bonjour d'A3"
End Function

Voici l'exécution de ce code:
Nom : 2020-02-14_055715.png
Affichages : 165
Taille : 10,9 Ko

Aie Aie Aie... La ligne du test 11 pose un problème d'exécution... On a oublié le "s" à Column... Mais comme le VBA ne savait pas ce qu'il allait réellement trouver comme type de données entre les crochets, il n'a planté qu'à l'exécution, c'est-à-dire bien trop tard. Avec la notation classique, le problème serait survenu à la compilation, nous évitant de passer pour un pisseur de code amateur qui ne comprend pas ce qu'il manipule... Je rappelle au passage que c'est une saine pratique de toujours "compiler" le code avant de l'exécuter*.
Nom : 2020-02-14_060116.png
Affichages : 165
Taille : 11,6 Ko


Dans l'exemple de code ci-dessus, on remarque que la variable locale A3 est prioritaire sur la fonction A3, qui sera prioritaire sur la cellule A3, car l'évaluation de ce que le VBA ne connaît pas au départ s'effectue "au plus près" du code qui utilise la variable/fonction/propriété/plage.

Le fait que le VBA ne sache qu'à l'exécution avec quoi il va devoir travailler 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 à des objets correspond à ne pas typer une variable, obligeant le VBA à déterminer le type de ce qu'il manipule à l'exécution, soit trop tard. 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, et de permettre les tests qui doivent être effectués avant une "mise en production", car ce n'est que dans de rares cas qu'il ne sera pas possible de typer les variables/fonctions/objets.


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.



L'utilisation de la syntaxe raccourcie [A1] n'est donc, vraiment pas, une bonne pratique et ne devrait jamais figurer dans du code professionnel.





* Cette "compilation" permet au VBA de vérifier que vous utiliser des variables, fonctions, procédures et propriétés que vous avez définies de manière explicite, que les méthodes et propriétés que vous utilisez avec les objets que vous manipulez existent bien, que les arguments que vous utilisez pour vos procédures, fonctions et propriétés sont cohérents (bon nombre, du bon type et à la bonne place si vous n'utilisez pas les arguments nommés), que vous passez bien en ByVal les arguments que vous ne pouvez pas passer en ByRef, tels qu'un élément isolé de tableau, par exemple... Vous pouvez compiler votre code avant exécution via le menu Débogage ou par un bouton à placer sur une barre d'outils. Notons au passage que cette compilation n'en est pas vraiment une (le code sera tout de même interprété lors de l'exécution) et qu'elle réinitialise les variables et objets de tous les modules du projet.

Nom : 2020-02-14_060348.png
Affichages : 163
Taille : 14,0 Ko

Nom : 2020-02-14_060404.png
Affichages : 162
Taille : 5,0 Ko

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