Knowledge base KB0070

Pour quelle raison ma macro Excel est-elle lente lorsque think-cell est activé ?

L'utilisation de la fonction .Select est un problème courant qui peut entraîner des problèmes de performances dans les macros VBA. Chaque fois qu'une cellule est sélectionnée dans Excel, chaque complément Excel (y compris think-cell) est notifié de cet événement de changement de sélection, ce qui ralentit fortement la macro. Les macros créées à l'aide de l'enregistreur de macros sont particulièrement sujettes à ce type de problème.

Microsoft recommande également d'éviter l'instruction .Select dans le code VBA pour améliorer les performances :

Exemple : Comment éviter d'utiliser la déclaration .Select

Analysons la simple macro AutoFillTable suivante :

Sub AutoFillTable()
 Dim iRange As Excel.Range
 Set iRange = Application.InputBox(prompt:="Enter range", Type:=8)
 Dim nCount As Integer
 nCount = iRange.Cells.Count
 For i = 1 To nCount
 Selection.Copy
 If iRange.Cells.Item(i).Value = "" Then
 iRange.Cells.Item(i).Range("A1").Select
 ActiveSheet.Paste
 Else
 iRange.Cells.Item(i).Range("A1").Select
 End If
    Next
End Sub

Cette fonction ouvre une zone de saisie qui demande à l'utilisateur de spécifier une plage de cellules. Cette fonction passe en revue toutes les cellules de cette plage. Si elle détecte une cellule qui n'est pas vide, elle en copie le contenu dans le Presse-papiers. Elle colle ensuite le contenu du Presse-papiers dans chaque cellule vide suivante.

AutoFillTable utilise le Presse-papiers pour copier le contenu des cellules. Aussi, la fonction doit sélectionner chaque cellule qui est manipulée afin qu'Excel sache à partir de quelle cellule copier et vers quelle cellule coller. La solution recommandée est illustrée dans la fonction AutoFillTable2 suivante :

Sub AutoFillTable2()
 Dim iRange As Excel.Range
 Set iRange = Application.InputBox(prompt:="Enter range", Type:=8)
 Dim iCellMaster As Excel.Range
 For Each iCell In iRange.Cells
 If iCell.Value = "" Then
 If Not iCellMaster Is Nothing Then
 iCellMaster.Copy (iCell)
 End If
 Else
 Set iCellMaster = iCell
 End If
 Next iCell
End Sub

AutoFillTable2 présente deux différences majeures par rapport à son prédécesseur :

  1. Tout particulièrement, elle n'implique plus la sélection d'une cellule. En lieu et place, lorsqu'une cellule non vide est détectée, celle cellule est stockée dans la variable iCellMaster. Par la suite, dès qu'une cellule non vide est détectée, tout le contenu de iCellMaster est copié dans iCell.
  2. La fonction de langage Visual Basic est utilisée Pour chaque … Suivant afin de vérifier chaque cellule de la plage. Il s'agit là d'une première amélioration en termes de lisibilité.