Cours VBA : les procédures et fonctions

Public - Private

Pour le moment, toutes les procédures créées sont de type Public, elles sont accessibles depuis tous les modules.

Sub exemple()

'Est identique à :

Public Sub exemple()

Pour rendre une procédure inaccessible hors du module, ajoutez Private :

Private Sub exemple()

Lancer une procédure depuis une procédure

Pour exécuter une procédure depuis une autre procédure, entrez simplement son nom.

Un exemple simple :

Private Sub avertissement()

    MsgBox "Attention !!!"

End Sub

Sub exemple()

    If Range("A1") = "" Then
        avertissement '<= exécute la procédure "avertissement"
    End If

End Sub

Ici, lorsque la procédure exemple est lancée et que A1 vaut "", la procédure avertissement est exécutée et affiche la boîte de dialogue.

Les arguments

Les arguments permettent de transmettre des valeurs d'une procédure à une autre (car rappelez-vous que par défaut les variables ne sont pas accessibles depuis les autres procédures).

Ajout d'un argument texte à la procédure avertissement :

Private Sub avertissement(texte As String)

    MsgBox "Attention : " & texte & " !"

End Sub

Sub exemple()

    If Range("A1") = "" Then 'Si A1 est vide
        avertissement "cellule vide"
    ElseIf Not IsNumeric(Range("A1")) Then 'Si A1 est non numérique
        avertissement "valeur non numérique"
    End If

End Sub
test procedures fonctions

L'argument ajouté à la procédure avertissement est de type String :

Private Sub avertissement(texte As String)

Pour exécuter la procédure avertissement, il faudra donc entrer en argument une valeur de type String :

avertissement "cellule vide"

En cas d'arguments multiples, ceux-ci doivent être séparés par des virgules.

Les arguments optionnels

Par défaut, si une procédure requiert des arguments, ceux-ci sont obligatoires pour exécuter la procédure.

Des arguments optionnels peuvent toutefois être ajoutés après les arguments obligatoires avec Optional, par exemple :

Private Sub boiteDialogue(nom As String, Optional prenom, Optional age)

Cette procédure peut alors être lancée avec ou sans arguments optionnels, comme ceci :

'Exemple 1 : on affiche le nom
boiteDialogue nom
    
'Exemple 2 : on affiche le nom et le prénom
boiteDialogue nom, prenom
    
'Exemple 3 : on affiche le nom et l'âge
boiteDialogue nom, , age
    
'Exemple 4 : on affiche le nom, le prénom et l'âge
boiteDialogue nom, prenom, age

Les arguments doivent être indiqués dans l'ordre.

Pour vérifier si un argument optionnel est présent ou non, nous utiliserons la fonction IsMissing. Cette fonction n'étant compatible qu'avec certains types de variables (dont Variant), le type des arguments optionnels n'a pas été déclaré (type non déclaré = Variant).

Voici un exemple avec les 2 portions de code ci-dessus :

Sub exemple()

    Dim nom As String, prenom As String, age As Integer
    
    nom = Range("A1")
    prenom = Range("B1")
    age = Range("C1")

    'Exemple 1 : on affiche le nom
    boiteDialogue nom
    
    'Exemple 2 : on affiche le nom et le prénom
    boiteDialogue nom, prenom
    
    'Exemple 3 : on affiche le nom et l'âge
    boiteDialogue nom, , age
    
    'Exemple 4 : on affiche le nom, le prénom et l'âge
    boiteDialogue nom, prenom, age

End Sub

Private Sub boiteDialogue(nom As String, Optional prenom, Optional age)

    'Si l'âge est manquant
    If IsMissing(age) Then
        
        If IsMissing(prenom) Then 'Si le prénom est manquant, on n'affiche que le nom
            MsgBox nom
        Else 'Sinon, on affiche le nom et le prénom
            MsgBox nom & " " & prenom
        End If

    'Si l'âge a été renseigné
    Else

        If IsMissing(prenom) Then 'Si le prénom est manquant, on affiche le nom et l'âge
            MsgBox nom & ", " & age & " ans"
        Else 'Sinon on affiche le nom, le prénom et l'âge
            MsgBox nom & " " & prenom & ", " & age & " ans"
        End If
    
    End If
       
End Sub

Aperçu (avec nom prénom et âge) :

test2 procedures fonctions

Il est également possible de renseigner des valeurs par défaut aux arguments optionnels et de tester ensuite ces valeurs (au lieu d'utiliser la fonction IsMissing) :

Private Sub boiteDialogue(nom As String, Optional prenom As String = "", Optional age As Integer = 0)

    'Si l'âge est manquant
    If age = 0 Then
        
        If prenom = "" Then 'Si le prénom est manquant, on n'affiche que le nom
            MsgBox nom
        Else 'Sinon, on affiche le nom et le prénom
            MsgBox nom & " " & prenom
        End If

    'Si l'âge a été renseigné
    Else

        If prenom = "" Then 'Si le prénom est manquant, on n'affiche que le nom
            MsgBox nom & ", " & age & " ans"
        Else 'Sinon on affiche le nom, le prénom et l'âge
            MsgBox nom & " " & prenom & ", " & age & " ans"
        End If
    
    End If
       
End Sub

ByRef - ByVal

Par défaut, les arguments sont de type ByRef ce qui signifie que, si une variable est passée en argument, c'est sa référence qui est transmise. Autrement dit, si la variable est modifiée dans la sous-procédure, elle le sera également dans la procédure d'appel.

Par exemple :

Sub exemple()

    Dim nombre As Integer
    nombre = 30

    carre nombre
   
    MsgBox nombre

End Sub

Private Sub carre(ByRef valeur As Integer) 'Il n'est pas nécessaire de préciser ByRef (type par défaut)

    valeur = valeur ^ 2

End Sub

Pour mieux comprendre, voici ce qui se passe lorsque la macro est lancée :

'La valeur initiale de la variable "nombre" est 30
nombre = 30

'La sous-procédure est lancée avec la variable "nombre" en argument
carre nombre

'La variable "valeur" fait référence à la variable "nombre" passée en argument, par conséquent si la variable "valeur" est modifiée, la variable "nombre" le sera aussi
Private Sub carre(ByRef valeur As Integer)

'La valeur de la variable "valeur" est modifiée (donc la variable "nombre" aussi)
valeur = valeur ^ 2

'Fin de la sous-procédure
End Sub

'La variable "nombre" a été modifiée, 900 est alors affiché dans la boîte de dialogue
MsgBox nombre

La seconde possibilité consiste à utiliser ByVal.

Contrairement à ByRef qui fait directement référence à la variable, ByVal transmet uniquement sa valeur, ce qui signifie que la variable passée en argument ne subit aucune modification.

Voici ce qui se passe avec le code précédent et ByVal :

'La valeur initiale de la variable "nombre" est 30
nombre = 30

'La sous-procédure est lancée avec la variable "nombre" en argument
carre nombre

'La variable "valeur" copie la valeur de la variable "nombre" (les 2 variables ne sont pas liées)
Private Sub carre(ByVal valeur As Integer)

'La valeur de la variable "valeur" est modifiée
valeur = valeur ^ 2

'Fin de la sous-procédure (dans cet exemple, la sous-procédure n'aura servi à rien)
End Sub

'La variable "nombre" n'a pas été modifiée, 30 est donc affiché dans la boîte de dialogue
MsgBox nombre

Les fonctions

La principale différence entre Sub et Function est qu'une fonction retourne une valeur.

En voici un exemple simple :

Function carre(nombre As Double)

    carre = nombre ^ 2 'La fonction "carre" retourne la valeur de "carre"

End Function

Sub exemple()

    Dim resultat As Double
	
    resultat = carre(9.876) 'La variable resultat reçoit la valeur retournée par la fonction
	
    MsgBox resultat 'Affichage du résultat (ici, le carré de 9.876)
	
End Sub

Vous pouvez remarquer que les arguments d'une fonction sont ajoutés entre () contrairement aux procédures où elles sont superflues.