Licence CC BY-NC-SA

Accélérer l'exécution de ses macros VBA sur Excel

À la recherche du temps perdu

Qui ne connait pas Microsoft Excel ? Ce tableur né dans les années 80 a su se faire une place de choix au fil des années.

Une de ses forces est le langage de macro VBA permettant à tout un chacun de réaliser des programmes simples ou complexes. Comme certains aspects de ce langage sont parfois méconnus et qu’il y a une interface de programmation (objets, méthodes, …) propre au logiciel, il arrive bien souvent d’obtenir des macros qui fonctionnent… mais qui prennent du temps, voire beaucoup de temps pour s’exécuter !

Ça tombe bien, car à travers ce billet nous allons voir quelques astuces liées au code pour que nos macros prennent moins de temps.

C’est parti !

Les bonnes pratiques de programmation

Nous commençons ce billet en douceur avec la notion des bonnes pratiques de développement. Ces dernières feront surtout gagner du temps au niveau de la conception et de la réalisation du programme, tout en réduisant les risques d’erreur.

Déclarer les types des variables

Donner un type à une variable, c’est aussi lui donner une certaine taille en mémoire. Le but est de donner le type adéquate à la donnée. De cette manière sa taille sera fixe, ni trop grande, ni trop petite.

Private Sub Exemple_Typage_Variables()
    Dim uneVariable ' Variable non typée
    Debug.Print VarType(uneVariable) ' => 0 : Empty
    uneVariable = "Toto"
    Debug.Print VarType(uneVariable) ' => 8 : String
    
    Dim iUnEntier As Integer ' Variable typée
    iUnEntier = 100
    Debug.Print VarType(iUnEntier)  ' => 2 : Integer
    ' iUnEntier = uneVariable ' => Erreur d'exécution : incompatibilité de types
End Sub

Pour être sûr de ne pas oublier de déclarer le type de vos variables, vous pouvez ajouter Option Explicit au début de votre code. En conséquence, une fenêtre s’ouvrira au moment de l’exécution si des variables ne sont pas déclarées.

Fenêtre erreur de compilation
Fenêtre erreur de compilation

Utiliser des variables

Ne lésinez pas sur les variables, en particulier lorsque les mêmes données reviennent régulièrement. Par exemple, une feuille de calcul utilisée à plusieurs endroits dans le code pourra être chargée une fois.

Option Explicit

Public Sub Exemple_Utilisation_Variables()
    Dim shPage1 As Worksheet
    Set shPage1 = Sheets("Feuil1")
    
    Dim dRecettes As Double, dDepenses As Double
    dRecettes = 12542.45
    dDepenses = 8572.1
    
    shPage1.Range("A1") = "Recettes"
    shPage1.Range("B1") = "Dépenses"
    shPage1.Range("C1") = "Bénéfices"
    
    shPage1.Range("A2") = dRecettes
    shPage1.Range("B2") = dDepenses
    shPage1.Range("C2") = dRecettes - dDepenses
End Sub
Résultat exemple utilisation variables
Résultat exemple utilisation variables

Utiliser des blocs With

Dans le même genre, le bloc With permet d’appliquer de multiples opérations à la suite à un élément en y accédant en une fois.

Public Sub Exemple_Utilisation_Blocs_With()
    With Worksheets("Feuil1")
        With .Range("A1:C1").Font
            .Bold = True
            .Size = 12
        End With
        
        With .Range("A1:C2").Borders
            .LineStyle = xlContinuous
            .ColorIndex = 23
            .Weight = xlThin
        End With
    End With
End Sub
Résultat exemple utilisation blocs With
Résultat exemple utilisation blocs With

Structurer son code

Portée des variables

Si une variable est utilisée à plusieurs endroits, il peut être intéressant de lui donner une portée plus large si ce n’est pas déjà fait afin de la déclarer qu’une seule fois (constantes, …).

Utilisation de procédures et fonctions

Découper son code permet de le rendre plus modulable, donc plus réutilisable, donc plus compréhensible aussi. Chaque procédure ou fonction doit avoir son propre rôle.

Complexité algorithmique

Il existe un domaine de l’informatique pour évaluer la complexité algorithmique. Parfois, la lenteur vient de l’algorithme ! Par exemple, il convient d’éviter d’imbriquer plus de deux boucles ensemble.

Public Sub Exemple_Complexite_Algorithmique()
    Dim i As Integer, j As Integer, k As Integer
    For i = 0 To 10000
        For j = 0 To 10000
            For k = 0 To 10000
                ' à éviter !
            Next k
        Next j
    Next i
End Sub

Au cours de cette première section, nous avons vu qu’en utilisant des variables typées, en intégrant des blocs With et en organisant notre code, nous pouvions gagner du temps à l’exécution, mais surtout à l’écriture de nos programmes.

Les paramètres de l'application

Dans cette seconde section, nous allons nous intéresser aux paramètres de l’application qui nous permettront de gagner du temps dans certains cas.

Les options de calcul des formules

Vous connaissez peut-être les options de calcul des formules dans l’onglet "Formules".

Options de calcul de l'onglet Formules
Options de calcul de l’onglet Formules

En mode automatique, les formules sont recalculées à chaque changement dans les dépendances.

Résultat exemple options calcul des formules
Résultat exemple options calcul des formules

Imaginons une formule faisant la somme d’une colonne. Si au cours du programme, des données sont ajoutées, modifiées ou supprimées dans cette colonne, la formule sera recalculée à chaque fois. Parfois, il est donc judicieux de passer en mode manuel le temps du programme afin de gagner en performance. Cela se fait avec la propriété Calculation de l’objet Application.

Public Sub Exemple_CalculationMode()
    Dim iCalculation As Integer
    iCalculation = Application.Calculation ' Sauvegarde du paramètre initial

    Application.Calculation = xlCalculationManual ' Mode manuel
    
    ' Traitement ...
    
    Application.Calculation = iCalculation ' Rétablissement du paramètre initial
End Sub

Si durant le programme, vous souhaitez recalculer des formules pour accéder aux nouvelles valeurs, vous pouvez utiliser la méthode Calculate sur une feuille ou encore sur l’application.

Voici un récapitulatif des valeurs possibles pour Calculation :

Nom Description
xlCalculationManual calcul lancé par utilisateur
xlCalculationSemiautomatic calcul géré par Excel en ignorant les modifications dans les tableaux
xlCalculationAutomatic calcul géré par Excel

L’option de mise à jour de l’écran

Par défaut, les opérations du programme se déroulent sous nos yeux. Si le programme insère des centaines voire des milliers de lignes, nous les verrons être écrites au fur et à mesure.

Pour désactiver la mise à jour de l’affichage le temps du programme, il est possible de jouer sur le paramètre ScreenUpdating de l’objet Application.

Public Sub Exemple_ScreenUpdating()
    Application.ScreenUpdating = False ' Désactivé
    
    Dim shPage2 As Worksheet
    Dim i As Integer
    
    Set shPage2 = Sheets("Feuil2")
    For i = 1 To 10000
        shPage2.Cells(i, 1) = i
    Next i
    
    Application.ScreenUpdating = True ' Activé
End Sub

En reprenant notre exemple, le résultat sera que les lignes apparaîtront en un coup à l’écran.

L’option des alertes

Selon les instructions, il arrive que l’exécution de macros entraîne l’ouverture de boîtes d’alerte. Ce qui est gênant, c’est que celles-ci bloquent la continuation du programme dans l’attente d’une réponse humaine.

Fenêtre d'alerte
Fenêtre d’alerte

Si vous êtes sûr qu’il n’y a rien de dangereux dans votre programme, vous pouvez désactiver celles-ci avec la propriété DisplayAlerts de l’objet Application.

Public Sub Exemple_DisplayAlerts()
    Application.DisplayAlerts = False ' Désactivé
    
    ' Traitement ...
    
    ' Application.DisplayAlerts = True ' Remis automatiquement à True à la fin
End Sub

Au cours de cette section, nous avons vu que nous pouvions désactiver le calcul automatique des formules, la mise à jour de l’affichage et l’affichage des alertes pendant l’exécution de nos macros, en fonction de nos besoins afin de réduire de façon importante le temps d’exécution.

Lecture et écriture de grands ensembles de données

Dans cette dernière section, nous allons voir qu’il est préférable de travailler sur les plus grands ensembles de données possibles tant en lecture qu’en écriture.

Lire ou écrire une ligne d’un tableau d’un coup est plus rapide que de lire ou écrire celle-ci cellule par cellule. De même, lire ou écrire un tableau par bloc de X lignes est plus rapide que de lire ou écrire celui-ci ligne par ligne. De même, lire ou écrire un tableau d’un coup est plus rapide que lire ou écrire celui-ci par bloc de X lignes.

En VBA, les variables de type Array nous aideront à effectuer cela.

Lecture des données d’un coup

Imaginons que nous ayons un tableau de 10000 lignes contenant le numéro de la ligne.

Tableau de 10000 lignes à lire
Tableau de 10000 lignes à lire

Nous pouvons lire l’intégralité de celui-ci d’un coup comme ceci :

Public Sub Exemple_Lecture_Donnees()
    Dim shPage4 As Worksheet
    Set shPage4 = Sheets("Feuil4")
    
    Dim loTableau1 As ListObject
    Set loTableau1 = shPage4.ListObjects("Tableau1")
    
    Dim vDonnees As Variant
    vDonnees = loTableau1.DataBodyRange.Value
    Debug.Print (VarType(vDonnees)) '=> 8204: Tableau (8192) de variant (12)
End Sub

Écriture des données d’un coup

Voici un exemple VBA écrivant l’intégralité d’un tableau d’un coup :

Public Sub Exemple_Ecriture_Donnees()
    Application.ScreenUpdating = False
    
    ' Construction du tableau 2D
    Dim vDonnees(9999, 2) As Variant
    Dim i As Long
    For i = LBound(vDonnees, 1) To UBound(vDonnees, 1)
        vDonnees(i, 0) = i + 1
        vDonnees(i, 1) = 9999 - i
    Next i
    
    Dim shPage5 As Worksheet
    Set shPage5 = Sheets("Feuil5")
    Dim loTableau2 As ListObject
    Set loTableau2 = shPage5.ListObjects("Tableau2")
    ' Suppression contenu tableau
    If Not loTableau2.DataBodyRange Is Nothing Then
        loTableau2.DataBodyRange.Rows.Delete
    End If
    
    ' Écriture du tableau d'un coup
    loTableau2.ListRows.Add.Range.Resize(UBound(vDonnees, 1), UBound(vDonnees, 2)).Value = vDonnees
    
    Application.ScreenUpdating = True
End Sub

Pendant cette section, nous avons vu qu’il est plus intéressant en terme de performance de travailler sur de grands ensembles de données en lecture et écriture lorsque c’est possible.


C’est déjà la fin de ce billet.

Au cours de celui-ci, nous avons vu trois grandes façons d’accélérer l’exécution de nos macros VBA sur Excel : en respectant les bonnes pratiques de programmation, en jouant sur les paramètres de l’application et en utilisant des arrays pour lire et écrire de grands ensembles de données.

En dehors du code, d’autres sources de lenteur sont possibles, notamment la configuration matérielle.

À bientôt !

Quelques ressources :

  • Page Wikipédia
  • Site Excel-Pratique
  • Livre Programmation VBA pour Excel pour les nuls (Excel 2010, 2013 et 2016), de John Walkenbach

Aucun commentaire

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte