VBA affiche l’échiquier

Accès à une cellule d’Excel représentant une case de l’échiquier : Range, Cells, Set et POO.

Accès à une cellule d’Excel représentant une case de l’échiquier : Range, Cells, Set et POO.


La procédure GuiDisplayBoardAt() d’affichage de l’échiquier dans la feuille Excel a été définie dans la fenêtre d’édition du module ModChess et appelée dans la fenêtre d’Exécution lors de la session précédente. Détaillons les éléments nouveaux de ce code.

Déclaration de GuiDisplayBoardAt()

Comme la liste des paramètres d’entrée est assez imposante, on a utilisé l’opérateur de continuation de ligne "_" en fin de la ligne de déclaration des paramètres d’entrée.

Sub GuiDisplayBoardAt(ByVal isSideWhite As Boolean, ByVal indRow As Integer, _
    ByVal indCol As Integer, ByVal strBoard As String)

On veut pouvoir indiquer l’orientation de l’échiquier, ses coordonnées dans la feuille Excel (d’où le "At" en fin de nom de procédure) et finalement l’emplacement des pièces.

Orientation de l’échiquier

Concernant l’orientation de l’échiquier, on notera en 1er paramètre d’entrée un nouveau type Boolean dont la variable isSideWhite (est-ce qu’on affiche l’échiquier côté des Blancs ?) vaut soit True (les Blancs sont en bas) soit False (les Blancs sont en haut).

ByVal isSideWhite As Boolean

Dans l’article précédent, on a indiqué True comme paramètre de GuiDisplayBoardAt() dans la fenêtre d’Exécution.

Essayez maintenant avec False :

GuiDisplayBoardAt False, rowBoardMain, colBoardMain, BoardBuild()

L’échiquier est orienté pour les Noirs en bas et les Blancs sont en haut. On notera l’inversion dans l’affichage des coordonnées. On ne pouvait donc pas les placer une bonne fois pour toute statiquement (manuellement) sur le bord de l’échiquier. Il faut donc les calculer dynamiquement.

Les coordonnées sur le bord de l’échiquier

isSideWhite est False. Les Blancs sont en haut.

On se situe dans la branche Else du If à l’intérieur de la boucle principale For Next par rangée indRank :

    For indRank = 0 To countRank - 1
        If isSideWhite Then
            Cells(indRow + 1, indRank + indCol) = Chr(ascFileA + indRank)
            Cells(indRow - indRank, indCol - 1) = indRank + 1
        Else
            Cells(indRow + 1, indRank + indCol) = Chr(ascFileH - indRank)
            Cells(indRow + indRank - 7, indCol - 1) = indRank + 1
        End If

Les cellules de la feuille Excel sont accessibles via le tableau Cells(rangée, colonne) qui est automatiquement défini par Excel VBA, c-a-d qu’on n’a pas à le déclarer. C’est un tableau qui accepte aussi bien la String Chr(ascFileA + indRank) qu’un Byte indRank + 1.

On a déjà expérimenté les expressions de droite pour le calcul des noms de la colonne et de la rangée dans Coordonnées sur l’échiquier (2eme partie) et la constante ascFileA dans Tout l’échiquier dans une chaîne.

L’orientation de l’échiquier indiqué via le booléen isSideWhite a un impact direct sur la rangée de la cellule concernant l’affichage dans un sens ou dans le sens opposé des coordonnées sur le bord de l’échiquier.

Parcours de l’échiquier au niveau de la cellule

Dans la rangée courante indRank, on parcourt chaque colonne grâce à la boucle secondaire For Next d’indice indFile.

On veut rendre le code générique concernant la couleur blanche ou noire de la case et son contenu (vide ou avec une pièce). Générique veut dire ici indépendant de l’orientation de l’échiquier. Il faut donc manipuler la cellule dans une variable indépendamment des coordonnées de colonne et de rangée. On a déclaré dans la liste des variables locales la cellule de la case courante : cellSqr As Range.

Dim indRank As Byte, indFile As Byte, cellSqr As Range, isSqrWhite As Boolean

Range est un type typique du GUI d’Excel VBA que l’on ne rencontrera guère dans Powerpoint ou Word. En première approche pour simplifier, on assimilera un Range à une seule cellule, d’où le nom de la variable cellSqr (square of cell) qui reprend en tête le nom du tableau Cells(row, col) mais au singulier. On gère l’échiquier cellule par cellule c-a-d case par case.


Ces petits riens


Par Catherine Deneuve & Serge Gainsbourg

Tant que cellSqr n’est pas initialisée, sa valeur n’est ni zéro ni la chaîne vide ’’’’ mais Nothing.

C’est une grande différence par rapport au type de base Integer ou String où un algorithme générera toujours un résultat parfois inattendu si la variable n’est pas initialisée.

Si on appelle par mégarde une méthode d’un objet VBA non encore initialisé, on est gentiment rappelé à l’ordre (en langage C ou C++, l’équivalent serait un pointeur nul qui planterait carrément le programme et on pourrait tout perdre si on n’a pas sauvegardé). On ne peut rien faire avec un objet dont la valeur est Nothing à l’exception de tester s’il est Nothing. Toute autre tentative ne vaut rien.

La variable cellSqr non encore initialisée vaut Nothing !

Avec un point d’arrêt (breakpoint) sur la première ligne de GuiDisplayBoardAt(), la variable cellSqr n’est pas encore initialisée avec une cellule de l’échiquier. On peut tester si sa valeur est (is) Nothing avec l’opérateur spécialisé "Is" qui apparaît généralement dans une condition d’If.

Dans la fenêtre d’Exécution, on a appelé la procédure d’affichage de l’échiquier. Si et seulement si cette procédure est stoppée sur un point d’arrêt à l’intérieur de GuiDisplayBoardAt(), on peut utiliser la variable cellSqr dans la fenêtre d’Exécution sinon elle ne sera pas connue car elle est locale à la procédure. Au moment où on tape cellSqr dans la fenêtre d’Exécution, la procédure GuiDisplayBoardAt() ne doit pas être terminée dans le débogueur.

? cellSqr Is Nothing

True

Notez que pour comparer un objet on ne peut pas utiliser le test d’égalité cellSqr = Nothing.


Revenons au corps de la boucle For Next par colonne indFile.

        For indFile = 0 To countFile - 1
            If isSideWhite Then
                Set cellSqr = Cells(indRow - indRank, indCol + indFile)
            Else
                Set cellSqr = Cells(indRow + indRank - 7, indCol - indFile + 7)
            End If

On affecte l’objet cellSqr classiquement avec l’opérateur d’affectation "=". Cependant comme il s’agit d’une affectation d’objet, il faut préfixer l’instruction par le mot-clé Set.
C’est une erreur classique d’oublier Set pour affecter un objet en VBA.

Suivant l’orientation de l’échiquier la cellule courante nécessite un calcul de son index de rangée et de son index de colonne. cellSqr est une des cases de l’échiquier, référencée dans Excel via le tableau d’objets Cells(rangée, colonne) de type Range.

Sélection de la case courante

Pour changer la couleur de fond de la case de l’échiquier, il faut sélectionner par programmation la cellule correspondante comme si l’utilisateur avait cliqué dessus à la souris.

            cellSqr.Select

Dans le premier article Initiation à Excel VBA : la fenêtre Exécution, on a déjà rencontré cette syntaxe du point séparateur "." entre l’objet Debug et sa méthode Print dans Debug.Print. Une méthode c’est la même chose qu’une Sub ou une Function mais appartenant à un objet.

Dans les dizaines de procédures et fonctions d’un programme d’Echecs, comment savoir que BoardBuild() et BoardDisplay() sont relatives à la même famille de gestion de l’échiquier ? On dit à la même classe. Tout ce que l’on sait, c’est que ces fonctions commencent alphabétiquement par le même mot "Board" grâce à l’inversion des deux mots par rapport au langage naturel : Build the Board.

On préférerait avoir un objet Board exposant les méthodes Build() et Display() via Board.Build et Board.Display. C’est juste une question de ponctuation, de "." entre les mots et cela fait toute la différence entre une approche classique procédurale et la POO (Programmation Orientée Objet) qui regroupe les méthodes en famille, en classe.

En pratique on obtient la liste des méthodes qu’un objet expose au moment de saisir le "." séparateur entre le nom de l’objet et la méthode dont on cherche le nom. La liste des méthodes apparaît en bulle d’aide grâce à l’autocomplétion qui aide également à la saisie d’éventuels paramètres en suggérant leurs types.

Dans l’éditeur VBA, à l’intérieur de la procédure où elle est déclarée, si on tape cellSqr suivi d’un ".", on verra en bulle d’aide les nombreuses méthodes que l’objet de type Range peut supporter. On s’intéresse ici à la sélection de la cellule grâce à la méthode Select.

Bulle d'aide sur les méthodes de l'objet cellSqr dans la fenêtre d'Exécution immédiate

On a mis un point d’arrêt (breakpoint) dans le For Next le plus imbriqué de la procédure GuiDisplayBoardAt(). La bulle d’aide sur saisie du "." séparateur marchera également dans la fenêtre d’Exécution à condition que cellSqr soit initialisée, c-a-d affectée via Set (voir le précédent chapitre).

? Not cellSqr Is Nothing

True

OK, l’objet cellSqr est valide (Not cellSqr Is Nothing signifie différent de Nothing), on peut afficher une de ses propriétés :

? cellSqr.Row

2

C’est la première rangée (indRank = 0 dans la fenêtres des Variables Locales du débogueur) des pièces des Blancs en haut de l’échiquier car lors de l’appel de GuiDisplayBoardAt() , le 1er paramètre isSideWhite est False.

  • Le couple de coordonnées (indRank, indFile) est du domaine de la représentation interne de l’échiquier de 0 à 7.
  • Le couple de coordonnées (indRow, indCol) est du domaine du GUI entre R2C14 et R9C21.

Dans le prochain article, on abordera comment le code change la couleur de fond (blanche ou noire) d’une case et comment on place une pièce sur une case.

Explorer l’algorithme pas à pas

L’algorithme étant d’un niveau plus complexe que les fonctions analysées jusqu’à maintenant, il est fortement recommandé de parcourir pas à pas au moins tout le calcul d’une rangée complète c-a-d toutes ses colonnes dans le débogueur.

Une fois être passé dans les instructions de la boucle des colonnes pour la 1ere rangée, entraînez-vous à savoir sauter le calcul de plusieurs rangées selon l’emplacement du point d’arrêt puis sortez par un Step Out.


Précédent : Echiquier graphique dans Excel

Suivant : Couleur d’une case en VBA

Posté le 13 juillet 2011 par Matt