VISUAL BASIC & EXCEL

TP 1

Calendrier avec affichage des fêtes mobiles


L'objectif de ce premier TP est de se familiariser avec le matériel et le logiciel que nous utiliserons cette année. Ces lignes sont écrites sur un PC et les exercices que nous feront seront toujours préparés sur Excel 97 pour PC. La version que vous utilisez est référencée Excel 98 (qui n'existe que sur Mac). Cela dit, il ne devrait pas y avoir beaucoup de différences entre les explications et la réalité de votre écran.

Voici comment se présente le logiciel Excel 97 sur un PC :


Sur cet écran, la résolution est de 600x800 points, mais sur votre Mac, elle peut être différente. Ceci explique que le nombre de lignes ou de colonnes visibles ne soit pas identique.

L'année dernière, vous avez déjà travaillé avec le tableur Excel. Vous avez sans doute appris à manipuler les cellules d'une feuille de calcul grâce à des formules bien choisies. Vous savez sans doute également comment modifier la taille des cellules et leur aspect (bordures, trames de fond). Vous avez aussi appris à gérer les polices de caractères ainsi que les commandes du menu Edition (copier, couper coller). De plus, un document Excel peut comporter plusieurs feuilles de calcul : ces feuilles sont accessibles en cliquant sur les onglets en bas de l'écran.

Il s'agit cette année d'aller plus loin en ajoutant des commandes programmées par vous mêmes. Ces commandes seront capables d'exécuter des suites d'instructions plus ou moins complexes, avec des boucles, des structures conditionnelles, des appels à d'autres commandes. Pour réaliser ces commandes, nous utiliserons le langage de programmation intégré à Excel : Visual Basic.

1. Exemple de programme écrit en VBA (Visual Basic pour Application)

Ce premier programme va nous permettre de réaliser un calendrier. Lorsque vous l'aurez tapé et essayé, vous pourrez le modifier à votre goût.
Choisir, la commande Outils/Macro/Vusual Basic Editor (le raccourci clavier sur PC est Alt-F11). On obtient alors l'écran suivant :

Effectuez un double-clic, à gauche, sur Feuil1(Feuil1), ou choisir la commande Affichage/Code afin d'obtenir une page blanche dans laquelle nous pourrons écrire notre programme. Ce programme sera associé à la feuille de calcul nommée Feuil1 (dont on pourra éventuellement changer le nom).
Tapez le programme ci-dessous. Les lignes qui commencent par des apostrophes ( ' ), sont des commentaires. La présence de commentaires n'est pas obligatoire mais recommandée. Cela permet de mieux comprendre le texte du programme (si quelqu'un d'autre veut le modifier par exemple...)
Remarques préliminaires : Visual Basic apporte une aide importante pendant la saisie. Ainsi, les mots du langage basic (comme sub, InputBox, For, BorderAround ) seront tapés entièrement en minuscules et, s'il n'y a pas d'erreur de frappe, les arguments éventuels seront proposés sous le curseur. Au moment du passage à la ligne, si tout est correct, des majuscules se mettent automatiquement. Bien entendu, comme dans tout éditeur de texte, vous pouvez utiliser les commandes habituelles du menu Edition (couper, copier, coller). Par ailleurs, certains mots s'affichent en couleur (les commentaires sont en vert, les mots-clés sont en bleu...).
'Macro Calendrier
'Réalisée par P. Rabiller le 04/02/2002
Dim Année 'Déclaration d'une variable "Année" utilisable dans tout le programme
Sub Calendrier() 'programme principal
   SaisirAnnée
   RéglerLargeurDesColonnes
   AfficherTitre
   AfficherNomsMois
   AfficherJours
End Sub
Sub SaisirAnnée() 'demande à l'utilisateur de taper une année
   Année = InputBox("Tapez l'année :", "Calendrier")
End Sub
Sub RéglerLargeurDesColonnes() 'chaque mois occupera 3 colonnes de largeurs 2, 2 et 15
   For c = 1 To 12
      Columns(3 * c - 2).ColumnWidth = 2
      Columns(3 * c - 1).ColumnWidth = 2
      Columns(3 * c).ColumnWidth = 15
   Next c
End Sub
Sub AfficherTitre()
   For semestre = 1 To 2 'le calendrier sera imprimé sur 2 pages, une par semestre
      Cells(1, 18 * semestre - 17) = "Année " & Année
      Range(Cells(1, 18 * semestre - 17), Cells(1, 18 * semestre)).Select
      With Selection
         .HorizontalAlignment = xlHAlignCenterAcrossSelection
         .VerticalAlignment = xlVAlignCenter
         .Font.Name = Arial
         .Font.Size = 20
         .Font.Bold = True
         .BorderAround Weight:=xlThick
         .Interior.ColorIndex = 4
      End With
   Next semestre
End Sub
Sub AfficherNomsMois() 'affichage des noms des 12 mois
   For m = 1 To 12
      ch = Format("1/" & m, "dd mmmm")
      Cells(2, 3 * m - 2) = Mid(ch, 4, 10)
      Range(Cells(2, 3 * m - 2), Cells(2, 3 * m)).Select
      With Selection
         .HorizontalAlignment = xlHAlignCenterAcrossSelection
         .VerticalAlignment = xlVAlignCenter
         .Font.Name = Arial
         .Font.Size = 14
         .Font.Bold = True
         .BorderAround Weight:=xlThick
         .Interior.ColorIndex = 15
      End With
   Next m
End Sub
Sub AfficherJours() 'affichage des jours : 1ère lettre + rang du jour
   For m = 1 To 12
      For j = 1 To 31
         ch = Format(j & "/" & m & "/" & Année, "dddd")
         If IsDate(j & "/" & m & "/" & Année) Then
            Cells(2 + j, 3 * m - 2) = Mid(ch, 1, 1)
            Cells(2 + j, 3 * m - 1) = j
         End If
      Next
j
      Range(Cells(3, 3 * m - 2), Cells(33, 3 * m)).BorderAround Weight:=xlThick
   Next m
End Sub
Dès que le programme est tapé, il est prudent d'enregistrer le travail sous le nom Calendrier1 par exemple (les versions suivantes seront nommées calendrier 2, calendrier 3 etc...)
Pour exécuter notre programme, il faut retourner à la feuille de calcul à l'aide de la commande Affichage/Objet ou Affichage/Microsoft Excel ou Alt-F11 puis choisir la commande Outils/Macro/Macros qui fait apparaître la fenêtre ci-contre :
Il suffit alors de choisir la macro " Feuil1.calendrier " et de cliquer sur le bouton " exécuter ".

Modifier ensuite, les largeurs des colonnes, au besoin, afin de permettre une impression sur 2 pages en format paysage. Pour cela, utilisez la commande Fichier/Mise en page puis cliquez sur l'option paysage. Pour savoir si les largeurs sont bonnes, utiliser la commande Affichage/Aperçu des sauts de page. Dès que le calendrier est au point, enregistrez-le à nouveau . Ne pas lancer l'impression tout de suite, mais attendre d'avoir fait les modifications des paragraphes 3.1 et 3.2 plus loin...

2. Analyse du programme calendrier

L'exemple que nous avons tapé montre déjà quelques règles de programmation et de syntaxe que nous devrons respecter. Certaines règles sont obligatoires pour que la macro fonctionne, d'autres sont facultatives mais fortement recommandées. Parmi ces dernières, on peut citer :

Dim Année
Cette instruction permet de déclarer la variable globale Année. Lorsqu'une même variable doit être utilisée dans plusieurs procédures, il est obligatoire de la déclarer en tête de programme. Faute de déclaration globale, chaque procédure utilisant la variable Année considérerait celle-ci comme une variable locale indépendante.
Sub Calendrier()
C'est la procédure principale du programme. Elle appelle successivement 5 procédures décrites plus loin dans le programme. C'est celà la décomposition en sous-tâches.
Sub SaisirAnnée()
C'est une procédure très courte qui fait appel à une boîte de dialogue standard portant le titre "Calendrier" et la question : "Taper l'année :".
Sub RéglerLargeurDesColonnes()
Dans cette procédure, il faut sans doute modifier les valeurs affectées aux largeurs en tenant compte de l'environnement Macintosh (encore une fois la macro a été réalisée sur un PC). Comme l'année se compose de 12 mois on utilise une structure Itérative (boucle) de type For ... Next. Pour chacune des valeurs entières de c (de 1 à 12) la valeur 3*c-2 correspond aux colonnes contenant le nom du jour, la valeur 3*c-1 correspond aux colonnes contenant le n° du jour et la valeur 3*c correspond aux colonnes libres. L'objet Columns() peut effectuer plusieurs opérations (appelées Méthodes) et a plusieurs propriétés parmi lesquelles :
Sub AfficherTitre()
Cette procédure affiche le titre : Année nnnn dans les cellules A1 (cellule(1,1)) et S1 (cellule(1,19)). Pour obtenir le titre complet Année 2002 (par exemple), on "ajoute" à la chaîne Année, la variable Année (telle qu'elle a été saisie dans la procédure SaisirAnnée). Pour coller deux chaînes de caractères l'une à la suite de l'autre, il faut utiliser l'opérateur de concaténation &. Dans cette instruction, la variable Année est considérée comme une chaîne de caractères. Une structure très intéressante est utilisée ici pour simplifier l'écriture : With ... End With. On aurait pu écrire directement :
Selection.HorizontalAlignment = xlHAlignCenterAcrossSelection
Selection.VerticalAlignment = xlVAlignCenter
Selection.Font.Name = Arial
Selection.Font.Size = 20
Selection.Font.Bold = True
Selection.BorderAround Weight:=xlThick
Selection.Interior.ColorIndex = 4
Mais à chaque fois, il faut répéter le mot " selection "...
Sub AfficherNomsMois()
On retrouve dans cette procédure la fonction Format. Cette fonction très puissante, permet de convertir, entre autres, des chaînes dates dans un format particulier. Ici, il s'agit d'obtenir le nom du mois en toutes lettres (mmmm) donc la chaîne "1/1" devient "01/janvier". Il est alors possible d'extraire (fonction Mid) de cette chaîne, les caractères à partir du 4è (1ère lettre du mois). Le fait de préciser 10 caractères à extraire permet d'appliquer la fonction à tous les mois de l'année car aucun nom de mois ne dépasse 10 caractères.

Sub AfficherJours()
Nous retrouvons la fonction Format pour extraire ensuite la première lettre du nom du jour. La fonction la plus intéressante ici est la fonction IsDate. Cette fonction permet de savoir si la chaîne transmise en paramètre peut être comprise comme une date (en tenant compte, même, des années bissextiles). Grâce à cette fonction, on peut remplir de façon automatique tous les mois en tenant compte du nombre de jours de chaque mois.
3. Modifications du programme
3.1. Mise en évidence des week ends.
Le cycle le plus important dans un calendrier est la semaine. Il est intéressant de bien visualiser les semaines. La façon la plus simple consiste à mettre en évidence les samedis et les dimanches. Il suffit de modifier légèrement la procédure AfficherJours en rajoutant, après la ligne :
Cells(2 + j,3 * m-1)=j
le texte suivant :

If (Cells(2 + j, 3 * m - 2) = "s") Or (Cells(2 + j, 3 * m - 2) = "d") Then
   Range(Cells(2 + j, 3 * m - 2), Cells(2 + j, 3 * m)).Select
   Selection.Interior.ColorIndex = 3
End If
3.2. Affichage des fêtes mobiles (calendrier liturgique catholique romain)
L'une des difficultés majeures en matière de calendrier concerne le calcul de la date de Pâques. Celle-ci est fixée le premier dimanche qui suit la première pleine lune du printemps. Le calcul est très compliqué car il doit tenir compte à la fois du calendrier grégorien (basé sur la course de la terre autour du soleil), du cycle lunaire (la lunaison moyenne est de 29,530588 jours) et de la date de l'équinoxe du printemps.
Parmi les méthodes de calcul de la date de Pâques, nous allons utiliser l'algorithme qui a été découvert en 1876 et diffusé par l'astronome Jean Meeus :
Soit A l'année grégorienne (postérieure donc à 1582)
On calcule successivement les nombres suivants :

n : reste de la division de A par 19 (cycle de Méton),
c : quotient entier de la division de A par 100,
u : reste de la division de A par 100,
s : quotient entier de la division de c par 4,
t : reste de la division de c par 4,
p : quotient entier de la division de (c+8) par 25,
q : quotient entier de la division de (c-p+1) par 3,
e : reste de la division de (19n+ c - s - q + 15) par 30,
b : quotient entier de la division de u par 4,
d : reste de la division de u par 4 ,
l : reste de la division de (32 + 2t +2b - e - d) par 7,
h : quotient entier de la division de (n + 11e + 22 l) par 451,
m : quotient entier de la division de (e + l - 17h + 114) par 31,
j : reste de la division de (e + l - 17h + 114) par 31 augmenté de 1.

Lorsqu'on connaît la date de Pâques, on peut facilement en déduire les autres fêtes religieuses liées à Pâques selon le tableau suivant :
Cendres
-46
Mercredi
Carême (1er dimanche de)
-42
Dimanche
Triduum Pascal
-3
Jeudi
-2
Vendredi
-1
Samedi
Pâques
0
Dimanche
Ascension
+39
Jeudi
Pentecôte
+49
Dimanche
Trinité
+56
Dimanche
Fête-Dieu
+63
Dimanche
Sacré-Coeur
+68
Vendredi

Pour traduire tous ces calculs, voici la procédure à ajouter en fin de programme :

Sub AfficherFêtesMobiles()
   n = Année Mod 19
   c = Année \ 100 'taper Alt + / pour obtenir la barre \
   u = Année Mod 100
   s = c \ 4
   t = c Mod 4
   p = (c + 8) \ 25
   q = (c - p + 1) \ 3
   e = (19 * n + c - s - q + 15) Mod 30
   b = u \ 4
   d = u Mod 4
   l = (32 + 2 * t + 2 * b - e - d) Mod 7
   h = (n + 11 * e + 22 * l) \ 451
   k = e + l - 17 * h + 114
   m = k \ 31
   j = k Mod 31 + 1
   Cells(2 + j, 3 * m) = "Pâques"
   ch = Format(j & "/" & m & "/" & Année, "0")
   m = Month(ch - 46)
   j = Day(ch - 46)
   Cells(2 + j, 3 * m) = "Cendres"
   m = Month(ch + 39)
   j = Day(ch + 39)
   Cells(2 + j, 3 * m) = "Ascension"
   m = Month(ch + 49)
   j = Day(ch + 49)
   Cells(2 + j, 3 * m) = "Pentecôte"
   m = Month(ch + 56)
   j = Day(ch + 56)
   Cells(2 + j, 3 * m) = "Trinité"
   m = Month(ch + 63)
   j = Day(ch + 63)
   Cells(2 + j, 3 * m) = "Fête-Dieu"
   m = Month(ch + 68)
   j = Day(ch + 68)
   Cells(2 + j, 3 * m) = "Sacré-Coeur"
End Sub

Il suffit alors de modifier le programme principal comme ceci :

Sub Calendrier() 'programme principal
   SaisirAnnée
   RéglerLargeurDesColonnes
   AfficherTitre
   AfficherNomsMois
   AfficherJours
   AfficherFêtesMobiles
End Sub

3.3. Découpage de l'année en 4 trimestres

Reprendre le programme précédent et le modifier de façon que le calendrier sorte sur 4 pages à raison d'une page par trimestre.
Enregistrer ce nouveau programme sous le nom Calendrier 2.

3.4. Impression sur une seule page.

Reprendre le programme et le modifier de façon que le calendrier complet sorte sur une seule page. Il faudra sans doute revoir la disposition des mois sur la page ...

3.5. Un seul mois choisi par l'utilisateur

Ce programme devra demander à l'utilisateur de choisir non seulement une année mais aussi un mois. L'ordinateur devra afficher seulement le mlois choisi. On pourra l'enregistrer sous le nom Calendrier 3

4. Ajout d'une commande de menu
Il est possible d'ajouter la nouvelle commande dans le menu outil. Il faut procéder de la façon suivante :
- Choisir la commande Outil/Macro
- Choisir la macro Calendrier et cliquer sur le bouton Options...
On obtient alors la fenêtre permettant de préciser ces options :

 

TP suivant >>

Retour au menu