Warum reagiert mein Excel-Makro so langsam, wenn think-cell aktiviert ist?
Eine häufige Ursache für Leistungsprobleme von VBA-Makros besteht in der Verwendung der .Select
-Funktion. Jedes Mal, wenn in Excel eine Zelle markiert wird, werden sämtliche Excel-Add-Ins (einschließlich think-cell) über die Änderung der Markierung benachrichtigt, wodurch das jeweilige Makro deutlich ausgebremst wird. Vor allem Makros, die durch Makroaufzeichnung erstellt wurden, sind für dieses Problem anfällig.
- Office-Blog: "Wie lassen sich große Bereiche in Excel am schnellsten durchsuchen?"
- MSDN: Leistungssteigerung in Excel 2007: „Referenzobjekte in Excel wie Bereichsobjekte direkt ohne Auswahl oder Aktivierung referenzieren“ (im Abschnitt „Schnellere VBA-Makros“).
Beispiel: Umgehung der .Select
-Funktion
Betrachten wir das folgende einfache Makro AutoFillTable
:
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
Diese Funktion öffnet ein Eingabefeld an, das den Benutzer dazu auffordert, einen Zellbereich anzugeben. Die Funktion durchläuft alle Zellen dieses Bereichs. Trifft sie dabei auf eine Zelle, die nicht leer ist, kopiert sie den Inhalt der Zelle in die Zwischenablage. Die Funktion fügt den Inhalt der Zwischenablage in jede nachfolgende leere Zelle ein.
AutoFillTable
verwendet die Zwischenablage, um den Zellinhalt zu kopieren. Daher muss die Funktion jede zu bearbeitende Zelle markieren, um Excel zu signalisieren, welche Zelle kopiert und in welche Zelle der Inhalt eingefügt werden soll. Die folgende Funktion AutoFillTable2
zeigt die empfohlene Lösung:
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
unterscheidet sich in zwei wichtigen Punkten von ihrem Vorgänger:
- Vor allem kommt sie ohne das Markieren von Zellen aus. Wenn eine Zelle gefunden wird, die nicht leer ist, wird ihr Inhalt stattdessen in der Variable
iCellMaster
gespeichert. Wird anschließend eine leere Zelle gefunden, wird der gesamte Inhalt voniCellMaster
iniCell
kopiert. - Dabei wird die Sprachfunktion
For Each … Next
von Visual Basic verwendet, um jede Zelle im Bereich zu besuchen. Dies verbessert bereits die Lesbarkeit.