Plan du cours
VBA, historique Lenvironnement de dveloppement sous Excel Les feuilles Les contrles La programmation en VBA La structure alternative La structure rptitive Le tableau
1/138
Plan du cours
L'enregistrement Le traitement d'erreur Lutilisation de DLLs Le concept de classe
2/138
VBA, historique
VBA acronyme de Visual Basic for Applications
fait partie de la famille Visual Basic (Basic acronyme de Beginners All-purpose Symbolic Instruction Code cr partir de 1963)
Visual Basic (pour Windows) a t lanc en 1991 VB est un langage de programmation gnral permettant de crer facilement et rapidement des applications Windows
3/138
VBA, historique
VBA
a t lanc en 1993 pour remplacer le langage macro utilis jusqualors dans Excel permet la cration dapplications hberges dans lapplication hte depuis 1997, les programmes de Office utilisent VBA comme langage de programmation (except Outlook) et VBA est vendu pour tre intgr dans des applications non Microsoft
4/138
VBA, historique
avantages
cest un langage de programmation complet intgrant tous les concepts usuels
types, variables, fonctions, etc.
5/138
VBA, historique
avantages
il est conu pour crer de manire visuelle des programmes ayant une interface utilisateur graphique il supporte la programmation vnementielle il est extensible via lintgration dadd-ins et/ou de composants Active-X dvelopps en VB ou autre
6/138
VBA, historique
avantages
langage de programmation puissant prsent dans toutes les applications Office
7/138
VBA, historique
dsavantages
cest un dialecte assez touffu malais apprhender dans sa totalit (plus de 1000 mots-cls) le code est toujours interprt (relativement lent) le langage nest pas standardis, il est la proprit de Microsoft qui peut le faire voluer ou stagner sa guise ! il est nest pas trs facile de diffuser ses programmes sur dautres machines
8/138
9/138
10/138
fentre projet
11/138
12/138
13/138
14/138
15/138
16/138
17/138
Les feuilles
une feuille
est un cadre dans lequel les lments dune application VBA peuvent tre disposs a des proprits peut ragir des vnements
18/138
Les feuilles
une feuille de calcul Excel
19/138
Les feuilles
une feuille utilisateur vierge que le programmeur peut dfinir sa guise notamment laide des contrles
le menu Toolbox visualisant la palette des contrles usuels souvre automatiquement lorsque le programmeur insre un userform
20/138
Les feuilles
le bouton fermeture est insr automatiquement par Excel l'excution, les points de la grille ont disparu, ils ne servent que comme repres au programmeur
21/138
Les contrles
Le programmeur peut ajouter des contrles
directement dans une feuille Excel
laide de la barre des outils Control Toolbox
dans un userform
laide du menu Toolbox
22/138
Les contrles
Select Objects, (slectionner un objet), ce nest pas un contrle, permet de slectionner les contrles CheckBox (case cocher) TabStrip (range donglets), contrle qui dfinit une collection de donglets RefEdit, contrle qui permet une slection aise de cellules (plages) dans une feuille de calcul Excel
23/138
Les contrles
Label (tiquette, intitul), permet de dfinir une zone texte afficher OptionButton (bouton doption) MultiPage (range de pages), contrle qui dfinit une collection de pages, c.--d. des containers pour dautres contrles
24/138
Les contrles
TextBox (zone de texte), permet de dfinir une zone de saisie ToggleButton (bouton bascule, interrupteur) ScrollBar (dfilement), contrle qui permet dajouter une barre de dfilement
25/138
Les contrles
ComboBox (zone de liste modifiable) Frame (cadre), insre un cadre qui permet de regrouper plusieurs contrles SpinButton (toupie), contrle qui permet dajouter une toupie
26/138
Les contrles
ListBox (zone de liste) CommandButton (bouton de commande), Image (image), contrle qui permet dajouter une image
27/138
Les contrles
la barre des outils Control Toolbox prsente deux parties en plus des diffrents contrles
Design Mode mode design View code voir le code Properties proprits
28/138
Les contrles
pour placer des contrles directement dans une feuille Excel, il faut entrer dans le design mode tant quon est en mode design, les contrles ne fonctionnent pas, les actions qui leurs sont associes ne se dclenchent pas !
29/138
Les contrles
en cliquant sur licne Properties, la fentre des proprits saffiche le programmeur peut ds lors modifier certaines caractristiques du contrle slectionn
30/138
Les contrles
licne View Code amne lenvironnement de dveloppement dExcel en premier plan le curseur est positionn dans la fentre ddition
31/138
Les contrles
En cliquant sur More Controls, le systme affiche la liste de tous les contrles installs sur la machine du programmeur.
32/138
Les contrles
pour obtenir la liste des contrles supplmentaires en travaillant avec un userform, il suffit de faire un clic droit dans la barre doutils Toolbox
33/138
La programmation en VBA
Ecrire un programme qui effectue une transformation de miles en km. L'utilisateur entre le nombre de miles et le programme affiche l'quivalent en kilomtres sachant que 1 mile = 1609 m.
Pour rsoudre un problme par des moyens informatiques, il n'y a pas de magie: il faut raliser un programme qui traite les donnes qu'on lui fournit pour produire les rsultats voulus. Cela signifie en clair que gnralement nous savons quelles sont les donnes et quels sont les rsultats produire. Ainsi pour rsoudre un problme, il faut faire l'inventaire des donnes et des rsultats. Dans le cas de notre premier exemple, nous avons comme : donne : le nombre de miles rsultat : le nombre quivalent en kilomtres Ces deux valeurs se trouveront quelque part en mmoire centrale de l'ordinateur. Dans un langage de haut niveau, l'emplacement exact et la reprsentation interne des valeurs ne nous proccupent gnralement pas. Pour manipuler ces valeurs, nous les dsignons par des noms symboliques.
34/138
La programmation en VBA
donne(s) : le nombre de miles rsultat(s) : l'quivalent en km identificateur miles identificateur km
A l'intrieur d'un programme, toute valeur est donc gnralement reprsente par un identificateur. Le nom de l'identificateur est laiss au choix du programmeur. Mais celui-ci a naturellement intrt choisir un nom proche de la dsignation de la valeur que l'identificateur est cens reprsenter. Les rgles de construction d'un identificateur diffrent d'un langage de programmation un autre. En VBA, le premier caractre doit tre une lettre de A Z. Il nest pas permis dutiliser un espace et les caractres . ! @ & $ #. La taille ne peut excder 255 caractres. Les lettres majuscules ou minuscules peuvent tre utilises indiffremment ce qui n'est pas le cas du langage C par exemple. Ainsi, en VBA : miLEs miles MILES ne dsignent qu'un seul identificateur, alors qu'en C, ces trois noms sont trois identificateurs diffrents.
35/138
La programmation en VBA
Attention :
un identificateur cr par le programmeur ne devrait pas porter le mme nom quun objet prdfini en VBA
Problme :
la liste est trs longue et peut changer
IsArray, Array, Option Base, Dim, Private, Public, ReDim, Static, LBound, UBound, Erase, ReDim, Collection, Add, Remove, Item, #Const, #If, Then, #Else, GoSub, Return, GoTo, On Error, On...GoSub, On...GoTo, DoEvents, End, Exit, Stop, Do, Loop, For, Next, Each, While...Wend, With, Choose, If, Else, Select Case, Switch, Call, Function, Property Get, Property Let, Property Set, Sub, Chr, Format, LCase, UCase, DateSerial, DateValue, Hex, Oct, Format, Str, CBool, CByte, CCur, CDate, CDbl, CDec, CInt, CLng, CSng, CStr, CVar, CVErr, Fix, Int, Day, Month, Weekday, Year, Hour, Minute, Second, Asc, Val, TimeSerial, TimeValue, Boolean, Byte, Currency, Date, Double, Integer, Long, Object, Single, String, Variant, IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject, Now, Time, DateAdd, DateDiff, DatePart, Timer, ChDir, ChDrive, FileCopy, MkDir, RmDir, Name, CurDir, FileDateTime, GetAttr, FileLen, Dir, SetAttr, Clear, Error, Raise, Error, Err, CVErr, On Error, Resume, IsError, DDB, SLN, SYD, FV, Rate, IRR, MIRR, NPer, IPmt, Pmt, PPmt, NPV, PV, Open, Close, Reset, Format, Print, Print #, Spc, Tab, Width #, FileCopy, EOF, FileAttr, FileDateTime, FileLen, FreeFile, GetAttr, Loc, LOF, Seek, Dir, Kill, Lock, Unlock, Name, Get, Input, Input #, Line Input #, FileLen, FileAttr, GetAttr, SetAttr, Seek, Print #, Put, Write #, Atn, Cos, Sin, Tan, Exp, Log, Sqr, Randomize, Rnd, Abs, Sgn, Fix, Int, DoEvents, AppActivate, Shell, SendKeys, Beep, Environ, Command, MacID, MacScript, CreateObject, GetObject, QBColor, RGB, DeleteSetting, GetSetting, GetAllSettings, SaveSetting, etc.
36/138
La programmation en VBA
Le programmeur doit spcifier le type, c'est--dire la nature de l'information reprsente par un identificateur. en VBA, il existe de multiples types prdfinis :
integer double string etc.
Une fois que nous avons fix un identificateur pour une valeur dans la mmoire de l'ordinateur, il nous reste indiquer quel est le genre, le type de la valeur. N'oublions pas, en effet, que la mmoire centrale d'un ordinateur se compose de mots mmoire identiques, quelque soit la nature de l'information que l'on y stocke. Donc la seule vue du mot mmoire, l'ordinateur n'est pas mme de dcider quel type d'information il est confront. C'est au programmeur que revient la tche d'indiquer la nature ou le type d'une valeur. Ainsi, pour tout identificateur qu'il dfinit, le programmeur doit indiquer au compilateur le type de la valeur reprsente par cet identificateur. Cela permet au compilateur de rserver assez d'espace mmoire pour la reprsentation de la valeur dans la mmoire. De plus, vu que le compilateur connat alors le type de l'identificateur, il peut effectuer des contrles stricts par la suite et dtecter des anomalies o le programmeur tente par exemple de "comparer des pommes et des poires" !
37/138
La programmation en VBA
pour travailler avec des nombres, le programmeur a le choix :
byte, integer, long, single, double, currency, decimal
Storage size Range 1 byte 2 bytes 2 bytes 4 bytes 4 bytes 8 bytes 0 to 255 True or False -32,768 to 32,767 -2,147,483,648 to 2,147,483,647 -3.402823E38 to -1.401298E-45 for negative values; 1.401298E-45 to 3.402823E38 for positive values -1.79769313486232E308 to -4.94065645841247E-324 for negative values; 4.94065645841247E-324 to 1.79769313486232E308 for positive values -922,337,203,685,477.5808 to 922,337,203,685,477.5807 +/-79,228,162,514,264,337,593,543,950,335 with no decimal point; +/-7.9228162514264337593543950335 with 28 places to the right of the decimal;
Currency Decimal
8 bytes 14 bytes
38/138
La programmation en VBA
dautres types existent :
boolean, date, object, string, variant le concept de tableau (array)
Date Object
8 bytes 4 bytes
January 1, 100 to December 31, 9999 Any Object reference 10 bytes + string length (0 to approximately 2 billion) Length of string (1 to approximately 65,400) 16 bytes, Any numeric value up to the range of a Double 22 bytes + string length (Same range as for variablelength String)
String (variable-length) String (fixed-length) Variant (with numbers) Variant (with characters)
User-defined (using Type) Number required by elementsThe range of each element is the same as the range of its data type. Note Arrays of any data type require 20 bytes of memory plus 4 bytes for each array dimension plus the number of bytes occupied by the data itself. The memory occupied by the data can be calculated by multiplying the number of data elements by the size of each element. For example, the data in a single-dimension array consisting of 4 Integer data elements of 2 bytes each occupies 8 bytes. The 8 bytes required for the data plus the 24 bytes of overhead brings the total memory requirement for the array to 32 bytes. A Variant containing an array requires 12 bytes more than the array alone.
39/138
La programmation en VBA
Une variable : un identificateur un type une valeur
En programmation imprative (C, Cobol...), les programmes arrivent produire les rsultats dsirs en manipulant des variables. Une variable est un triplet (identificateur, type, valeur). En clair, une variable est dsigne par un nom ou identificateur. D'aprs ce qui prcde, un type est associ l'identificateur en question. Comme cet identificateur dsigne des mots dans la mmoire centrale de l'ordinateur, une variable a toujours une valeur. La valeur est obtenue en interprtant les mots mmoire dsigns par l'identificateur de la manire indiqu par le type de la variable. Cette valeur peut tre indfinie si le programmeur utilise une variable sans que celle-ci n'ait t initialise. En VBA, une variable numrique est initialise par dfaut 0, alors qu'une variable de type chane de caractres prend comme valeur la chane vide "".
40/138
La programmation en VBA
une variable est dclare explicitement laide du mot rserv DIM pour interdire la dclaration implicite de variables
il faut placer la directive OPTION EXPLICIT dans chaque programme ou cocher cette case dans le menu Tools/Options
Toute variable devrait tre dclare avant sa premire utilisation. Pour des raisons historiques, dans VBA et la plupart des dialectes Basic, une variable peut tre utilise sans dire pralablement au systme quel type de donnes elle est cense contenir. Une telle variable a alors le type Variant. Cest une pratique rejeter pour des raisons de performances, doccupation despace mmoire, de scurit, etc. Malheureusement, par dfaut, VBA fonctionne de cette faon. Il est donc vivement conseill de dsactiver ce comportement en plaant la directive OPTION EXPLICIT manuellement dans chacun de ses programmes, ou de manire plus pratique, en cochant la case Require Variable Declaration dans le menu Tools/Options de lenvironnement de programmation.
41/138
La programmation en VBA
Exemples de dclarations de variables :
DIM total AS Integer DIM nbre AS Integer, delta AS Double
mais :
DIM nbre1 AS Integer, nbre2 AS Integer
Une dclaration de variable(s) dbute donc par le mot rserv DIM. Deux dclarations de variable dans une instruction DIM sont spares par le symbole ",". Dans notre exemple, nous crirons : Dim miles As Double, km As Double
42/138
La programmation en VBA
l'affectation est l'instruction fondamentale dans les langages impratifs l'affectation permet de changer la valeur d'une variable il faut que le type de lexpression et le type de la variable soient compatibles ! format simplifi :
[LET] variable "=" expression
Dans les langages de programmation impratifs, l'instruction d'affectation est l'instruction fondamentale permettant au programmeur de donner aux variables les valeurs attendues. L'affectation permet de donner explicitement une valeur une variable. Lors de l'excution de cette instruction, l'expression place droite du symbole "=" est value. Aprs valuation de cette expression, la valeur rsultante est transfre dans les cellules mmoire dsignes par l'identificateur de variable plac gauche du symbole d'affectation "=". Remarque trs importante : la valeur quavait la variable gauche du symbole "=" juste avant l'excution de l'affectation est irrmdiablement perdue ! De ce fait, l'ordre dans lequel les instructions sont places par le programmeur, est primordial. Remarque : Dans un format gnral d'une instruction, une expression place entre { } signifie que l'expression en question peut tre rpte de 0 autant de fois qu'on le dsire. Une expression entre [ ] est facultative, c'est--dire qu'elle est prsente une fois ou pas du tout. Le mta-symbole | indique qu'on a le choix entre l'expression sa gauche et sa droite.
43/138
La programmation en VBA
dans notre exemple : km = 1.609 * miles la variable miles, dsignant le nombre de miles convertir en km est multiplie par 1.609. Cette valeur est affecte ensuite la variable km.
Le programmeur peut dfinir des expressions trs complexes. Voici quelques oprateurs dans leur ordre de priorit dcroissant: ^ exponentiation 2^3=8 moins unaire -3 */ multiplication, division 3/2=1.5 \ division entire 3\2 = 1 Mod modulo 7 Mod 4 =3 +addition, soustraction & concatnation dexpressions En utilisant \ et MOD, les arguments non entiers sont arrondis vers lentier le plus proche. Ces oprateurs peuvent tre combins volont. Le programmeur doit nanmoins savoir quune expression est value de la gauche vers la droite, lordre de priorit indiqu prvaut et que seul un placement de parenthses peut modifier l'ordre d'valuation l'intrieur d'une expression. Il faut videmment veiller ce que les types manipuls dans une expression soient compatibles. VBA effectue des conversions de types dans une expression si les oprandes sont de type nombre diffrents. Attention : le rsultat de loprateur & est un string
44/138
La programmation en VBA
il existe deux botes de dialogue prdfinies en VBA
InputBox MsgBox
VBA offre de nombreuses possibilits travers les contrles pour saisir et afficher des donnes. Deux botes de dialogue prdfinies existent nanmoins pour simplifier la vie du programmeur et pour donner un aspect usuel aux dialogues standards : InputBox et MsgBox.
45/138
La programmation en VBA
InputBox affiche une bote de dialogue, attend que lutilisateur entre du texte ou clique sur un bouton et retourne un string renfermant le texte entr Format simplifi :
InputBox(prompt [,title] [,default])
title default
46/138
La programmation en VBA
Pour notre exemple, on crira :
miles = InputBox("Entrez le nombre de miles", "Conversion de miles en kilomtres")
47/138
La programmation en VBA
MsgBox affiche une bote de dialogue, attend que lutilisateur clique sur un bouton de la bote et renvoie un Integer indiquant quel bouton a t cliqu Format simplifi :
MsgBox(prompt [,buttons] [,title])
buttons
title
48/138
La programmation en VBA
Pour notre exemple, on crira :
res = MsgBox(miles & " miles quivalent " & km & " kilomtres", _
Le texte affich lintrieur de la bote rsulte de la concatnation des expressions miles & " miles quivalent " & km & " kilomtres en se servant de loprateur &. Le contenu de la variable miles vaut 10 et celui de km vaut 16.09. Ces valeurs de type double sont transformes en chanes de caractres et concatnes aux constantes littrales places entre . vbOKOnly est une constante prdfinie dans VBA. Il dnote un type de bote o le programmeur na que la possibilit de cliquer sur OK. La valeur entire retourne par MsgBox identifie le bouton cliqu par lutilisateur. vbOK vbCancel vbAbort vbRetry vbIgnore vbYes vbNo 1 2 3 4 5 6 7 OK Cancel Abort Retry Ignore Yes No
49/138
La programmation en VBA
VBA prfinit dautres botes de dialogue standard
OK/Cancel Yes/No Abort/Retry/Ignore etc.
The first group of values (05) describes the number and type of buttons displayed in the dialog box; the second group (16, 32, 48, 64) describes the icon style; the third group (0, 256, 512) determines which button is the default; and the fourth group (0, 4096) determines the modality of the message box. When adding numbers to create a final value for the buttons argument, use only one number from each group. vbOKOnly 0 Display OK button only. VbOKCancel 1 Display OK and Cancel buttons. VbAbortRetryIgnore 2 Display Abort, Retry, and Ignore buttons. VbYesNoCancel 3 Display Yes, No, and Cancel buttons. VbYesNo 4 Display Yes and No buttons. VbRetryCancel 5 Display Retry and Cancel buttons. VbCritical 16 Display Critical Message icon. VbQuestion 32 Display Warning Query icon. VbExclamation 48 Display Warning Message icon. VbInformation 64 Display Information Message icon. VbDefaultButton1 0 First button is default. VbDefaultButton2 256 Second button is default. VbDefaultButton3 512 Third button is default. VbDefaultButton4 768 Fourth button is default. VbApplicationModal 0 Application modal; the user must respond to the message box before continuing work in the current application. VbSystemModal 4096 System modal; all applications are suspended until the user responds to the message box.
50/138
La programmation en VBA
nous disposons maintenant de tous les ingrdients de base pour raliser notre premier exemple il existe au moins deux faons de procder il suffit par exemple de crer un bouton de commande dans une feuille Excel et lui associer laction de conversion demande
Nous avions dj vu quil existe en principe deux faons de programmer en VBA : placer des contrles directement dans une feuille de calcul Excel placer les contrles dans un userform et activer le userform dans sa feuille Excel. Dans ce premier exemple, nous adoptons la premire technique.
51/138
La programmation en VBA
le contrle placer dans la feuille
tapes suivre : placer un contrle bouton de commande sur une feuille Excel vide. Sur limage, la case cocher Gridlines de Tools/Options dans longlet View a t dsactiv et les cases ont t formats avec une couleur saumon. agrandir le bouton sa convenance changer certaines proprits du bouton de commande travers la fentre des proprits. Sur le transparent, elles sont indiques par des flches rouges. Pour cet exemple, il sagit de Backcolor, Caption et Name. Backcolor change la couleur du bouton; Caption contient le texte qui sera plac dans le bouton et Name permet de changer le nom symbolique par dfaut du bouton. Il sagit de bien choisir le nouveau nom car tout changement ultrieur savre laborieux ! Lidentificateur choisi est BoutonCalcul. double-cliquer le bouton nous amne dans lditeur de lenvironnement de dveloppement. Maintenant, il sagit dcrire le code associ lvnement Click sur le bouton de commande. Cest ici quil faut placer les instructions que lenvironnement doit excuter si par la suite lutilisateur final clique sur ce bouton.
52/138
La programmation en VBA
le code VBA que le programmeur doit crire
le systme cre automatiquement ces deux lignes qui marquent le dbut et la fin de l'action associer au dclenchement de l'vnement click sur BoutonCalcul
Une fois dans lditeur, le curseur est positionn lintrieur dune procdure que le systme a nomm BoutonCalcul_Click(). Le nom est la concatnation de lidentificateur que nous avons choisi comme nom pour le contrle Bouton de commande et de lvnement associ laction, ici click. En VBA, une procdure est appele sub (subroutine, sous-routine). Le mot private (ajout automatiquement par le systme) figurant avant sub signifie que cette procdure nest visibile est accessible que dans la feuille de calcul Excel qui contient le bouton. Deux remarques concernant lcriture du code : le symbole ' est le dbut d'un commentaire, c'est--dired'un texte qui est ignor par l'interprte VBA, mais qui sert documenter le code crit. Il est essentiel de bien documenter ses programmes ! une ligne trop longue peut tre coupe. Il suffit de terminer la ligne qui doit tre coupe par le symbole _ et de continuer la ligne plus bas. Il ne reste qu' tester le programme : on peut passer par exemple dans la feuille Excel, s'assurer qu'on est plus en mode design et cliquer sur le bouton qu'on vient de crer!
53/138
La programmation en VBA
bouton qui sert afficher la "userform"
Le programme prcdent peut tre ralis avec une interface diffrente en utilisant un "userform"
Une mme solution de problme peut tre implmente par des programmes diffrents, notamment au niveau de l'interface utilisateur. Le programme qui convertit des miles en km est ralis diffremment en utilisant une feuille utilisateur "userform" dfinie dans l'environnement de programmation.
54/138
La programmation en VBA
trois contrles de type Label
Dans l'environnement de programmation, une feuille utilisateur est insr dans le projet travers le menu "Insert/User Form". Des proprits de la feuille ainsi cre peuvent tre modifies par le programmeur. Dans l'exemple ci-dessus, les proprits modifies sont marques par une flche : il s'agit de la couleur de fond, du titre (Conversion) et du nom (feuille) de la userform telle qu'elle est connue par Excel. Les contrles sont ensuite placs dans le userform. De nouveau nous devons changer certaines proprits pour les adapter nous besoins. Il est essentiel de changer le nom par dfaut des contrles que nous manipulerons plus tard dans les instructions et ceci avant de commencer programmer les actions associes ces contrles.
55/138
La programmation en VBA
56/138
La programmation en VBA
vnement Click BoutonCalcul
Aprs avoir dfini le "userform" Feuille, nous dfinissons un bouton de commande BoutonCalcul dans la feuille de travail Excel. Son but est d'activer le userform Feuille lorsque l'utiliteur clique sur le bouton. Au moment o Excel charge la feuille de travail (worksheet) en mmoire, celle-ci contient le userform Feuille que nous veons de crer, mais il est cach. Il suffit de la rendre visible. C'est le travail de la procdure BoutonCalcul_Click() associ ce bouton travers l'instruction Show appliqu Feuille : Feuille.Show A l'excution, lorsque le userform est actif, l'utilisateur peut entrer des valeurs dans les zones d'dition, dans notre cas miles. En cliquant sur le bouton "Calcul", l'action BoutonCalcul_Click() propre ce bouton est dclenche, c'est--dire l'instruction km.Value = 1.609 * miles.Value Elle signifie que la valeur associe au contrle km devient la valeur associe au contrle miles multiplie par 1.609. Value est une des proprits du contrle TextBox.
57/138
La structure alternative
la ralisation d'actions n'est pas toujours un processus squentiel beaucoup de situations exigent des traitements spcifiques d'o la ncessit d'une structure de contrle alternative permettant d'introduire la notion de choix
Les exemples raliss jusqu' prsent avaient la caractristique que toutes les instructions de chacune des actions taient excutes squentiellement dans leur ordre d'apparition. Dans la vie relle, il existe videmment une infinit d'exemples o le traitement effectuer est variable, selon la nature des donnes. Les langages de programmation impratifs donnent au programmeur, travers la structure de contrle alternative, la possibilit de procder des traitements spcifiques.
58/138
La structure alternative
Syntaxe
If condition Then [statements] {ElseIf condition-n Then [elseifstatements] } [Else [elsestatements]] End If
Dans linstruction conditionnelle, si l'valuation de la condition donne comme rsultat la valeur logique TRUE , alors ce sont les instructions suivant le mot rserv THEN qui sont excutes et l'excution continue en squence avec l'instruction qui suit logiquement linstruction IF END IF. Les parties ELSEIF, ELSE, mme si elles sont prsentes, ne seront pas excutes. Il peut y avoir autant de ELSEIF que ncessaire, mais il ne peut y en avoir aprs le ELSE. Si l'valuation de l'expression donne la valeur FALSE, alors ce sont toutes les instructions ELSEIF (si prsentes et dans l'ordre d'apparition) qui sont values. Si une des ces conditions est value TRUE, les instructions associes sont excutes et l'excution continue en squence avec l'instruction qui suit logiquement linstruction IF END IF. Dans le cas o la condition du IF est value FALSE et que toutes les conditions ELSEIF ventuelles sont aussi values FALSE, les instructions associes la partie ELSE, pourvu qu'elle existe, sont excutes. Dans le cas o il ny a pas de partie ELSE, l'excution continue en squence avec l'instruction qui suit logiquement linstruction IF. Il est permis d'crire des instructions IF imbriques (une instruction IF contenant une autre instruction IF, etc.). Il est important d'crire proprement les instructions IF en mettant en vidence les imbrications!
59/138
La structure alternative
Exemples :
les programmes convertissant les miles en km acceptent des nombres ngatifs en cliquant sur le bouton Cancel, le programme se "plante"
Les programmes prcedents calculent le rsultat exact pourvu que l'utilisateur entre une donne correcte. Tel n'est pas le cas s'il entre par exemple un nombre de miles ngatif, ou s'il entre des caractres ou s'il clique sur le bouton "Cancel" dans la bote de dialogue "InputBox". Les deux programmes doivent tre modifis afin d'liminer ce comportement incorrect.
60/138
La structure alternative
Private Sub BoutonCalcul_Click() Dim miles As Variant, km As Double Dim res As Integer deux instructions IF imbriques ' saisie de la donne miles = Val(InputBox("Entrez le nombre de miles", "Conversion de miles en kilomtres")) If miles <> 0 Then ' l'utilisateur a cliqu OK ' vrification de la validit de la donne If miles < 0 Then res = MsgBox("Nombre de miles ngatif", vbCritical, "Rsultat de la conversion") Else ' calcul du rsultat km = 1.609 * miles ' affichage du rsultat res = MsgBox(miles & " miles quivalent " & km & " kilomtres", vbOKOnly, "Erreur") End If End If End Sub
La variable miles n'est pas saisie directement comme un nombre, mais d'abord comme du texte qui est transform par la suite, grce la fonction Val(), en un nombre. Exemples : Dim MyValue MyValue = Val("2457") MyValue = Val(" 2 45 7") MyValue = Val("24 and 57") MyValue = Val("a24") MyValue = Val("2a24 ") MyValue = Val("") ' Returns 2457. ' Returns 2457. ' Returns 24. ' Returns 0. ' Returns 2. ' Returns 0.
La fonction InputBox() renvoie la valeur entre par l'utilisateur si celui-ci clique sur "Ok" ou la chane "" (vide) s'il clique sur "Cancel". Ce comportement permet au programmeur de savoir quel bouton a t cliqu.
61/138
La structure alternative
If Val(miles.Value) >= 0 Then km.Value = 1.609 * Val(miles.Value) Else Dim res As Integer res = MsgBox("Nombre de miles ngatif", _ vbCritical, _ "Erreur") End If
62/138
La structure alternative
Exercice: calcul de la date du lendemain
Il s'agit d'crire un programme qui calcule la date du lendemain partir d'une date correcte entre au clavier. Ce problme d'apparence simple n'est pas si anodin que cela, car il montre une des difficults de la programmation : la prcision des concepts manipuls par le programme.
Description des donnes et rsultats : anne entre mois entr jour entr anne du lendemain mois du lendemain jour du lendemain a m j al ml jl
63/138
La structure alternative
si pas fin de mois alors { passer simplement au jour suivant } ml m al a jl j + 1 sinon { c'est la fin d'un mois. Est-ce la fin d'anne ? } si pas fin d'anne alors { c'est une fin de mois normale } jl 1 ml m + 1 al a sinon { c'est bien la St. Sylvestre } jl 1 ml 1 al a + 1 finsi finsi
Il ne reste qu' formaliser les diffrentes conditions. La condition fin de mois peut tre crite ainsi : j = 31 ou ou ou j = 30 et m = 4, 6, 9 ou 11 j = 29 et m = 2 j = 28 et m = 2 et ce nest pas une anne bissextile
Remarquons encore une fois que nous avons suppos que la date entre est correcte. La condition anne bissextile peut, quant elle, tre formalise de la faon suivante : ((a divisible par 4) et (a pas divisible par 100)) ou (a divisible par 400) La condition fin d'anne s'crit : fin de mois et m = 12
64/138
La structure alternative
BoutonSpinJour BoutonSpinMois BoutonSpinAnnee FeuilleDonnee Jour Mois Annee
FeuilleResultat
DateLendemain
Pour la ralisation de l'interface utilisateur du programme, nous prvoyons deux "userform" appels respectivement FeuilleDonnee et FeuilleResultat. FeuilleDonnee prsente trois contrles "TextBox" associs chacun un contrle "SpinButton". Dans FeuilleDonnee l'utilisateur fixe une date, puis clique sur le bouton "Calcul" pour voir afficher FeuilleResultat.
65/138
La structure alternative
dans les proprits de chaque contrle "SpinButton", nous fixons
le nom la valeur logique Max la valeur logique Min l'orientation la valeur de dpart
Un contrle "SpinButton" peut tre prsent horizontalement ou verticalement. Les valeurs Max et Min sont des limites logiques autorises. Mais attention : le systme ne fait aucun contrle pour vrifier qu'il y a dpassement de ces valeurs limites, c'est au programmeur que revient cette charge ! Cela est tout fait logique, puisque jusqu' prsent, nous n'avons pas encore associ de zone de saisie, en l'occurrence un contrle de type "TextBox" au "SpinButton".
66/138
La structure alternative
Pour chacun des contrles de type "SpinButton", nous devons dfinir ce qu'il doit faire en prsence des vnements du type
SpinDown SpinUp
67/138
La structure alternative
Private Sub BoutonSpinJour_SpinUp() If Jour.Value < BoutonSpinJour.Max Then Jour.Value = Jour.Value + 1 Else Jour.Value = BoutonSpinJour.Min End If Private Sub BoutonSpinJour_SpinDown() End Sub If Jour.Value > BoutonSpinJour.Min Then
Jour.Value = Jour.Value - 1 Else Jour.Value = BoutonSpinJour.Max End If End Sub
Lorsque l'utilisateur clique sur la flche montante du contrle BoutonSpinJour, c'est clairement pour faire avancer de "un" la valeur du contrle Jour. Le programmeur doit donc programmer cette action en veillant ce que cette valeur ne dpasse pas 31. Plutt que de travailler directement avec la constante numrique 31, nous travaillons avec la valeur conserve dans une proprit de BoutonSpinJour, savoir Max. Lorsque que la valeur limite suprieure est atteinte, nous recommenons avec la valeur limite infrieure ! Il en est de mme si l'utilisateur clique sur la flche descendante du contrle BoutonSpinJour ; c'est clairement pour faire reculer de "un" la valeur du contrle Jour.
68/138
- Introduction Visual Basic for Applications Private Sub BoutonCalcul_Click() Dim a As Integer, m As Integer, j As Integer Dim al As Integer, ml As Integer, jl As Integer Dim annee_divisible_par_4 As Boolean, annee_divisible_par_100 As Boolean Dim annee_divisible_par_400 As Boolean a = Annee.Value m = Mois.Value j = Jour.Value annee_divisible_par_4 = IIf(a Mod 4 = 0, True, False) annee_divisible_par_100 = IIf(a Mod 100 = 0, True, False) annee_divisible_par_400 = IIf(a Mod 400 = 0, True, False) ' calcul de la date du lendemain If Not ((j = 31) Or _ ((j = 30) And ((m = 4) Or (m = 6) Or (m = 9) Or (m = 11))) Or _ ((j = 29) And (m = 2)) Or _ ((j = 28) And (m = 2) And _ Not ((annee_divisible_par_4 And _ Not annee_divisible_par_100) Or _ annee_divisible_par_400) _ )_ ) Then ' on n'est pas la fin d'un mois jl = j + 1 ml = m al = a ElseIf m <> 12 Then ' fin de mois mais pas fin d'anne al = a ml = m + 1 jl = 1 Else ' c'est la St. Sylvestre al = a + 1 ml = 1 jl = 1 End If FeuilleResultat.DateLendemain.Value = jl & "-" & ml & "-" & al FeuilleResultat.Show End Sub
69/138
La structure alternative
Forme spciale d'instruction alternative, la fonction :
IIF(expression, expr_Vrai, expr_Faux)
Si expression est value TRUE, la fonction IIF() renvoie comme valeur le rsultat de l'valuation de l'expression expr_VRAI, autrement la valeur expr_FAUX. Exemple : mention = iif(note > 16, "Trs bien", "satisfaisant") Attention : expr_VRAI et expr_FAUX sont valus toujours tous les deux !
70/138
La structure rptitive
Pour introduire cette structure de contrle, nous ralisons un programme qui calcule la somme des n premiers nombres entiers positifs, o n entier positif ou nul est entr au clavier de l'ordinateur. En clair, il s'agit de calculer la somme : 1+ 2 + 3 + + n, mais en supposant que nous n'ayons pas la formule pour la calculer directement.
Description des donnes et des rsultats : entier positif ou nul entr au clavier somme des entiers Mthode de rsolution : 1. 2. 3. entrer n calculer somme afficher n et somme n somme
Raffiner 2 : Pour obtenir la somme, il suffit d'ajouter successivement le nombre suivant i la somme dj calcule. Initialement somme vaut 0 et i vaut 1. Le nombre entier suivant se trouve dans la variable i. Cette rptition s'arrte lorsque i > n. somme 0 i1 tant que i n faire ii+1 fintantque
corps de la boucle
somme somme + i
initialisations
71/138
La structure rptitive
La structure de contrle de rptition scrit:
tant que condition de maintien faire corps de la boucle fintantque
celle-ci
la condition de maintien dans la boucle est d'abord value. Si elle est vrifie, c'est--dire si sa valeur est vrai, le corps du tant que fintantque est excut. Aprs excution de la dernire instruction de ce corps, l'excution continue avec l'valuation de la condition de maintien, d'o l'effet de boucle ou rptition. La boucle ou rptitive s'arrte lorsque la condition d'arrt de la boucle est vrifie. La condition qui apparat dans le tant que fintantque est une condition de maintien dans la boucle. La condition d'arrt de la boucle s'obtient donc en niant la condition de maintien ou, inversement, la condition de maintien s'obtient en niant la condition d'arrt.
valuer la condition
vrai
corps de la boucle
72/138
Comme le corps d'une boucle est excut jusqu' la ralisation de la condition d'arrt, il est primordial, lorsque l'on crit une boucle, de s'assurer que le corps de la boucle contienne des instructions qui garantissent effectivement la possibilit de la ralisation de la condition d'arrt. Si tel n'tait pas le cas, alors le programme contenant la boucle ne s'arrterait jamais de lui-mme vu que la condition d'arrt ne serait jamais ralise. Lorsque l'on est dans un cas pareil, on dit que le programme boucle ou qu'il est dans une boucle infinie. Voici un exemple simple de boucle infinie : i1 tant que i < 10 faire afficher('Coucou') fintantque Vu que i vaut 1 initialement, le corps de la boucle est excut. Ensuite la condition est rvalue ; comme i n'a pas chang, la condition donne de nouveau vrai et ainsi de suite. Le corps de cette boucle ne contient pas d'instruction pouvant modifier un des oprandes de la condition d'arrt. Si on programme cet algorithme et qu'on l'excute sur machine, il faut gnralement une intervention externe de l'utilisateur pour l'arrter, au pis en redmarrant la machine (sur un systme simple).
73/138
La structure rptitive
Format VBA :
"WHILE" expression instruction(s) "WEND"
Tant que l'expression est value la valeur vrai, la ou les instructions qui suivent l'expression sont excutes. Si l'expression est value faux, l'instruction while est termine et lexcution continue dans le programme avec linstruction suivant logiquement linstruction wend. Ainsi, si la premire valuation de l'expression, celle-ci a comme valeur faux, le bloc d'instructions compris entre WHILE et WEND n'est jamais excut.
74/138
La structure rptitive
Private Sub BoutonDemarrage_Click() Dim n As Integer, somme As Integer, i As Integer n = InputBox("Entrez un entier positif", _ "Calcul de la somme des N premiers entiers", 0) i=1 somme = 0 While i <= n somme = somme + i i=i+1 Wend MsgBox ("La somme des " & n & " premiers entiers vaut " & somme) End Sub
Remarquons que nous crirons toujours le corps d'une boucle lgrement dcal vers la droite afin de bien montrer la porte de la structure de contrle. Il reste une remarque faire sur l'obtention de la condition d'arrt partir de la condition de maintien ou vice versa. Comme nous l'avons vu plus haut, une condition s'obtient en niant l'autre. Pour ce faire, on peut bien entendu utiliser l'oprateur logique NOT. Mais on peut aussi utiliser les lois de de Morgan qui scrivent : non(A ou B) = non(A) et non(B) non(A et B) = non(A) ou non(B) Supposons, par exemple, que la condition d'arrt d'une boucle s'crive : (x 3) ou (x 5) La condition de maintien dans la boucle est donc : non[(x 3) ou (x 5)] = non(x 3) et non(x 5) = (x > 3) et (x < 5)
75/138
La structure rptitive
Calculer la somme d'une suite de nombres positifs ou nuls entrs au clavier de l'ordinateur. La fin de la suite est marque par un nombre ngatif.
Le problme prcdent tait un peu spcifique en ce sens que la condition d'arrt de la boucle ne dpendait que d'un paramtre fix une fois pour toutes avant l'excution de la boucle, lors de la saisie du nombre entier. On peut aussi tre confront la situation o le facteur dterminant la condition d'arrt de la boucle est lui-mme dtermin dans le corps de la boucle. Nous allons tudier ce cas sur un petit programme qui calcule la somme d'une suite de nombres positifs ou nuls entrs au clavier de l'ordinateur. La fin de la suite est marque par un nombre ngatif. Pour rsoudre ce problme, il faut additionner la dernire valeur lue la somme des valeurs dj traites. L'historique de ces valeurs ne nous intresse pas et il suffit d'une variable contenant la dernire valeur lue et non encore traite. Description des donnes et des rsultats : dernire valeur lue et non encore traite somme des valeurs traites nbre somme
76/138
Mthode de rsolution : Il est clair qu'il faut utiliser une boucle pour rsoudre ce problme. Le corps de boucle s'crit : somme somme + nbre lire(nbre) La condition d'arrt de la boucle est : nbre < 0, c'est--dire que lon arrte si l'utilisateur entre un nombre ngatif. Pour que la boucle fonctionne correctement, il faut initialiser la somme zro et lire le premier nombre. Nous obtenons ainsi : somme 0 lire(nbre) { saisie d'avance : valeur lue et non encore traite } tant que nbre 0 faire somme somme + nbre lire(nbre) fintantque afficher(somme) Cet algorithme rvle donc qu'il y a deux oprations de saisie, la saisie d'avance et la saisie courante. Cela peut paratre surprenant premire vue, mais en fait c'est normal puisque c'est la valeur lue qui dtermine l'arrt de la boucle. { saisie courante : valeur lue et non encore traite }
77/138
On aurait pu tre tent de changer l'ordre des instructions du corps de la boucle. lire(nbre) somme somme + nbre La condition d'arrt de la boucle ne change pas, c'est toujours nbre < 0. Alors que faire si nbre est ngatif ? On doit empcher l'addition de ce nbre somme, ce qui peut se faire par un test. On obtient : lire(nbre) si nbre 0 alors somme somme + nbre finsi L'initialisation de somme ne change pas, par contre pour nbre, il y a un problme. Il ne reste qu' utiliser un truc pour que a marche quand mme : on initialise nbre zro ce qui permet d'entrer dans le corps de la boucle : Nous obtiendrions l'algorithme suivant : somme 0 nbre 0 tant que nbre 0 faire lire(nbre) si nbre 0 alors somme somme + nbre finsi fintantque afficher(somme) Cet algorithme est mauvais car il nous force utiliser des trucs pour empcher l'arrt prmatur de la boucle ; de plus, le corps de la boucle est inutilement compliqu cause de la structure alternative qui n'est pas conomique du tout car le test si nbre 0 se fait deux fois pour chaque passage dans la boucle ! Une solution pareille doit donc tre rejete.
78/138
La structure rptitive
Dim nbre As Integer, somme As Integer somme = 0 ' saisie d'avance nbre = InputBox("Entrez un entier positif", _ "Calcul de la somme de N nombres ( < 0 pour arrter)", 0) While nbre >= 0 somme = somme + nbre ' saisie courante nbre = InputBox("Entrez un entier positif", _ "Calcul de la somme de N nombres ( < 0 pour arrter)", 0) Wend MsgBox ("La somme des nombres entrs vaut " & somme)
79/138
La structure rptitive
VBA offre de multiples formes de structures de contrle de rptition
WHILEWEND FORNEXT FOR EACHNEXT DOLOOP
La plupart des langages de programmation offrent au programmeur plusieurs structures de contrle rptitive mieux adaptes l'une ou l'autre situation. WHILEWEND est la structure la plus gnrale que l'on rencontre dans tous les langages de programmation usuels. Lorsque que le nombre d'itrations est connu, fix l'avance, on peut utiliser la boucle FORNEXT bien adapte cette situation. La boucle FOR EACHNEXT est adapte des situations que nous verrons plus tard. Finalement, la boucle DO LOOP existe en deux formes fondamentales et est trs flexible.
80/138
La structure rptitive
FOR variable = debut TO fin [STEP pas]
{instruction} [EXIT FOR] {instruction}
NEXT [variable]
Requis. Variable numrique utilise comme compteur de boucle. Elle ne peut tre un boolen ou un lment d'un tableau. Requis. Valeur initiale du compteur. Requis. Valeur finale du compteur.. Optionnel. La quantit ajoute au compteur aprs chaque passage dans la boucle. Si STEP est absent, le pas vaut 1.
Le pas peut tre positif or ngatif. S'il est >= 0, le corps de la boucle est excut tant que compteur <= fin. S'il est < 0, le corps de la boucle est excut tant que compteur >= fin. Lorsque toutes les instructions du corps de boucle ont t excutes, fin est additionn automatiquement la variable compteur. EXIT FOR est prvu pour quitter prmaturement la boucle et est gnralement utilis conjointement avec une instruction IF ! Attention : Il est fortement dconseill de changer la valeur d'une variable compteur l'intrieur de la boucle !
81/138
La structure rptitive
Exemple : Calcul de la factorielle d'un nombre factorielle(0) = 1 factorielle(n) = n*(n-1)*(n-2)*3*2*1
Dim nbre As Integer, fact As Integer, i As Integer nbre = InputBox("Entrez un entier positif ou nul", _ "Calcul de la factorielle d'un nombre", 0) fact = 1 For i = nbre To 2 Step -1 fact = fact * i Next i MsgBox ("La factorielle de " & nbre & " vaut " & fact)
82/138
La structure rptitive
L'instruction de rptition existe sous quatre formes diffrentes : Do While condition {instruction} [Exit Do] {instruction} Loop
Do Until condition {instruction} [Exit Do] {instruction} Loop
La forme DO WHILE condition LOOP est quivalente la forme WHILE WEND. La condition est une condition de maintien dans la boucle ! Si nous reprenons le premier exemple de ce chapitre, on crit : i=1 somme = 0 Do While i <= n somme = somme + i i=i+1 Loop DO UNTIL condition LOOP est trs semblable sauf que cette fois-ci la condition est la condition d'arrt de la boucle. Exemple : i=1 somme = 0 Do Until i > n somme = somme + i i=i+1 Loop Dans les deux cas, le corps de la boucle peut ne jamais tre excut !
83/138
La structure rptitive
Do {instruction} [Exit Do] {instruction} Loop While condition
Do {instruction} [Exit Do] {instruction} Loop Until condition
Ces deux formes se distinguent fortement des deux prcdentes, car cette fois, le corps de la boucle est toujours excut au moins une fois, car la vrification de la condition de maintien ou d'arrt se fait chaque fois la fin de l'excution du corps ! Cette forme peut tre trs pratique dans certains cas, comme par exemple la vrification d'une saisie. Do n = InputBox("Entrez un entier positif", _ "Calcul de la somme des N premiers entiers", 0) Loop Until n >= 0 ou Do n = InputBox("Entrez un entier positif", _ "Calcul de la somme des N premiers entiers", 0) Loop While n < 0
84/138
Les fonctions
Trois structures de contrle fondamentales :
la structure squentielle la structure alternative la structure rptitive
Mthode de dveloppement par raffinements successifs : ncessit dun outil de structuration du code
Jusqu' prsent, nous avons tudi les trois structures de contrle fondamentales permettant d'crire tout programme calculable effectivement. Rappelons encore une fois ces trois structures : la structure squentielle: les instructions sont excutes en squence, l'une aprs l'autre, dans leur ordre d'apparition ; la structure alternative: les instructions sont excutes en fonction de la ralisation dune condition; la structure rptitive: les instructions sont excutes un nombre variable de fois dpendant de la ralisation de la condition d'arrt. Mais l'criture de programmes corrects n'est pas une chose aussi facile que cela parat premire vue. Il est intressant de disposer d'une mthode de dveloppement permettant de construire des programmes corrects. C'est ce que nous avons fait dans les chapitres prcdents en utilisant la mthode de dveloppement de programmes par raffinements successifs tout en s'aidant d'une mthode de construction de boucles base sur le concept d'invariant. Dans la mthode de dveloppement par raffinements successifs, le but est de dcomposer un problme en sous-problmes, chacun de ces sous-problmes tant plus facile rsoudre que le problme initial. C'est ce que nous avons fait dans les programmes raliss, mais linconvnient est que le programme ne garde plus aucune trace de cet effort de structuration et de dcomposition, part les commentaires.
85/138
Les fonctions
Outil de structuration du code :
le sous-programme
fonction procdure
Ce sont des concepts que lon retrouve dans tous les langages de programmation impratifs.
Cette lacune est comble par le concept de sous-programme (procedure, subroutine). Nous verrons quil existe deux types de sous-programmes : les fonctions et les procdures. Ces notions favorisent, supportent le style de dveloppement par raffinements successifs en ce sens qu'elles permettent au programmeur de traduire en VBA, telles quelles, les diffrentes phases de raffinement. Le concept de fonction ou procdure a encore d'autres avantages. Il permet notamment de pouvoir rutiliser du code existant et, de ce fait, augmente la productivit. De plus, il permet d'introduire un niveau d'abstraction en permettant de construire et de manipuler des structures qui n'existent pas d'office dans le langage. Le concept de fonction et/ou de procdure est prsent dans tous les langages de programmation impratifs usuels.
86/138
Les fonctions
sous-programme :
ensemble dinstructions, calculant un certain nombre de rsultats en fonction dun certain nombre de donnes. les donnes et rsultats du sous-programme sont appels arguments ou paramtres.
Un sous-programme est un moyen dont dispose le programmeur pour nommer une action complexe. Cette action est dcrite au moyen dun ensemble dinstructions du langage. Le programmeur a le moyen de paramtriser cette action travers des arguments quil fournit au sous-programme. Pour raliser laction dcrite par un sous-programme, un programme ou un sousprogramme peut appeler ou invoquer le sous-programme en question. La diffrence essentielle entre un programme et un sous-programme est donc quun sous-programme peut agir pour le compte dun programme ou dun sousprogramme. Lorsquil ny a pas de confusion possible, nous utiliserons indiffremment les termes programme et sous-programme. Lorsquun programme appelle un sous-programme, nous distinguerons entre le programme appel et le programme appelant. A la fin de lexcution du programme appel se produit un retour automatique vers le programme appelant linstruction suivant logiquement linstruction dappel du sous-programme.
87/138
Les fonctions
la dfinition dun sous-programme comporte :
le nom du sous-programme le nombre et le type de ses arguments une description de laction
Lorsque le programmeur dfinit un sous-programme, il doit lidentifier en lui donnant un nom et en prcisant le nombre et le type de ses arguments. Ensuite, il fournit la suite dinstructions produisant laction voulue au moment de lexcution du sous-programme. Ces instructions manipulent gnralement les arguments ventuels du sousprogramme. Il est donc ncessaire de donner un nom chacun des arguments du sous-programme. On les appelle arguments formels ou paramtres formels.
88/138
Les fonctions
appel dun sous-programme :
crire le nom du sous-programme suivi dune liste darguments effectifs
Pour appeler un sous-programme, il suffit, dans le programme appelant, dcrire le nom du sous-programme suivi dune liste ventuelle darguments effectifs (rels). Chacun de ces arguments effectifs est cens remplacer largument formel correspondant tel quil est dfini dans la dfinition du sous-programme. Nous verrons plus loin comment se fait trs prcisment ce remplacement. Dans la plupart des langages de programmation impratifs, la correspondance entre les arguments effectifs et formels doit tre totale, tant du point de vue nombre que de leurs types respectifs. Au moment de lexcution, dans le programme appelant, lendroit de lappel du sous-programme, les instructions de ce dernier seront excutes avec les arguments effectifs fournis dans lappel. Une fonction qui sappelle elle-mme est appele une fonction rcursive.
89/138
Les fonctions
un sous-programme ne reprsentant qu'une action est appel une procdure un sous-programme dnotant une valeur est une fonction
A travers l'utilisation de procdures, le programmeur a la possibilit de dfinir de nouvelles primitives (instructions). A la diffrence des instructions prdfinies dans le langage, ces nouvelles instructions ne sont comprises que par le programme dans lequel ces procdures sont dfinies. Une fonction ne peut tre appele que dans une expression. Il faut videmment que la fonction en question soit dfinie dans le programme appelant !
90/138
Les fonctions
dans VBA Function nom_fonction [(arglist)] [As type] { instruction | nom_fonction = expression | Exit Function } End Function
Une fonction a un nom et possde ventuellement une liste d'arguments place entre parenthses. Le programmeur peut indiquer le type de la valeur retourne par la fonction travers le mot-cl AS. Le corps de la fonction dlimite par FUNCTION et END FUNCTION se compose d'instructions VBA qui peuvent tre bien sr des appels de fonction/procdure. L'instruction EXIT FUNCTION permet d'arrter l'excution de la fonction et de continuer l'excution l'endroit qui suit immdiatement l'appel de la fonction. Normalement cela est ralis automatiquement lorsque l'excution arrive END FUNCTION. La valeur retourne par la fonction est donne par une instruction d'affectation o la zone rceptrice porte le mme nom que la fonction. Une fonction peut contenir plusieurs instructions EXIT FUNCTION, mais du point de vue mthodologique, cette pratique est dconseiller. Le principe sain qui prvaut est : une fonction a un point dentre et un point de sortie !
91/138
Les fonctions
dans VBA Sub nom_fonction [(arglist)] { instruction} [ Exit Sub ] { instruction} End Sub
Une procdure a un nom et possde ventuellement une liste d'arguments place entre parenthses. Le corps de la fonction dlimite par SUB et END SUB se compose d'instructions VBA qui peuvent tre bien sr des appels de fonction/procdure. L'instruction EXIT SUB permet d'arrter l'excution de la procdure et de continuer l'excution l'instruction qui suit logiquement l'appel de la procdure. Normalement cela est ralis automatiquement lorsque l'excution arrive END SUB. Une fonction peut contenir plusieurs instructions EXIT SUB, mais du point de vue mthodologique, cette pratique est dconseiller.
92/138
Les fonctions
La syntaxe simplifie d'un argument de la liste d'arguments est la suivante : [ByVal | ByRef] varname As type deux arguments sont spars par une virgule
Un argument est pass par dfaut par rfrence, c'est--dire que l'argument dans la fonction est un alias du paramtre effectif. En clair, si la fonction modifie l'argument, c'est en ralit l'argument effectif qui est chang. C'est le mode de passage par dfaut. Lorsque le programmeur passe un argument par valeur, alors la fonction dispose de sa propre copie de l'argument. Si elle le modifie, cela n'affecte en rien l'argument effectif correspondant.
93/138
Les fonctions
appel d'une procdure
comme instruction
nom_de_procdure argument1, argument2
ou
CALL nom_de_procdure(arg1, arg2)
Lors de l'appel d'une fonction ou procdure, les arguments effectifs utiliss doivent tre compatibles avec les arguments formels tels qu'ils sont dfinis dans la dclaration de cette fonction ou procdure. Si le mode de transmission de l'argument est ByRef, l'argument formel qui doit tre une variable, est li l'argument effectif, il en devient un alias. Si le mode de transmission de l'argument est ByVal, l'argument effectif, qui est alors une expression, est valu et l'argument formel correspondant aura comme valeur initiale la valeur rsultant de cette valuation. En principe, le nombre et le type des paramtres effectifs et formels doivent correspondre.
94/138
Les fonctions
dans une feuille de travail normale Excel
une fonction dfinie par l'utilisateur peut tre utilise tout comme une fonction prdfinie une procdure dfinie par l'utilisateur peut tre associe une macro
Un avantage des fonctions et des procdures dfinies par l'utilisateur avec VBA est qu'elles peuvent tre utilises dans des feuilles de calcul Excel.
95/138
Les fonctions
une fonction /procdure peut contenir des dclarations de variables ce sont des variables locales la fonction/procdure elles sont automatiquement cres au moment de l'appel et dtruites la fin de l'excution de la fonction /procdure
Une variable locale peut porter le mme nom qu'un variable dfinie globalement, c'est--dire en dehors d'une fonction ou procdure. Une telle variable est appele une variable globale. Dans le cas o une variable locale porte le mme nom qu'une variable globale, cette dernire n'est plus accessible dans la fonction qui dfinit cette variable locale.
96/138
Les fonctions
Function Reverse(ByVal s As String) As String Dim rev As String, i As Integer rev = "" For i = Len(s) To 1 Step -1 rev = rev & Mid(s, i, 1) Next i Reverse = rev End Function
La fonction Reverse renvoie comme valeur la chane de caractres transmise renverse. L'argument effectif n'est pas modifi !
97/138
Les fonctions
Function DeuxiemeDegre(ByVal a As Double, ByVal b As Double, ByVal c As Double, _ x1 As Double, x2 As Double) As Boolean ' calcul du discriminant Dim delta As Double delta = b * b - 4 * a * c ' dtermination des solutions ventuelles ... If (delta < 0) Then Else DeuxiemeDegre = False x1 = (-b - Sqr(delta)) / (2 * a) ElseIf (delta = 0) Then x2 = (-b + Sqr(delta)) / (2 * a) x1 = -b / (2 * a) DeuxiemeDegre = True x2 = x1 End If DeuxiemeDegre = True End Function ...
Cette fonction admet 5 arguments : les 3 premiers sont passs par valeur ; ce sont les donnes que nous fournissons la fonction le deux derniers sont passs par rfrence ; ce sont les rsultats que la fonction renvoie De plus, la fonction a comme valeur un boolen indiquant si oui ou non l'quation admet des solutions relles. Voici une procdure utilisant cette fonction : Sub test_deuxiemeDegre() Dim s1 As Double, s2 As Double If DeuxiemeDegre(3, 6, 3, s1, s2) Then Debug.Print s1; s2 End If End Sub
98/138
Les tableaux
un tableau permet de dfinir un ensemble fini d'lments de mme type un tableau est conserv dans la mmoire centrale de lordinateur tous les lments dun tableau portent le mme nom, mais chacun porte un numro (indice) diffrent
Tout programme peut tre crit avec les trois structures de contrle de base. Nanmoins, nous venons de voir que les concepts de fonction et de procdure peuvent faciliter la mise au point de programmes. Jusqu prsent, nous avons manipul des variables simples. Or dans certains cas, cette approche se rvle assez fastidueuse. Cest pour cela que le concept de tableau est prsent dans la plupart des langages de programmation. Un tableau est une structure de donnes conserve dans la mmoire centrale de l'ordinateur. L'utilisation d'un tableau permet de dfinir un ensemble fini d'lments de mme type. Chaque lment d'un tableau est identifi par le mme identificateur (le nom du tableau) et par un numro unique appel indice de l"lment du tableau. Grce ces deux donnes, on peut manipuler chacun des lments d'un tableau. Le temps d'accs un lment est indpendant de la valeur de l'indice, et les lments peuvent tre accds dans n"importe quel ordre. On dit que c'est une structure de donnes accs alatoire.
99/138
Les tableaux
VBA supporte deux types de tableaux
les tableaux statiques les tableaux dynamiques
La taille occupe par un tableau statique en mmoire centrale est fixe une fois pour toutes au moment de la compilation. Pour un tableau dynamique, le programmeur ne doit doit pas spcifier immdiatement la taille que celui-ci occupe en mmoire; ceci se fait plus tard l'aide de l'instruction REDIM. Attention : cette flexibilit se paie en perte de vitesse d'excution du programme.
100/138
Les tableaux
Exemple d'un tableau statique :
DIM t(5) AS single
t
0 1 2 3 4 5
La taille des tableaux statiques doit tre fixe la compilation. Lindice du premier lment d'un tableau est zro par dfaut. Dans lexemple ci-dessus, le tableau t se compose de 6 lments numrots de 0 5. La directive OPTION BASE 1 permet de fixer l'indice du 1er lment des tableaux 1. Elle doit prcder toute dfinition de tableau et ne peut figurer qu'une seule fois dans la partie "dclarations" d'un module. Les lments dun tableau sont initialiss 0 pour les types numriques et "" (la chane vide) pour les chanes de caractres (string). Un tableau peut tre utilis comme argument dun fonction, mais une fonction ne peut pas retourner un tableau autrement que comme un de ses arguments passs par variable.
101/138
Les tableaux
le programmeur doit fixer la borne suprieure du tableau statique si la borne infrieure n'est pas indique, elle vaut 0 par dfaut ou 1 si OPTION BASE 1 mais il peut aussi fixer celle-ci lui-mme
exemple : DIM t(-10 TO 10) AS integer
En fixant la borne infrieure d'un tableau statique, le programmeur doit veiller ce que sa valeur soit infrieure ou gale celle de la borne suprieure. Erreur : Correct : DIM t(1 TO -1) AS string DIM x(-1 TO 1) AS string DIM u(2 TO 2) AS integer ' 3 lments d'indice -1, 0, 1 ' 1 lment d'indice 2
102/138
Les tableaux
accs un lment dun tableau Le nom du tableau doit tre suivi par une expression place entre parenthses. Lexpression est value lexcution et reprsente lindice. exemple : t(3) = 12.5
i=2 debug.print t(i+1)
Une variable indice reprsentant un accs un lment d'un tableau peut s'utiliser partout o une variable normale peut tre utilise. A lexcution, il est interdit que lindice ait une valeur plus petite que la borne infrieure du tableau ou plus grande que lindice maximum indiqu dans la dfinition du tableau. Si tel est quand mme le cas, lexcution sarrte avec un message derreur. Remarque : DEBUG.PRINT affiche la valeur de ses arguments dans la fentre "Immediate" de l'environnement de dveloppement !
103/138
Les tableaux
Exemple : crivons un programme qui cre un tableau de nombres, les trie en ordre croissant, puis les affiche dans la fentre "Immediate"
Option Explicit Option Base 1 Sub main() Const maxValue As Integer = 40 Const maxArraySize As Integer = 20 Dim t(maxArraySize) As Single Dim i As Integer, j As Integer, ind_max As Integer Dim max As Single, tmp As Single ' crer les valeurs entires au hasard entre 1 et maxvalue For i = LBound(t) To UBound(t) t(i) = Int(maxValue * Rnd + 1) Next i
VBA prvoit deux primitives pour accder respectivement aux valeurs de la borne suprieure et de la borne infrieure d'un tableau, savoir UBOUND() et LBOUND(). Elles admettent toutes les deux le tableau comme argument. VBA, comme la plupart des langages de programmation modernes, supporte le concept de constante. Une constante dfinit un nom symbolique qui sert identifier une valeur. Le nom dune constante peut tre utilis par la suite, dans le domaine de dfinition de lidentificateur de constante, en lieu et place de la valeur. La valeur attache au nom symbolique ne peut plus tre modifie dans le programme. Les avantages du concept de constante sont multiples : le programme est plus lisible. Au lieu de contenir des valeurs obscures, il contient un texte en clair dcrivant au mieux la valeur ; le programme est plus facilement maintenable car il suffit en gnral de modifier la valeur de la constante en un endroit et puis de recompiler le programme. Dans le cas contraire, le programmeur doit vrifier ligne par ligne son code source et corriger les valeurs manuellement, ce qui nest pas sans risque derreur ; le fait quune valeur soit dfinie comme une constante interdit au programmeur de changer accidentellement cette valeur. En effet, bien quune constante ait un identificateur tout comme une variable, le compilateur ne permet pas de lutiliser comme une variable et affiche un message derreur le cas chant.
104/138
Les tableaux
'trier les valeurs ' afficher les valeurs i = UBound(t) For i = LBound(t) To UBound(t) Debug.Print t(i); While i > LBound(t) Next i max = t(1): ind_max = 1 Debug.Print For j = 2 To i End Sub If t(j) > max Then ind_max = j: max = t(j) End If Next j ' ind_max pointe sur le maximum de 1 i. Mettons-le sa place tmp = t(i): t(i) = t(ind_max): t(ind_max) = tmp i=i-1 Wend ...
...
La fonction prdfinie RND() renvoie un nombre pseudo-alatoire compris entre 0 inclus et 1 exclus. Il existe beaucoup de faons de trier des lments. Une mthode simple, mais pas trs efficace est le tri par slection. Il fonctionne d'aprs le principe suivant : slectionner l'lment du tableau ayant la plus grande cl ; changer cet lment avec le dernier lment du sous-tableau non encore tri. Un lment vient d'tre tri. Appliquer la mthode sur le soustableau restant non encore tri. Remarque : En VBA, il est permis d'crire plusieurs instructions sur une mme ligne si elles sont spares par le symbole ":".
105/138
Les tableaux
un tableau peut tre utilis comme argument d'une fonction
il doit tre pass par rfrence l'argument formel correspondant doit tre marqu par une paire ()
Exemples : Sub init_array(t() As Single) Dim i As Integer For i = LBound(t) To UBound(t) t(i) = Int(maxValue * Rnd + 1) Next i End Sub Sub display_array(t() As Single) Dim i As Integer For i = LBound(t) To UBound(t) Debug.Print t(i); Next i Debug.Print End Sub
106/138
Les tableaux
Exemple :
Sub tri_fonction() Const maxArraySize As Integer = 20 Dim t(maxArraySize) As Single ' crer les valeurs entires au hasard Call init_array(t) 'trier les valeurs Call sort_array(t) ' afficher les valeurs display_array t End Sub
Sub sort_array(t() As Single) Dim i As Integer, j As Integer, ind_max As Integer Dim max As Single, tmp As Single i = UBound(t) While i > LBound(t) max = t(1): ind_max = 1 For j = 2 To i If t(j) > max Then ind_max = j: max = t(j) End If Next j ' ind_max pointe sur le maximum de 1 i. Mettons-le sa place tmp = t(i): t(i) = t(ind_max): t(ind_max) = tmp i=i-1 Wend End Sub
107/138
Les tableaux
un tableau dynamique
est un tableau dont la taille n'est pas fixe l'avance le programmeur peut l'ajuster sa guise pendant l'excution MAIS : la modification de la taille d'un tableau est une opration coteuse !
Il existe des situations o la taille d'un tableau ne peut tre estime convenablement l'avance. VBA propose au programmeur le concept de tableau dynamique.
108/138
Les tableaux
dclaration d'un tableau dynamique
DIM t() AS single
ajustage de la taille
en prservant les lments dj contenus dans le tableau
REDIM PRESERVE
Pour dclarer un tableau dynamique, il suffit de ne pas indiquer de taille pour le tableau. Par la suite, si on veut placer des lments dans le tableau, celui-ci doit tre redimensionn l'aide de l'instruction REDIM afin de rserver de l'espace mmoire pour ces lments. Dans l'instruction REDIM, il faut indiquer le nom du tableau ainsi que le nombre d'lments que l'on souhaite qu'il contienne. En fait, cette instruction provoque, de manire interne, la cration d'un nouveau tableau de la taille dsire. En utilisant l'option PRESERVE, les valeurs existantes sont recopies de l'ancien tableau dans le nouveau, hauteur du nombre d'lments dfinis dans le nouveau.
109/138
Les tableaux
Dim t() As Integer, i As Integer Dim maxValue As Integer maxValue = InputBox("Combien d'lments ?") ReDim t(maxValue) ' crer les valeurs entires au hasard For i = LBound(t) To UBound(t) t(i) = Int(maxValue * Rnd + 1) Next i ' afficher les valeurs For i = LBound(t) To UBound(t) Debug.Print t(i); Next i Debug.Print
... ' diminuer la taille du tableau ReDim Preserve t(4) ' afficher les valeurs For i = LBound(t) To UBound(t) Debug.Print t(i); Next i Debug.Print ' augmenter la taille du tableau ReDim Preserve t(7) ' afficher les valeurs For i = LBound(t) To UBound(t) Debug.Print t(i); Next i Debug.Print
A l'excution, ce programme affiche 1 4 10 4 3 6 4 5 1 6 3 11 1 4 10 4 1 4 10 4 0 0 0 dans la fentre "Immediate". Nous constatons que lorsque le tableau est redimensionn une valeur plus grande, ces nouveaux lments sont initialiss la valeur par dfaut de leur type.
110/138
Les tableaux
un tableau peut tre multi-dimensionnel
jusqu' 60 dimensions en pratique 2 ou 3 dimensions (matrices, etc.)
il suffit d'indiquer le nombre d'lments dans chaque dimension dans LBound() et UBound(), il faut indiquer un deuxime argument, le numro de dimension
Pour dfinir un tableau multi-dimensionnel, il suffit d'indiquer le nombre d'lments pour chaque dimension, dans les formats vus pour les tableaux statiques. Si on veut utiliser les fonctions LBound() et UBound(), on doit utiliser comme deuxime paramtre le numro de la dimension. Un tableau dynamique peut aussi tre multi-dimensionnel. Mais si on utilise l'instruction REDIM avec l'option PRESERVE, on ne peut modifier dynamiquement le nombre de dimensions et uniquement la taille de la dernire dimension peut tre change. Par contre, sans PRESERVE, le programmeur peut changer aussi bien le nombre de dimensions que la taille de celles-ci.
111/138
Les tableaux
Const NbreLignes As Integer = 5 Const NbreColonnes As Integer = 7 Const maxValue As Integer = 40 Dim t(NbreLignes, NbreColonnes) As Integer Dim i As Integer, j As Integer ' crer les valeurs entires au hasard For i = LBound(t, 1) To UBound(t, 1) For j = LBound(t, 2) To UBound(t, 2) t(i, j) = Int(maxValue * Rnd + 1) Next j Next i ...
... ' afficher les valeurs For i = LBound(t, 1) To UBound(t, 1) For j = LBound(t, 2) To UBound(t, 2) Debug.Print t(i, j); Next j Debug.Print Next i Debug.Print
Ce programme cre une matrice de 5 lignes et 7 colonnes. Elle est initialise avec des nombres alatoires et puis la matrice est affiche. Voici une trace d'excution : 38 40 24 22 25 4 8 12 1 7 17 22 23 32 2 17 3 13 25 21 24 14 37 31 24 18 30 7 3 10 31 39 14 28 32
112/138
L'enregistrement
en VBA, le programmeur peut crer ses propres types en se basant sur les types existants un enregistrement (record) se compose dun nombre fixe dlments, de types ventuellement diffrents. ces diffrents composants et leurs types sont dfinis par la liste des champs de lenregistrement. lordre des champs na pas dimportance.
Jusqu prsent nous avions la possibilit de dfinir des variables simples de type integer, single,etc. ou alors des variables de type tableau, o chacun des lments du tableau tait du mme type. Avec le concept denregistrement, nous avons la possibilit de dfinir des variables de type complexe par composition (agglomration) de types existants. Chaque lment faisant partie de lenregistrement est appel un champ. Le type du champ est quelconque, pourvu quil soit dfini. Lordre dans lequel les champs sont dclars dans la dfinition de lenregistrement na pas dimportance.
113/138
L'enregistrement
exemple : les nombres rationnels sont des nombres de la forme a/b o a et b sont deux entiers avec b 0. comment reprsenter lgamment ce concept dans VBA ? solution : lenregistrement
Tout comme dans le cas des tableaux, une dfinition denregistrement ne peut tre rcursive. Ceci signifie que le type denregistrement en cours de dfinition ne peut tre utilis comme type dun champ de lenregistrement. Pour notre exemple, nous crirons par exemple : Type rationnel numerateur As Integer denominateur As Integer End Type
114/138
L'enregistrement
laccs un champ dun enregistrement seffectue par le symbole . un objet de type enregistrement peut tre utilis comme argument formel/effectif mais doit tre pass par rfrence la valeur dune fonction ne peut tre un enregistrement il est permis de faire des affectations entre deux objets du mme type enregistrement
Pour accder un champ dun enregistrement, il suffit dindiquer le nom de lenregistrement, suivi du symbole . et du nom du champ en question. A lintrieur dun enregistrement, tous les identificateurs de champs doivent tre uniques et ne doivent pas tre des mots rservs. Le symbole . peut videmment tre utilis en cascade si un champ dun enregistrement est lui-mme un enregistrement. Tout comme pour les tableaux, il est permis dutiliser comme argument formel/effectif un objet de type record, mais une fonction ne peut retourner comme valeur un record et un tel objet doit obligatoirement tre pass par rfrence. Il est de mme permis deffectuer des affectations entre des objets de mme type record.
115/138
L'enregistrement
Option Explicit Type rationnel numerateur As Integer denominateur As Integer End Type Sub init_rat(num As Integer, denom As Integer, r As rationnel) r.numerateur = num r.denominateur = denom End Sub Sub affiche_rat(r As rationnel) Debug.Print r.numerateur; "/"; r.denominateur End Sub
116/138
L'enregistrement
Sub add_rat(r1 As rationnel, r2 As rationnel, r As rationnel) r.numerateur = (r1.numerateur * r2.denominateur) + (r2.numerateur * r1.denominateur) r.denominateur = r1.denominateur * r2.denominateur End Sub Sub main() Dim r1 As rationnel, r2 As rationnel, r3 As rationnel Call init_rat(1, 3, r1) ' affiche 1 / 3 Call init_rat(2, 5, r2) ' affiche 2 / 5 Call affiche_rat(r1) affiche_rat r2 Call add_rat(r1, r2, r3) affiche_rat r3 End Sub ' affiche 11 / 15
117/138
Le traitement d'erreurs
une erreur l'excution (fichier non trouv, division par 0, etc.) provoque l'arrt brutal du programme VBA offre des primitives de gestion d'erreurs d'excution :
On Error GoTo nom_paragraphe On Error Resume Next On Error GoTo 0
On Error GoTo nom_paragraphe indique au systme qu'en cas d'erreur d'excution, l'excution ne doit pas s'arrter mais continuer l'endroit indiqu par nom_paragraphe. Un paragraphe est une endroit dans une procdure ou fonction dont le dbut est indiqu par nom_ paragraphe suivi de ":". On Error Resume Next dans ce cas, on ignore l'erreur et l'excution continue l'instruction suivante ! On Error GoTo 0 sert dsactiver le gestionnaire d'erreur instaur par le programmeur et ractiver le comportement par dfaut de VBA. L'objet prdfini Err permet au programmeur de s'informer sur le type de l'erreur travers les proprits Number et Description.
118/138
Le traitement d'erreurs
Exemple :
Public Sub DivisionPar0Geree() On Error GoTo GestionnaireErreur Dim nbre As Integer nbre = InputBox("Entrez un nombre", "Calcul de l'inverse d'un nombre") MsgBox ("L'inverse de " & nbre & " = " & 1 / nbre) Exit Sub GestionnaireErreur: MsgBox "Tentative de division par 0" & vbNewLine & "Code d'erreur : " & Err.Number _ & vbNewLine & "Message : " & Err.Description End Sub
Dans un gestionnaire d'erreur, le programmeur peut utiliser les instructions suivantes : Resume l'instruction ayant provoqu l'erreur est excute nouveau Resume Next l'excution continue l'instruction suivant logiquement celle qui a provoqu l'erreur Resume nom_paragraphe l'excution continue la premire instruction du paragraphe dsign par nom_paragraphe Attention : cette instruction ne peut tre utilise que dans un gestionnaire d'erreurs.
119/138
Lutilisation de DLLs
Une DLL (Dynamic Link Library) est une bibliothque de fonctions. Il existe des DLL systme mais le programmeur peut crire ses propres DLL en C, C++, VB, etc. Les DLL systme constituent l'API (Application Programming Interface) Windows, donnant l'accs quasi toutes les fonctions systme de Windows.
L'utilisation de fonctions systme dfinies dans des DLL ncessite de bonnes connaissances et une bonne documentation non fournie avec Office de manire standard. Il peut tre intressant de savoir qu'un programmeur VBA peut aller au-del des possibilits offertes intrinsquement par le langage en faisant appel des fonctions systme de Windows excuter un travail critique en temps par une routine compile.
120/138
Lutilisation de DLLs
Une fonction dfinie dans une DLL doit tre dclare pralablement son utilisation au niveau global dans un module.
DECLARE SUB NomSub LIB "NomLib" (ListeParamtres) DECLARE FUNCTION NomFunc LIB "NomLib" (ListeParamtres) AS NomType
La liste des paramtres peut tre prcde par la clause ALIAS NomAlias qui dsigne le nom effectif de la fonction dans la DLL. Ceci peut tre intressant si ce nom original de la routine est un mot rserv en VBA, dbute par un _, etc. Il faut faire trs attention aux problmes de correspondance dans la liste des paramtres et du type de la fonction entre les types VBA et les types C/C++ (la plupart des DLL sont ralises dans ces langages). De ce fait, il faut quasi toujours passer les arguments par valeur (BYVAL), mode de transmission par dfaut dans ces deux langages mais pas en VBA ! Ainsi les types C suivants ont les quivalents suivants en VBA C VBA BYTE x ByVal x As Byte LPBYTE x x As Byte short x ByVal x As Integer short far * x x As Integer LONG x ByVal x As Long LPLONG x x As Long float x ByVal x As Long float far * x x As Long double x ByVal x As Double double far * x x As Double
121/138
Lutilisation de DLLs
Declare Sub RenvoieRepertoireWindows Lib "kernel32" Alias "GetWindowsDirectoryA" _ (ByVal lpBuffer As String, ByVal nSize As Long) Function NullString(x As String) NullString = Left(x, InStr(x, Chr(0)) - 1) End Function Function WinDir() As String Dim tmp As String tmp = Space(256) Call RenvoieRepertoireWindows(tmp, 255) Sub AfficheRepertoireWindows() WinDir = NullString(tmp) MsgBox WinDir(), , "Rpertoire Windows" End Function
End Sub
Une chane de caractres C est une suite contingu de caractres termine par un 0 binaire. De plus, il faut que le programmeur ait dj rserv une chane de caractres VBA avec suffisamment de place pour recevoir la chane de caractres C de la part de la fonction DLL appele, sous peine de voir cette dernire n'importe o dans la mmoire de l'espace VBA !
122/138
Le concept de classe
VBA intgre des concepts modernes tel que
classe objet masquage d'information
Lobjet est le concept central en programmation oriente objet. Cest lentit de base lors de lexcution dun programme. Un objet occupe de la place en mmoire centrale et les donnes quil contient dterminent son tat. Mais en plus de son tat, il contient toutes les fonctions dterminant son comportement. Cest ce quon appelle gnralement lencapsulation. Cette technique permet de garder ensemble et de considrer comme un tout les donnes et les fonctions modlisant une entit. Lencapsulation rduit donc la dispersion des donnes et des fonctions, et permet au programmeur de mieux apprhender et rduire la complexit dun problme. Bien que les informations soient toutes emmagasines dans un objet, cela ne signifie nullement quelles soient toutes accessibles.
123/138
Le concept de classe
encapsulation masquage d'information
Lensemble des informations dun objet est divis en deux parties : une partie publique, visible et accessible en dehors de lobjet ; une partie prive, invisible et inaccessible en dehors de lobjet. Cette partie dinformations est bien sr accessible et utilisable par les fonctions membres de lobjet. Cest le principe du masquage dinformation, trs utile pour implanter de faon effective un niveau dabstraction en cachant lutilisateur le comment de limplmentation de lobjet. Le masquage dinformation permet aussi de crer par la suite du code plus facilement modifiable et maintenable. Comme les utilisateurs ne savent pas comment une opration est ralise, mais uniquement ce quelle produit comme effet sur lobjet, il est possible de changer la ralisation de lopration (gnralement pour la rendre plus efficace) sans rpercussions ngatives pour les utilisateurs de lobjet.
124/138
Le concept de classe
communication avec un objet
messages mthodes
La communication avec un objet ne peut se faire qu travers son interface publique. Elle est ralise en envoyant un message lobjet, cest--dire le nom dune opration avec les arguments adquats. Le comportement de lobjet est dfini comme lensemble des messages auxquels il peut rpondre. Lors de la rception dun message, il excute ce quon appelle une mthode, ou plus simplement une fonction ralisant lopration associe au message.
125/138
Le concept de classe
une classe dfinit un ensemble potentiel dobjets c'est une description statique
Une classe dfinit un ensemble potentiel dobjets. Tout objet rsulte, au moment de lexcution du programme, de linstanciation dune classe existante. Une classe est quant elle une description statique, fige dans le programme de lensemble potentiel dobjets instanciables. On utilise souvent une mtaphore pour faire comprendre la distinction entre lobjet et la classe : lusine (la classe) fabrique des produits (les objets). Le programmeur a videmment la possibilit de prciser la faon dont un objet doit tre produit. Dans le programme, on ne voit que des classes ; lexcution, il nexiste que des objets. Ce comportement est comparable celui dun type. En fait, dfinir une classe quivaut dfinir un type nouveau.
126/138
Le concept de classe
En VBA, le concept de classe (class module) est un outil de rutilisation de code.
Le programmeur peut insrer (crer) un ou plusieurs "class module" dans son projet. Un module cr pour un projet peut tre aussi tre export sous forme de fichier ayant l'extension cls. Un tel fichier peut alors tre import dans un autre projet : rutilisation de code !
127/138
Le concept de classe
Exemple :
cration de la classe Rationnel implmentant les nombres rationnels interface :
mthodes :
init add affiche numerateur denominateur initialisation d'un rationnel addition de deux rationnels affichage d'un rationnel accesseur et modificateur du numrateur accesseur et modificateur du dnominateur
Pour illustrer le concept de classe en VBA, nous crons la classe Rationnel partir de laquelle nous pourrons instancier des objets par la suite. Ces objets ne seront manipulables par le programmeur qu' travers leur interface publique compose des cinq mthodes (fonctions) publiques indiques plus haut.
128/138
Le concept de classe
en VBA :
le nom du module de classe est le nom de la classe, c'est--dire le nom du type
Le programmeur doit choisir avec soin le nom du module de classe. Ce nom sera en effet le nom du type des objets instancis sur base de la dfinition de cette classe. Nous adoptons la convention d'crire le premier caractre de ce nom en majuscules.
129/138
Le concept de classe
Private pNumerateur As Integer Private pDenominateur As Integer Sub init(ByVal num As Integer, ByVal denom As Integer) Sub affiche() Sub add(ByVal r As Rationnel, r1 As Rationnel) Public Property Get Numerateur() As Integer Public Property Get Denominateur() As Integer Public Property Let Numerateur(ByVal num As Integer) Public Property Let Denominateur(ByVal denom As Integer) Private Sub normaliser(num As Integer, denom As Integer) Private Function pgcd(ByVal n1 As Integer, ByVal n2 As Integer) As Integer
Ce transparent illustre l'interface complte de la classe Rationnel. Elle comprend les procdures init, affiche et add sous une forme connue. Par contre, la procdure normaliser ainsi que la fonction pgcd sont diffrentes en ce sens quels sont dclares prives (private). Cela signifie que ces deux sousprogrammes ne peuvent tre utilises que dans le ce module de classe. Ils sont inaccessibles en-dehors de ce dernier. Par dfaut, lorsque le programmeur omet de spcifier public ou private, le systme considre qu'il s'agit d'une dfinition publique ! La classeRationnel dfinit deux donnes membres prives : pNumerateur et pDenominateur (par convention, nous utilisons le prfixe p pour indiquer qu'il s'agit d'une donne prive). Tout objet instanci par la suite partir de la classe Rationnel contiendra ces deux champs, mais le programmeur ne pourra les accder directement. Il devra passer par les procdures prvues cet effet : Property Get et Property Let (il existe encore une Property Set). Property Let sert changer la valeur d'une donne membre de type autre qu'objet tandis que Property Get sert accder en lecture une donne membre. Property Set sert changer la valeur d'une donne membre de type objet.
130/138
Le concept de classe
Public Sub init(ByVal num As Integer, ByVal denom As Integer) Call normaliser(num, denom) Dim tmp As Integer tmp = pgcd(Abs(num), Abs(denom)) pNumerateur = IIf(denom < 0, -num, num) / tmp pDenominateur = IIf(denom < 0, -denom / tmp, denom / tmp) End Sub Private Sub normaliser(num As Integer, denom As Integer) ' normaliser : seul le numrateur est ventuellement ngatif num = IIf(denom < 0, -num, num) denom = IIf(denom < 0, -denom, denom) End Sub
Private Function pgcd(ByVal n1 As Integer, ByVal n2 As Integer) As Integer n1 = Abs(n1) n2 = Abs(n2) While n1 <> n2 If n1 > n2 Then n1 = n1 - n2 Else n2 = n2 - n1 End If Wend pgcd = n1 End Function
La procdure init a le droit d'appeler les pgcd et normaliser qui sont dfinies PRIVATE. L'utilisteur final de la classe Rationnel n'est pas autoris le faire !
131/138
Le concept de classe
Public Property Get Numerateur() As Integer Numerateur = pNumerateur End Property Public Property Get Denominateur() As Integer Denominateur = pDenominateur End Property Public Property Let Numerateur(ByVal num As Integer) pNumerateur = num End Property Public Property Let Denominateur(ByVal denom As Integer) pDenominateur = denom End Property
Property Let/Set/Get sont des fonctions/procdures permettant de manipuler les donnes membres de la classe : ici pNumerateur et pDenominateur. Le programmeur, utilisateur de la classe Rationnel ne connatra pas les noms des donnes membres. Il les manipule via les Property Numerateur et Denominateur !
132/138
Le concept de classe
Sub add(ByVal r As Rationnel, r1 As Rationnel) Dim num As Integer, denom As Integer num = (pNumerateur * r.Denominateur) + (r.Numerateur * pDenominateur) denom = pDenominateur * r.Denominateur Dim tmp As Integer tmp = pgcd(Abs(num), Abs(denom)) num = num / tmp denom = denom / tmp Call normaliser(num, denom) r1.Numerateur = num r1.Denominateur = denom End Sub Sub affiche() Debug.Print pNumerateur; "/"; pDenominateur End Sub
Les mthodes de la classe ont le droit d'accder aux donnes membres sans passer par les Property. L'objet excutant la mthode Add additionne l'argument r " soi-mme" et renvoie le rsultat travers l'argument r1. L'accs une donne membre publique ou une fonction/procdure/property publique d'un objet s'crit : objet.donne/fonction/procdure/property
133/138
Le concept de classe
Dim r1 As Rationnel, r2 As Rationnel Dim r3 As Rationnel, r4 As Rationnel Set r1 = New Rationnel Set r2 = New Rationnel r1.init 1, 3 r2.init 2, 5 r1.affiche '1/3 r2.affiche '2/5 Set r3 = New Rationnel Call r1.add(r2, r3) r3.affiche ' 11 / 15
' r1 = r3 ' ERREUR r1 et r3 sont des objets Set r1 = r3 r1.affiche ' 11 / 15 Set r4 = New Rationnel Call r4.init(2, -4) r4.affiche '- 1 / 2 r1.Numerateur = 1: r1.Denominateur = 3 r2.Numerateur = 2: r2.Denominateur = -4 r1.add r2, r3 r3.affiche '- 1 / 6
Pour l'utilisateur final de la classe Rationnel, Rationnel est un nouveau type. De manire interne, une variable de type classe est en fait un pointeur sur un objet de cette classe. L'instruction DIM ne fait que de dclarer le pointeur et c'est l'aide du mot-cl NEW que l'objet est cr dans la mmoire de l'ordinateur. Pour affecter une nouvelle valeur un objet, il faut obligatoirement utiliser l'instruction SET. Comme le montre cet exemple, une fonction ou une procdure membre peut tre appele avec la syntaxe d'une fonction ou procdure normale. Une property par contre s'utilise comme si c'tait une donne membre !
134/138
Le concept de classe
Set r1 = New Rationnel r1.init 1, 3 r1 1 3
R1 et r2 pointent en fait chacun sur un objet de type Rationnel. Dans le jargon informatique, on dit que ce sont des pointeurs.
135/138
Le concept de classe
Set r1 = r2
r1 Cet objet est devenu inaccessible ! 1 3
En travaillant avec des pointeurs, il faut toujours faire attention ne pas perdre involontairement lobjet sur lequel on pointe. Lorsque lon veut se dbarasser explicitement dun objet devenu inutile, il suffit de lui affecter la valeur nothing.
136/138
Le concept de classe
Private Sub Class_Initialize() Numerateur = 0 Denominateur = 1 Debug.Print "Cration du rationnel " & Me.Numerateur & "/" & Me.Denominateur End Sub Private Sub Class_Terminate() Debug.Print "Destruction du rationnel " & Me.Numerateur & "/" & Me.Denominateur End Sub
A ct des fonctions et procdures applicables sur des objets, il existe deux procdures de classe, lies aux vnements Initialize et Terminate. Lorsquun objet est cr, automatiquement la procdure Class_Initialize est invoque sans que le programmeur ait le faire explicitement, sous rserve videmment davoir dfini une action pour cet vnement. De mme, lorsquun objet vient mourir, cest--dire quil est dtruit parce quaucun pointeur ne pointe plus sur lui, automatiquement, la procdure de classe Class_Terminate est excute, sous rserve quelle a t dfinie.
137/138
Le concept de classe
Sub testNothing() Dim r1 As Rationnel Set r1 = New Rationnel r1.affiche Set r1 = Nothing Set r1 = New Rationnel r1.init 3, 8 r1.affiche End Sub
Cration du rationnel 0/1 0/1 Destruction du rationnel 0/1 Cration du rationnel 0/1 3/8 Destruction du rationnel 3/8
A ct des fonctions et procdures applicables sur des objets, il existe deux procdures de classe, lies aux vnements Initialize et Terminate. Lorsquun objet est cr, automatiquement la procdure Class_Initialize est invoque sans que le programmeur ait le faire explicitement, sous rserve videmment davoir dfini une action pour cet vnement. De mme, lorsquun objet vient mourir, cest--dire quil est dtruit parce quaucun pointeur ne pointe plus sur lui, automatiquement, la procdure de classe Class_Terminate est excute, sous rserve quelle a t dfinie.
138/138