CLS: Tipps & Tricks: Excel-VBA



Tipps & Tricks: Excel-VBA

Auf dieser Seite finden Sie 22 Tipps & Tricks für Excel-VBA. Soweit keine Einschränkungen dazu genannt werden, gelten diese Tipps & Tricks für alle Versionen von Excel.

Wenn in den folgenden Erläuterungen Texte wie MsgBox formatiert sind, handelt es sich um konkret einzugebende Inhalte wie VBA-Code oder die Eingabe von Werten. Menüs wie Datei Speichern sind wie hier zu sehen formatiert. Schaltflächen oder Registerkarten auf Dialogen werden wie Menüs behandelt.

Alle Tipps sind nach bestem Wissen geprüft, aber selbstverständlich ohne Gewähr. Sollten Sie doch einen Fehler darin entdecken, würden wir uns freuen, wenn Sie uns per eMail Bescheid sagen.

Die meisten Benutzer werden Excel so eingestellt haben, dass in den Spaltenköpfen Buchstaben zu sehen sind. Dann erscheinen Zelladressen in der so genannten A1-Schreibweise.

Erst wenn Sie mit Extras Optionen Allgemein das Kontrollkästchen Z1S1-Bezugsart aktiviert haben, sehen Sie die Spaltenköpfe mit Zahlen. Dabei ändern sich auch alle Formeln in die entsprechende Z1S1-Schreibweise:

A1-Schreibweise Z1S1-Schreibweise
relative Adressierung =C7 =Z(3)S(-2) Formel in der Zelle $E$4
absolute Adressierung =$C$7 =Z7S3 Formel in einer beliebigen Zelle

Dabei ist die Z1S1-Schreibweise sicherlich erst einmal gewöhnungsbedürftig, aber die A1-Schreibweise ist auch nicht wirklich überzeugend. Denn =C7 ist nur dann die tatsächliche Zelle C7, wenn die Formel in E4 steht. Eigentlich meint die Adresse =(drei Zeilen tiefer) und (zwei Spalten weiter links).

Und genau das wird in der Z1S1-Schreibweise perfekt formuliert: =Z(3)S(-2) meint als relative Angabe =Zeile(3 tiefer)Spalte(-2, also weiter links). Wenn sich ein Verweis auf die gleiche Spalte oder Zeile bezieht, steht dort Z oder S ohne folgende Zahl. Als absolute Angabe wird die Z1S1-Adressierung ohne Klammern geschrieben.

Insbesondere die vier typischen, relativen Angaben (direkt drüber, drunter, rechts oder links) sind in der Z1S1-Schreibweise sehr einfach und übersichtlich:

Z1S1-Schreibweise
Zelle links daneben =ZS(-1)
Zelle rechts daneben =ZS(1)
Zelle darüber =Z(-1)S
Zelle darunter =Z(1)S

Da der Verweis auf andere Zellen in Excel am besten durch einfaches Anklicken erfolgt, spielt die Z1S1-Schreibweise ihre Stärken natürlich vor allem in der Programmierung aus. Anders als bei der A1-Schreibweise muss Ihr Makro nicht erst ermitteln, in welcher Zelle eine Formel eingefügt wird, sondern kann direkt eine solche relative Angabe schreiben.

Sie können für jeden Kommentar alle seine Eigenschaften verändern, nicht jedoch für alle gleichzeitig. Das ist ziemlich ärgerlich, wenn Sie beispielsweise entdecken, dass es mit transparenten Kommentaren einfacher wäre, die dahinter liegenden Zellen noch zu erkennen. Die folgende VBA-Prozedur stellt für alle Kommentare des aktuellen Blattes die Transparenz um:

Sub AlleKommentareImBlattAendern()
Dim cmtDieser As Comment

For Each cmtDieser In ActiveSheet.Comments 'alle Kommentare durchlaufen
cmtDieser.Shape.Fill.Transparency = 0.25
Next
End Sub

Nach diesem Schema können Sie alle Eigenschaften aller Kommentare auf diesem Blatt ändern.

Um eine Liste gerade ohne ihre Titelzeile per VBA durchsuchen zu können, ist der entgegengesetzte Fall zu dem Tipp "Erste Zeile eines Bereichs markieren" nötig. Die Funktion sieht daher so aus:

Function AllesOhneErsteZeile(rngStart As Range) As Range
If rngStart.Rows.Count = 1 Then
Set AllesOhneErsteZeile = rngStart
MsgBox "Dieser Bereich hat nur eine Zeile!", vbCritical
Else
Set AllesOhneErsteZeile = rngStart.Offset(1, 0). _
Resize(rngStart.Rows.Count - 1, rngStart.Columns.Count)
End If
End Function

Dabei wird die linke obere Ecke des ursprünglichen Bereichs mit Offset(1, 0) um eine Zeile nach unten verschoben, und seine Gesamtgröße mit Resize auf die Zeilenzahl-1 reduziert. Wenn nur eine Zeile markiert war, kann die Anzahl der Zeilen nicht weiter reduziert werden, daher ist hier eine extra Prüfung notwendig. Auch hier kann der Test nur über eine eigene Test-Prozedur erfolgen, soweit die Funktion nicht in anderem Code aufgerufen wird.

Sub TesteOhneErsteZeile()
AllesOhneErsteZeile(Selection).Select
End Sub

Bereichsnamen, welche Sie nur im Laufe eines Makros temporär benötigt haben, können Sie anschließend wieder löschen wie in der folgenden Prozedur:

Sub BereichsnamenLoeschen()
Application.Names("Merken").Delete
End Sub

Bitte beachten Sie, dass der Name "Druckbereich" sich auch hier ungewöhnlich verhält, er wird trotz der hier benutzten dateiweiten Syntax (Application-Objekt!) nur lokal in der Tabelle gelöscht.

Innerhalb einer Excel-VBA-Programmierung sollten Sie immer auf Bereichsnamen und nicht auf Zelladressen zugreifen, denn dann kann sich das Layout der Tabelle komplett ändern, ohne dass Ihr Makro davon betroffen ist. Dabei ist es hilfreich, sich den Umgang mit Bereichsnamen durch eigene Prozeduren etwas zu vereinfachen. Schreiben Sie dazu die folgende Prozedur:

Sub BereichsnamenFestlegen(rngHier As Range, strName As String)
Application.Names.Add strName, rngHier
End Sub

Sie haben vielleicht bemerkt, dass das Names-Objekt überraschenderweise dem Application-Objekt untergeordnet ist. Es gibt ebenso ActiveSheet als passendes Elternobjekt, aber dann muss der angegebene Name auch wirklich in genau diesem Blatt enthalten sein. mit der Application-Variante kann der Bereichsname irgendwo in der aktiven Arbeitsmappe sein (ja, Sie haben recht, es hätte dann richtigerweise eigentlich das ActiveWorkbook-Elternobjekt sein müssen...). Mit dieser Funktion können Sie nun die folgenden Prozeduren zum Testen nutzen:

Sub MarkierungAlsDruckbereich()
BereichsnamenFestlegen Selection, "Druckbereich"
End Sub
 
Sub MarkierungMerken()
BereichsnamenFestlegen Selection, "Merken"
End Sub

Der Bereichsname "Druckbereich" entspricht im deutschen Excel übrigens dem Aufruf des Befehls Datei Druckbereich Druckbereich festlegen und ist anschließend sehr schön durch die gestrichelte Umrahmung zu erkennen. Außerdem wird er nur als lokaler Bereichsname angelegt, gilt also nur innerhalb einer Tabelle, damit jede einen eigenen Druckbereich haben kann. Das entspricht aber nicht dem "normalen" Verhalten eines Bereichsnamens.

Oftmals wird im Laufe eines Makros ein Bereich mit Daten gefüllt und soll anschließend einen Bereichsnamen erhalten, damit für den Rest des Makros einfacher darauf zugegriffen werden kann. Anders als im vorigen Beispiel sind aber möglicherweise nur die Zelladressen bekannt. Dann müssen Sie auf die Schreibweise achten:

Sub BereichBenennen()
ActiveWorkbook.Names.Add "Ergebnisse", _
"=" & Selection.CurrentRegion.Address
End Sub

In diesem Beispiel wird ausgehend von der markierten Zelle der umgebende Bereich ermittelt, also alle Nachbarzellen, die Daten enthalten. Das sind typischerweise alle Listenelemente, wenn Sie per VBA Daten ermittelt und in einer Tabelle gespeichert haben. Deren (absolute) Adresse ist nun die Grundlage für Zuweisung des Bereichsnamens. Wichtig hierbei ist das führende "="-Zeichen, denn ansonsten erfindet Excel alle möglichen Textformen für die Adresse, aber keine gültige Zuweisung!

Da Sie innerhalb eines echten VBA-Programms natürlich nicht mit Selection arbeiten (sollten), weil das sehr langsam ist, kommt vermutlich eher die folgende, fett markierte Änderung vor:

Sub BereichBenennen()
ActiveWorkbook.Names.Add "Ergebnisse", _
"=" & ActiveSheet.Range("$A$1").CurrentRegion.Address
End Sub

Auch hier ist das "="-Zeichen vor der Adresse zwingend notwendig.

Wenn Sie eine Excel-Mappe mit Makro-gesteuerten Funktionalitäten ausstatten, brauchen Sie sehr schnell einen Platz, um ein paar Hilfsdaten speichern zu können. Wo? Natürlich in einer Tabelle! Wie können Sie aber verhindern, dass diese von normalen Benutzern einsehbar ist? Sie müssen sie nur gut genug verstecken:

Sub BlattWeg()
ActiveWorkbook.Sheets("Tabelle1").Visible = xlSheetHidden
End Sub

Das ist die normale Lösung, wie es per Menü Format Blatt Ausblenden manuell auch durchgeführt werden kann. Um ein solches Blatt wieder einzublenden, nutzen Sie Format Blatt Einblenden oder:

Sub BlattWeg()
ActiveWorkbook.Sheets("Tabelle1").Visible = xlSheetVisible
End Sub

Das hilft also nicht, denn solchermaßen versteckte Blätter sind immer noch einblendbar. Nur per VBA gibt es aber eine verschärfte Stufe des Versteckens:

Sub BlattWeg()
ActiveWorkbook.Sheets("Tabelle1").Visible = xlSheetVeryHidden
End Sub

So ausgeblendete Arbeitsblätter werden im Einblende-Dialog nicht mehr angezeigt. Ätsch!

Dateinamen ermitteln ID 380 Top-Tipp!

Es ist schon ein bißchen peinlich, dass gerade beim Aufruf einer Windows-Funktion, nämlich dem Anzeigen des DateiÖffnen- oder DateiSpeichernUnter-Dialogs jedes MS-Office-Programm sein eigenes VBA-Süppchen kocht. Dabei müßte eigentlich nur der systeminterne API-Befehl weitergereicht werden. Immerhin gibt es bei Excel (anders als bei den anderen) zwei fertige Funktionen, die das machen, auch wenn die so gut versteckt sind, dass man sie eher zufällig entdeckt.

Um eine vorhandene Datei auswählen zu können, existiert die GetOpenFileName-Funktion, die jedoch im Gegensatz zu praktisch allen anderen Funktionen immer mit ihrem Elternobjekt Application zusammen genutzt werden muss:

Sub DateiEinzelAuswahl()
Dim varDatei As Variant
 
varDatei = Application.GetOpenFilename("Excel-Arbeitsmappen,*.xls," & _
"Alle Excel-Dateien,*.xl?", 2, "Bitte wählen Sie eine Datei aus!")
If varDatei = False Then
MsgBox "Sie haben abgebrochen."
Else
MsgBox "Sie haben '" & varDatei & "' ausgewählt."
End If
End Sub

Die Variable varDatei für den Dateinamen muss vom Datentyp Variant sein, weil beim Abbruch des DateiÖffnen-Dialogs der Wert False zurückgegeben wird, was in der Bedingung geprüft wird.

Der erste Parameter der GetOpenFileName-Funktion gibt die Filterliste an, wobei immer abwechselnd ein beliebiger Text und ein Filter mit Jokerzeichen durch Kommata getrennt wird. Wenn Sie einen Filter aus der Liste vorbesetzen wollen, geben Sie als zweites Argument dessen Index an, der hier ausnahmsweise mal mit 1 beginnt. Das dritte Argument erlaubt es, den Titel des Dialogs zu öffnen. Die Beschriftung der Öffnen-Schaltfläche lässt sich nur auf dem Mac ändern, unter Windows wird es ignoriert.

Auch wenn der DateiÖffnen-Dialog täuschend echt aussieht: er öffnet nicht und soll das auch nicht. Er ist lediglich eine systemkonforme Methode, auf eine Datei zu zeigen und dabei beispielsweise auch Pfad und Laufwerk wechseln zu können. Was Sie anschließend mit der Datei machen, regelt Ihr VBA-Code, hier wird nur ein gültiger Name samt Pfad von einer garantiert vorhandenen Datei ermittelt.

Wie Sie vielleicht am nächsten, hier noch nicht benutzten Parameter MultiSelect schon gesehen haben, lassen sich damit auch mehrere Dateien gleichzeitig auswählen, indem Sie True angeben:

Sub DateiMehrfachAuswahl()
Dim varDatei As Variant
Dim strDateien As String
Dim i As Integer
 
varDatei = Application.GetOpenFilename("Excel-Arbeitsmappen,*.xls," & _
"Alle Excel-Dateien,*.xl?", 2, "Bitte wählen Sie eine Datei aus!", , True)
If IsArray(varDatei) Then
For i = 1 To UBound(varDatei)
strDateien = strDateien & varDatei(i) & vbCrLf
Next
MsgBox "Sie haben diese Dateien ausgewählt:" & vbCrLf & strDateien
Else
MsgBox "Sie haben abgebrochen."
End If
End Sub

Alternativ zu dem ersten Beispiel können Sie die Variable varDatei auch daraufhin prüfen, ob sie ein Array enthält, denn nun werden alle ausgewählten Dateien in einem solchen übergeben. Auch hier folgt in einer MsgBox lediglich die Namensliste, ohne dass eine der Dateien geöffnet würde.

Während der DateiÖffnen-Dialog sicherstellt, dass es diese Datei auch gibt, erlaubt der DateiSpeichernUnter-Dialog im Gegenteil, einen neuen Dateinamen vorzugeben. Eigentlich sollte er auch überprüfen und warnen, wenn der Dateiname schon existiert, aber das ist bei GetSaveAsFilename nicht der Fall:

Sub DateiSpeichernUnter()
Dim strDatei As String
Dim strVorschlag As String
 
strVorschlag = "Beispiel" & Format(Now(), "yyyy_MM_dd") & ".xls"
strDatei = Application.GetSaveAsFilename(strVorschlag, _
"Excel-Dateien,*.xls", 1, "Daten sichern")
MsgBox "Diese Datei soll als '" & strDatei & "' gesichert werden."
End Sub

Das Prinzip der Filter funktioniert genauso, aber es gibt zusätzlich die Möglichkeit, einen Dateinamen vorzugeben, wie es hier gezeigt ist.

Um den Pfad zu beeinflussen, der beim Öffnen der Datei-Auswahldialoge angezeigt wird, können Sie die "MSDOS-Befehle" ChDrive und ChDir einsetzen, die auch in VBA entsprechend heißen.

Immer wieder ist es in der Excel-Programmierung nötig, von einem Bereich nur die Titelzeile zu finden, sei es zum Markieren oder zur weiteren Verarbeitung während des Makros. Das ist mit einem eher unbekannten Befehl sehr leicht zu bewerkstelligen:

Function ErsteZeile(rngStart As Range) As Range
Set ErsteZeile = rngStart.Offset(0, 0).Resize(1, rngStart.Columns.Count)
End Function

Diese Funktion ErsteZeile erhält als einziges Argument einen Bereich (Range) und gibt als Ergebnis den ermittelten Bereich nur der Titelzeile zurück. Dazu wird die linke obere Ecke des ursprünglichen Bereichs mit Offset(0, 0) ausdrücklich nicht verschoben, aber seine Gesamtgröße mit Resize auf eine Zeile reduziert.

Zum Testen der Funktion benötigen Sie eine Prozedur wie im folgenden Beispiel, bei der ausgehend von der aktuellen Markierung anschließend deren Titelzeile markiert ist:

Sub TesteErsteZeile()
ErsteZeile(Selection).Select
End Sub

Starten Sie die Prozedur TesteErsteZeile einfach, indem Sie den Cursor hineinsetzen und F5 drücken.

Auch wenn Formeln in Excel-Dateien sinnvollerweise nicht per Makro, sondern besser in einer Vorlage (XLT-Datei) erstellt und diese per VBA nur mit allen Formeln geöffnet wird, muss doch gelegentlich mal eine Formel eingefügt werden. Da es dafür verschiedene Möglichkeiten gibt, sollen diese am Beispiel einer Summe in der Zelle A4 gezeigt werden.

VBA-Befehl
A1, englisch ActiveSheet.Range("A4").Formula = "=Sum(A1:A3)"
A1, deutsch ActiveSheet.Range("A4").FormulaLocal = "=Summe(A1:A3)"
Z1S1, englisch ActiveSheet.Range("A4").FormulaR1C1 = "=Sum(R[-3]C:R[-1]C)"
Z1S1, deutsch ActiveSheet.Range("A4").FormulaR1C1Local = "=Summe(Z(-3)S:Z(-1)S)"

Dabei bedeutet der Zusatz ...Local immer, dass deutsche Syntax in der Formel anzuwenden ist, ansonsten die amerikanische. Achten Sie bitte bei der amerikanischen Syntax darauf, dass nicht nur der Funktionsname englisch ist, sondern bei der Z1S1-Schreibweise auch die Buchstaben und die Klammern anders sind!

Der schon im Tipp "A1- oder Z1S1-Schreibweise" genannte Vorteil der Z1S1-Schreibweise besteht darin, dass hier immer die drei Zellen über der Formel addiert werden, ohne dass Sie im Makro wissen müssten, in welcher Zelle Sie eigentlich schreiben. In der A1-Schreibweise verhält sich die Formel nämlich wie eine absolute Adressierung. Das können Sie feststellen, wenn Sie als Zielzelle ...Range("B4")... ändern, dann paßt sich die Formel keineswegs an. Nur die Z1S1-Schreibweise ist wirklich relativ.

Wenn Sie eine benutzerdefinierte VBA-Funktion programmieren, bleibt die unabhängig vom Neuberechnen des Tabellenblattes, in dem sie sich befindet. Sie müssen also immer zu so Tricks greifen, wie in dem entsprechenden Zellbereich alle Gleichheitszeichen durch Gleichheitszeichen zu ersetzen, damit Formeln zum Neuberechnen gezwungen werden.

Fügen Sie stattdessen im Code der Funktion Application.Volatile ein, dann werden diese Funktionsaufrufe auch dann neuberechnet, wenn Excel sowieso alles aktualisiert. Natürlich kann das Ihre Arbeitsblätter auch ziemlich langsam machen, wenn Sie das exzessiv einsetzen.

Manchmal wäre es praktisch, alle Kommentare eines Blattes auslesen und in Zellen weiterbearbeiten zu können. Da Excel das nicht bietet, hilft die folgende Prozedur:

Sub KommentareInZellenKopieren()
Dim wksQuelle As Worksheet 'die Tabelle mit Kommentaren
Dim wksZiel As Worksheet 'die Tabelle zum Ausdrucken
Dim cmtDieser As Comment 'ein Kommentar
Dim lngZeile As Long

Set wksQuelle = ActiveSheet 'Achtung, vorher merken, weil neues Blatt kommt
Set wksZiel = ThisWorkbook.Worksheets.Add() 'macht immer eine neue Tabelle dafür

With wksZiel
lngZeile = 1
.Cells(lngZeile, 1).Value = "Adresse"
.Cells(lngZeile, 2).Value = "Zellwert"
.Cells(lngZeile, 3).Value = "Kommentar"
.Rows(lngZeile).Font.Bold = True 'Titelzeile fett machen

For Each cmtDieser In wksQuelle.Comments 'alle Kommentare durchlaufen und in neuer Tabelle auflisten
lngZeile = lngZeile + 1
.Cells(lngZeile, 1).Value = cmtDieser.Parent.AddressLocal
.Cells(lngZeile, 2).Value = cmtDieser.Parent.Value
.Cells(lngZeile, 3).Value = cmtDieser.Text
Next
End With
End Sub

Die Kommentare sind anschließend mit Zelladresse in einer neuen Tabelle aufgelistet und können dort wie alle anderen Zellen auch sortiert oder ähnlich behandelt werden.

Wenn ein Tabellenblatt viele Kommentare enthält, können Sie diese zwar alle gleichzeitig anzeigen oder ausdrucken lassen, dabei überlappen sie sich aber meistens. Ein bisschen VBA hilft dabei, dass alle Kommentare schön am rechten Rand untereinander aufgereiht werden:

Sub KommentareVerschieben()
Dim wksQuelle As Worksheet 'die Tabelle mit Kommentaren
Dim wksKopie As Worksheet 'die kopierte Tabelle davon, damit das Original zur Sicherheit erhalten bleibt
Dim cmtDieser As Comment 'ein Kommentar
Dim dblLeft As Double 'die Links-Position, an welche die Kommentare verschoben werden sollen
Dim dblTop As Double 'die Top-Position, an welche die Kommentare untereinander verschoben werden sollen

Set wksQuelle = ActiveSheet
wksQuelle.Copy wksQuelle 'jetzt ist das neue Blatt die erste Tabelle
Set wksKopie = ThisWorkbook.Worksheets(1) 'mit einer Kopie der Tabelle arbeiten, damit das Original erhalten bleibt

With wksKopie.UsedRange
dblLeft = .Left + .Width + 20 '+20 für ein bisschen Abstand nach rechts
End With

For Each cmtDieser In wksKopie.Comments 'alle Kommentare durchlaufen und in neuer Tabelle auflisten
dblTop = dblTop + 10 '10 als senkrechter Abstand
With cmtDieser
.Visible = True 'alle sichtbar machen
.Shape.Left = dblLeft 'an den rechten Rand schieben
.Shape.Fill.Transparency = 0 'undurchsichtig machen
.Shape.TextFrame.AutoSize = True 'Größe automatisch anpassen
.Shape.Top = dblTop 'Kommentar an senkrechte Position schieben
dblTop = dblTop + .Shape.Height 'von oben nach unten anordnen
End With
Next
End Sub

Wenn Sie die Zeile mit AutoSize weglassen, bleiben die Kommentare in ihrer ursprünglichen Größe, sonst werden sie in optimaler Breite (also meistens einzeilig) angezeigt.

Bei umfangreichen Datenmengen ist es sehr praktisch, einige Daten mit Kommentaren kennzeichnen zu können (nämlich via Rechtsklick und Kommentar einfügen). Was jedoch anschließend fehlt, ist ein Überblick über diese Kommentare. Sie lassen sich zwar mit Bearbeiten Gehe zu Inhalte und der Auswahl "Kommentare" markieren, dann sehen Sie aber immer noch nicht deren Inhalte.

In der einfachsten Fassung zeigt das folgende Makro alle Kommentare mit Angabe der jeweiligen Zelle in einer MsgBox an:

Sub KommentareZeigen()
Dim cmtDieser As Comment
 
For Each cmtDieser In ActiveSheet.Comments
MsgBox "Kommentar in " & cmtDieser.Shape.TopLeftCell.AddressLocal & _
": " & cmtDieser.Text
Next
End Sub

Das ist bei vielen Kommentaren lästig und unübersichtlich, daher sollen die Kommentar-Daten besser in eine Excel-Tabelle geschrieben werden. Dazu werden sie aus dem aktiven Tabellenblatt ausgelesen und in ein neu angelegtes Tabellenblatt derselben Datei geschrieben:

Sub KommentarListe()
Dim shtListe As Worksheet
Dim shtKommentare As Worksheet
Dim cmtDieser As Comment
Dim i As Integer
 
Set shtKommentare = ActiveSheet
Set shtListe = ActiveWorkbook.Sheets.Add()
i = 0
For Each cmtDieser In shtKommentare.Comments
shtListe.Range("A1").Offset(i, 0).Range("A1").Value = _
cmtDieser.Shape.TopLeftCell.AddressLocal
shtListe.Range("A1").Offset(i, 1).Range("A1").Value = _
cmtDieser.Text
i = i + 1
Next
End Sub

Entsprechend lässt sich auch das Löschen alle Kommentare per VBA sehr einfach realisieren, wie das nächste Makro zeigt:

Sub KommentareLoeschen()
Dim cmtDieser As Comment
 
For Each cmtDieser In ActiveSheet.Comments
cmtDieser.Delete
Next
End Sub

Alternativ können Sie die Kommentare aber auch löschen, nachdem Sie mit Bearbeiten Gehe zu Inhalte und der Auswahl "Kommentare" alle markiert haben und dann per Rechtsklick Kommentar löschen anklicken. Anders als der Wortlaut vermuten lässt, werden dann die Kommentare in allen markierten Zellen entfernt.

Wenn Sie in Excel die Entf-Taste drücken, wird nur der Zellinhalt, nicht jedoch die Formatierung gelöscht. Entsprechend gibt es dafür in VBA verschiedene Methoden, welche die jeweiligen Teile einer Zelle löschen. Der folgende Code nimmt nacheinander die entsprechenden Löschungen vor.

Sub DiversesLoeschen()
Selection.ClearFormats 'nur Format löschen
Selection.ClearContents 'nur Inhalt löschen
'oder gleich
Selection.Clear 'Inhalt und Format löschen
End Sub

Am besten starten Sie die Prozedur mit F8 für jede Zeile einzeln, so dass Sie zwischendurch in der Excel-Datei sehen können, was jeweils gelöscht worden ist.

Wenn Sie Prozeduren aus anderen (geöffneten) Excel-Dateien benutzen wollen, legen Sie zuerst einen Verweis auf die Datei an. Damit keine Verwechslungen möglich sind, muss die mitzubenutzende Datei (in den Eigenschaften des VB-Editors) einen eindeutigen internen Namen erhalten, der ja ansonsten immer noch "VBProject" heißt. Danach öffnen Sie über das Menü Extras Verweise den Dialog, um einen Verweis auf jene Datei anzulegen. Wenn die Datei den internen Namen "Testvorlage" hat und eine Prozedur MachDies enthält, erfolgt deren Aufruf so:

Sub FremdaufrufMitVerweis
Testvorlage.MachDies
End Sub
Alle Parameter können wie bei einer Prozedur oder Funktion der gleichen Datei übergeben werden, auch der Zugriff auf globale Variablen ist so möglich.

Mit der Application.Run-Methode können Sie (öffentliche) Prozeduren aus anderen geöffneten Excel-Dateien aufrufen. Falls es mehrere gleichnamige gibt, geben Sie vor dem Ausrufezeichen noch den Namen der Datei an:

Sub FremdaufrufOhneVerweis
Application.Run ActiveWorkbook.Name & "!MachDies"
End Sub

Die eventuellen Parameter der Prozedur können durch Komma getrennt als Parameter angegeben werden und müssen in der richtigen Reihenfolge stehen. Benannte Argumente sind hier also nicht erlaubt.

Wenn Sie eine Tabelle per VBA löschen, erscheint trotzdem von Excel die Sicherheitsmeldung, dass auf diesem Blatt Daten enthalten sein könnten. Dies können Sie mit DisplayAlerts ausschalten:

Sub BlattWeg
Application.DisplayAlerts = False
ActiveWorkbook.Sheets("Tabelle1").Delete
Application.DisplayAlerts = True
End Sub

Sie sollten die Warnungen direkt anschließend wieder aktivieren, weil sie sonst dauerhaft ausgeschaltet sind.

Wenn Sie in Excel von Ihren Benutzern oder Benutzerinnen auf mehreren Blättern Dateneingaben verlangen, ist das oft wie in einem Assistenten organisiert, also die Werte auf Tabellenblatt 1 müssen vorhanden sein, bevor das Weitergehen in Tabellenblatt 2 sinnvoll ist. Das lässt sich sogar sehr einfach überprüfen. Der folgende Code muss im Tabellenmodul derjenigen Tabelle eingefügt werden, welches noch nicht betreten werden darf, wenn die Zelle mit dem Bereichsnamen PruefDaten (die in irgendeinem anderen Blatt sein kann) noch unausgefüllt ist:

Private Sub Worksheet_Activate()
With Application.Range("PruefDaten")
If .Value = "" Then
.Parent.Activate
End If
End With
End Sub

Beim Versuch, dieses Tabellenblatt zu betreten, wird automatisch dessen Worksheet_Activate-Ereignis ausgelöst. Darin prüfen Sie nun den Wert der Zelle namens PruefDaten. Falls diese leer ist, wird deren Parent-Objekt, also ihre zugehörige Tabelle, aktiviert. Ihr Code muss also gar nicht konkret "wissen", wo sich der Bereich befindet.

Damit Ihre Makros nicht versehentlich von Benutzern erstellte Dateien in einem falschen Format speichern, sollten Sie bei Bedarf prüfen, mit welcher Excel-Version sie vorher gespeichert wurden.

Jede Datei besitzt die Eigenschaft CalculationVersion, eine Long-Zahl(!), welche sowohl die Versionsnummer der Hauptversion des zuletzt speichernden Excel-Programms als auch in den letzten vier Ziffern eine Nummer für dessen Unterversion seines Berechnungsmoduls enthält. Zur Analyse könnte Ihr Makro beispielsweise so arbeiten:

Sub DateiVersion()
Dim strVersion As String
Dim strHauptVersion As String
Dim strUnterVersion As String
 
strVersion = CStr(ActiveWorkbook.CalculationVersion)
strHauptVersion = Left(strVersion, Len(strVersion) - 4)
strUnterVersion = Mid(strVersion, Len(strVersion) - 3)
 
Select Case strHauptVersion
Case "9"
MsgBox "Excel 2000: Unterversion " & strUnterVersion
Case "10"
MsgBox "Excel 2002: Unterversion " & strUnterVersion
Case "11"
MsgBox "Excel 2003: Unterversion " & strUnterVersion
Case "12"
MsgBox "Excel 2007: Unterversion " & strUnterVersion
Case Else
MsgBox "Excel " & strHauptVersion & ": Unterversion " & strUnterVersion
End Select
End Sub

Die eher unübliche, explizite Umwandlung einer Long-Zahl in eine Zeichenkette geschieht, damit anschließend korrekt mit Zeichenketten-Funktionen wie Left oder Mid gearbeitet werden kann. Unter VisualBasic würde zwar auch sonst intern eine Datentypkonvertierung durchgeführt, aber solch schlechter Stil sollte gar nicht erst geschrieben werden.

Mit der Funktion MarkierungMerken aus dem Tipp "Bereichsnamen zuweisen" können Sie sich am Anfang eines Makros einfach merken, wo Ihr/e Benutzer/in die Zellmarkierung hatte. Falls diese zwischendurch verschoben wurde (wobei das Selection-Objekt aber grundsätzlich eher vermieden werden sollte, weil das zugehörige Verschieben des Zellzeigers auf dem Bildschirm eine der eher langsamen Aktionen ist. Das Selection-Objekt taucht aber oft in aufgezeichneten Makros auf...), können Sie am Ende Ihrer Makros die ursprüngliche Markierung wiederherstellen:

Sub GeheZuMerker()
Application.Range("Merken").Select
End Sub

Der/Die Benutzer/in wird es Ihnen danken, dass die mühsam hergestellte Markierung nicht einfach so verschwunden ist!

Während Excel in Tabellen den 1.1.1900 als Tag 1 seiner Zeitrechnung betrachtet, beginnt VBA mit dem 31.12.1899.