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

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) :

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.