TOP

VBA-Leçon 9. Procédures et fonctions

Dans tout langage de programmation, il existe des concepts tels que des procédures et des fonctions. Ils ont également été inclus dans le langage de programmation intégré VBA pour Excel.

  • Une fonction est une routine qui renvoie un résultat. Un appel de fonction est une expression et peut être utilisé dans d'autres expressions ou sur le côté droit d'une instruction d'affectation (notée dans VBA par "Function") ;
  • Une procédure est toute routine qui n’est pas une fonction. Marqué dans VBA comme "Sub" (du mot "sous-programme").

  • Procédures (Public - Private)

    À ce stade, toutes les procédures que nous avons créées sont de type Public, ce qui signifie qu'elles sont accessibles depuis n'importe quel module.

    1. Sub example()  
    2.   
    3. 'Identique à:  
    4. Public Sub example()  

    Pour rendre la procédure disponible uniquement dans un certain module, le mot-clé Private est utilisé :

    1. Private Sub example()  

    Exécuter une procédure au milieu d'une autre procédure

    Pour exécuter une procédure depuis une autre procédure, il suffit de saisir son nom.

    En voici un exemple très simple :

    1. Private Sub warning()  
    2.     MsgBox "Caution !!!" '"AVERTISSEMENT!"  
    3. End Sub  
    4.   
    5. Sub macro_test()  
    6.     If Range("A1") = "" Then  
    7.         warning '=> exécuter la procédure "warning"  
    8.     End If  
    9.     'etc...  
    10. End Sub  

    Arguments

    Les arguments permettent d'utiliser les valeurs d'une procédure dans une sous-procédure (rappelons que par défaut, les variables ne sont disponibles que depuis la procédure dans laquelle elles ont été déclarées).

    1. Private Sub warning(var_text As String)  
    2.     MsgBox "Caution : " & var_text & " !"  
    3. End Sub  
    4.   
    5. Sub macro_test()  
    6.     If Range("A1") = "" Then  
    7.         warning "empty cell"               '"cellule vide"  
    8.     ElseIf Not IsNumeric(Range("A1")) Then  
    9.         warning "non-numerical value"      '"valeur non numérique"  
    10.     End If  
    11. End Sub  

    Un argument a été ajouté à la procédure "warning", dans ce cas il s'agit d'une variable "var_text" de type "String" (ruban) :

    1. Private Sub warning(var_text As String)  

    Cette routine prend un argument, nous devons donc mettre une valeur après "warning" pour l'exécuter :

    1. warning "empty cell"  

    Lorsque nous voulons écrire plusieurs arguments, ils doivent alors être séparés par des virgules.

    Arguments facultatifs

    Par défaut, si la procédure a des arguments, alors ils doivent être fournis, et s'ils ne le sont pas, alors la procédure ne sera pas exécutée.

    Un argument facultatif peut être ajouté après un argument obligatoire, à l'aide du mot-clé Optionnel. Exemple:

    1. Private Sub dialog_boxes(last_name As StringOptional first_name, Optional age)  

    Cette procédure peut désormais être exécutée avec ou sans argument optionnel, comme ici :

    1. 'Exemple 1 : afficher le nom :  
    2. dialog_boxes last_name1  
    3.     
    4. 'Exemple 2 : on affiche le nom et le prénom :  
    5. dialog_boxes last_name1, first_name1  
    6.     
    7. 'Exemple 3 : afficher le nom et l'âge :  
    8. dialog_boxes last_name1, , age1  
    9.     
    10. 'Exemple 4 : afficher le nom, le prénom et l'âge :  
    11. dialog_boxes last_name1, first_name1, age1  

    Les arguments doivent être saisis dans le bon ordre.

    Pour tester si un argument facultatif est présent dans une procédure, nous utilisons la fonction IsMissing. Cette fonction n'est compatible qu'avec certains types de fonctions (de type Variant) et cela est critique car le type des arguments optionnels n'a pas été déclaré (type non déclaré = Variant).

    Voici un exemple qui utilise les deux extraits de code évoqués ci-dessus :

    1. Sub macro_test()  
    2.   
    3.     Dim last_name1 As String, first_name1 As String, age1 As Integer  
    4.      
    5.     last_name1 = Range("A1")  
    6.     first_name1 = Range("B1")  
    7.     age1 = Range("C1")  
    8.   
    9.     'Exemple 1 : afficher le nom :  
    10.     dialog_boxes last_name1  
    11.      
    12.     'Exemple 2 : on affiche le nom et le prénom :  
    13.     dialog_boxes last_name1, first_name1  
    14.      
    15.     'Exemple 3 : afficher le nom et l'âge :  
    16.     dialog_boxes last_name1, , age1  
    17.      
    18.     'Exemple 4 : afficher le nom, le prénom et l'âge :  
    19.     dialog_boxes last_name1, first_name1, age1  
    20.   
    21. End Sub  
    22.   
    23. Private Sub dialog_boxes(last_name As StringOptional first_name, Optional age)  
    24.      
    25.     If IsMissing(age) Then 'Si la variable âge est manquante...  
    26.          
    27.         If IsMissing(first_name) Then 'Si la variable prénom_nom est manquante, alors  
    28.                                       'seul le nom de famille sera affiché  
    29.            MsgBox last_name  
    30.         Else 'Sinon, le nom et le prénom seront affichés  
    31.            MsgBox last_name & " " & first_name  
    32.         End If  
    33.          
    34.     Else 'Si la variable âge est présente...  
    35.   
    36.         If IsMissing(first_name) Then 'Si la variable prénom_nom est manquante, alors  
    37.                                       'le nom de famille et l'âge seront affichés  
    38.            MsgBox last_name & ", " & age & " years old"  
    39.         Else 'Dans le cas contraire, le nom, le prénom et l'âge seront affichés  
    40.            MsgBox last_name & " " & first_name & ", " & age & " years old"  
    41.         End If  
    42.      
    43.     End If  
    44.          
    45. End Sub  

    Voir image ci-dessous (exemple 1) :

    ByRef - ByVal

    Par défaut, les arguments sont de type ByRef, ce qui signifie que si une variable est passée en argument, une référence à celle-ci sera également transmise. En d’autres termes, si une variable a été modifiée par une autre sous-procédure, elle sera également modifiée dans la procédure externe qui appelle cette sous-procédure.

    Exemple:

    1. Sub macro_test()  
    2.     Dim var_number As Integer  
    3.       
    4.     var_number = 30  
    5.     calcul_square var_number  
    6.      
    7.     MsgBox var_number  
    8. End Sub  
    9.   
    10. Private Sub calcul_square(ByRef var_value As Integer'ByRef est facultatif  
    11.                                                       '(c'est la valeur par défaut)  
    12.     var_value = var_value * var_value  
    13. End Sub  

    Pour que ce soit clair, voici un exemple de ce qui se passera si l’exécution de la macro démarre :

    1. var_number = 30  
    2. 'La valeur initiale de la variable "var_number" est 30  
    3.   
    4. calcul_square var_number  
    5. 'La sous-procédure est exécutée avec "var_number" comme argument  
    6.   
    7. Private Sub calcul_square(ByRef var_value As Integer)  
    8. 'La variable "var_value" sert dans une certaine mesure à un accès rapide à la variable "var_number",  
    9. 'ce qui signifie que si la variable "var_value" est modifiée, la variable "var_number" sera également modifiée  
    10. '(et ils ne doivent pas nécessairement avoir le même nom)  
    11. var_value = var_value * var_value  
    12. 'La valeur de la variable "var_value" est modifiée (et donc "var_number" est également modifiée en même temps)  
    13.   
    14. End Sub  
    15. 'Fin de la sous-procédure  
    16.   
    17. MsgBox var_number  
    18. 'La variable "var_number" a été modifiée donc 900 sera désormais affiché dans la boîte de dialogue  

    La deuxième méthode consiste à utiliser ByVal.

    Contrairement à ByRef, qui passe une référence (libellé), ByVal passe une valeur, ce qui signifie que la valeur passée en argument n'a pas été modifiée.

    Ci-dessous, vous pouvez voir comment fonctionnent le code précédent et ByVal :

    1. var_number = 30  
    2. 'La valeur initiale de la variable "var_number" est 30  
    3.   
    4. calcul_square var_number  
    5. 'La sous-procédure est exécutée avec "var_number" comme argument  
    6.   
    7. Private Sub calcul_square(ByVal var_value As Integer)  
    8. 'La variable "var_value" copie la valeur de la variable "var_number" (les 2 variables ne sont pas liées)  
    9.   
    10. var_value = var_value * var_value  
    11. 'La valeur de la variable "var_value" a changé  
    12.   
    13. End Sub  
    14. 'Fin de la sous-procédure (dans cet exemple la sous-procédure n'a aucun effet)  
    15.   
    16. MsgBox var_number  
    17. 'La variable "var_number" n'a pas été modifiée et donc 30 sera affiché dans la boîte de dialogue  

    Ce que vous devez retenir : utilisez ByVal lorsque la variable ne doit pas être modifiée.

    Les fonctions

    La principale différence entre une procédure et une fonction est qu'une fonction renvoie une valeur.

    Voici un exemple simple :

    1. Function square(var_number)  
    2.     square = var_number ^ 2 'La fonction "carré" renvoie la valeur "racine carrée"  
    3. End Function  
    4.   
    5. Sub macro_test()  
    6.     Dim result As Double  
    7.     result = square(9.876) 'La variable de résultat reçoit la valeur calculée par la fonction  
    8.     MsgBox result 'Le résultat s'affiche (dans ce cas le carré de 9,876)  
    9. End Sub  

    La fonction peut être utilisée sur une feuille de calcul comme n'importe quelle autre fonction dans Excel.

    Par exemple, pour obtenir le carré de la valeur saisie dans la cellule A1 :