CLS: Tipps & Tricks: Access-VBA



Tipps & Tricks: Access-VBA

Auf dieser Seite finden Sie 17 Tipps & Tricks für Access-VBA. Soweit keine Einschränkungen dazu genannt werden, gelten diese Tipps & Tricks für alle Versionen von Access. Tipps zu VBA, die für alle Office-Programme gelten, finden Sie bei VBA allgemein.

Wenn der Datentyp DAO.Recordset oder ähnliches heißt, muss im VBA-Editor-Menü Extras Verweise die Bibliothek "Microsoft Data Access Objects" (nämlich "DAO", meistens in Version 3.6) angeklickt sein. Der Datentyp ADO.Recordset oder ähnliche erfordert dort "Microsoft ActiveX Data Objects" (nämlich "ADO" in Version 2.1). Auch wenn es technisch möglich ist, sollten Sie je Datenbank nur einen der beiden Verweise aktivieren, damit Sie nicht die oft gleichnamigen Objekte verwechseln. Seit Access 2013 heißt dieser Verweis "Microsoft Office 15.0 database engine Object", wird aber in der Programmierung wie früher als "DAO" angesprochen.

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 E-Mail Bescheid sagen.

Die SysCmd-Funktion bietet auch die einfachste Möglichkeit, die Access-Version zu ermitteln:

Function AccessVersion()
AccessVersion = SysCmd(acSysCmdAccessVer)
End Function
 
Sub VersionsTest()
MsgBox "Hier läuft Access Version " & AccessVersion
End Sub

Dabei wird nicht die offizielle Version wie beispielsweise "Access 2002" angezeigt, sondern die interne Nummerierung (hier also "10.0").

Sobald eine Aktionsabfrage ausgeführt wird, warnt Access den/die Anwender/in erstens durch eine grundsätzliche Meldung, dass diese Abfrage Daten verändern werde und zweitens mit einer Meldung, wieviele Datensätze betroffen sein werden. Im Verlauf eines fertig programmierten Ablaufs soll ein/e Benutzer/in diese Hinweise natürlich nicht sehen.

Weit verbreitet ist daher die Technik, mit folgendem Code die Warnungen in Access generell auszuschalten:

Sub SQLAusfuehren
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE * FROM Tabellenname"
DoCmd.SetWarnings True
End Sub

Wenn die Ausführung allerdings durch einen Laufzeitfehler unterbrochen wird, bleiben die Warnungen aus - und zwar nicht nur für diese Datenbank, sondern dauerhaft für dieses Access auf dem Rechner! Das trifft ebenfalls Entwürfe von Tabellen, Abfragen, Formularen o.ä., deren ungespeicherte Änderungen dann ohne Rückfrage immer gespeichert werden. Das ist ein völlig unnötiges Risiko.

Die Warnungen werden dabei von der Access-Oberfläche erzeugt, DoCmd.RunSQL simuliert nämlich eine/n Anwender/in, der/die via Oberfläche eine Aktionsabfrage startet und also gewarnt werden muss. Probieren Sie stattdessen folgenden Code:

Sub SQLAusfuehrenBesser
CurrentDB.Execute "DELETE * FROM Tabellenname"
End Sub

Dabei wird die Ausführung der Aktionsabfrage direkt an die JetEngine delegiert, welche die Arbeit auch im ersten Fall im Hintergrund gemacht hat. Diesmal aber ist die Access-Oberfläche nicht beteiligt, daher entfallen die Meldungen.

Die Warnmeldungen von Access sind genauso lästig, wenn Sie nicht einen SQL-Befehl, sondern eine bereits gespeicherte Abfrage ausführen wollen. Die oft übliche Version lautet:

Sub AktionAusfuehren
DoCmd.SetWarnings False
DoCmd.OpenQuery "NameDerAktionsabfrage"
DoCmd.SetWarnings True

Die direkte Ausführung via JetEngine ohne Beteiligung der Access-Oberfläche gelingt mit:

Sub AktionAusfuehren
CurrentDB.QueryDefs("NameDerAktionsabfrage").Execute

Das ist nicht nur kürzer als die dreizeilige Version mit DoCmd.SetWarnings, sondern auch unproblematischer, weil die System-Meldungen dabei grundsätzlich eingeschaltet bleiben.

Geben Sie den folgenden Beispiel-Code in einem beliebigen Access-Modul ein, um die Namen aller enthaltenen Felder zu sehen:

Sub ZeigeFeldnamen
Dim tblDiese as DAO.TableDef
Dim fldDieses as DAO.Field
 
Set tblDiese = CurrentDB.OpenRecordset("MeineTabelle")
For Each fldDieses in tblDiese.Fields
Msgbox fldDieses.Name
Next
End Sub

(Siehe dazu auch den Tipp Alle Felder einer Tabelle ermitteln im Formular)

Sehr verführerisch in der Programmierung ist eine typische VBA-Auflistung wie die Forms-Auflistung. Mit dieser können Sie scheinbar alle Formulare anzeigen, wie der folgende Code zeigt:

Sub FormulareFindenOffene
Dim frmDiese as UserForm
Dim dbsDiese as Database
 
Set dbsDiese = CurrentDB()
For Each frmDiese in dbsDiese.Forms
Msgbox frmDiese.Name
Next
End Sub

Bei genauerem Hingucken werden Sie aber feststellen, dass es tatsächlich nicht alle, sondern nur die geöffneten Formulare sind, die darin aufgelistet sind. Das ist durchaus so gewollt und dokumentiert, kommt aber für viele oftmals überraschend.

Was machen Sie nun, wenn Sie wirklich eine Liste aller in der Datenbank enthaltenen, aber nicht unbedingt geöffneten Formulare benötigen? Ab Access 2000 gibt es nicht nur das CurrentDB-Objekt, welches nur die Datenobjekte enthält, sondern auch CurrentProject mit den übrigen Objekten der Bedienungsoberfläche.

Dort heißt die entsprechende Auflistung AllForms und kann wie folgt benutzt werden:

Sub FormulareFindenOffene
Dim frmDiese as Object
 
For Each frmDiese in CurrentProject.AllForms
Msgbox frmDiese.Name
Next
End Sub

Dann sehen Sie tatsächlich alle gespeicherten Formulare und nicht nur die geöffneten.

Geben Sie den folgenden Beispiel-Code in einem beliebigen Access-Modul ein, um die Namen aller enthaltenen Tabellen zu sehen:

Sub ZeigeTabellennamen
Dim dbsDiese as DAO.Database
Dim tblDiese as DAO.TableDef
 
Set dbsDiese = CurrentDB()
For Each tblDiese in dbsDiese.TableDefs
Msgbox tblDiese.Name
Next
End Sub

Wie Sie bemerken werden, sind wirklich alle Tabellen in der Auflistung enthalten, also auch die mit 'MSys...' anfangenden Systemtabellen, die normalerweise ausgeblendet sind.

Um diese auch noch auszublenden, können Sie mit dem 'Like'-Operator die Namen überprüfen. Dabei müssen Sie bedenken, dass es nicht nur die immer vorhandenen 'MSys...'-Tabellen, sondern möglicherweise auch 'USys...'-Tabellen (z.B. in AddIns) gibt. Der obige Code ändert sich dann wie folgt:

'...wie bisher 
For Each tblDiese in dbsDiese.TableDefs
If Not tblDiese.Name Like "?Sys*" Then
Msgbox tbldiese.Name
End If
Next
'...wie bisher 

(Siehe dazu auch den Tipp Alle Felder einer Tabelle ermitteln im Formular)

Um den Benutzer einer Datenbank eindeutig zu identifizieren, können Sie natürlich auf das (nur bis Version 2003!) eingebaute Sicherheitssystem der DB-Anmeldung zurückgreifen. Müssen sie aber nicht. Schließlich hat der Benutzer sich bereits identifiziert, als er den Rechner eingeschaltet hat. Diese beiden Informationen (Benutzer- und Computername) können Sie direkt abfragen:

Sub AnmeldeName()
MsgBox Environ("Username") & " / " & Environ("Computername")
End Sub

Um eine Datei via VBA-Code auszuwählen, greifen Sie natürlich über den eingebauten Windows-DateiAuswahl-Dialog zu. Dazu müssen Sie zuerst mit Extras Verweise die Bibliothek 'Microsoft Office XX.0 Object Library' (XX ist die Versionsnummer) einbinden. Dann können Sie eine Datei so auswählen:

Sub WaehleDateiAus()
Dim dlgFileOpen As FileDialog

Set dlgFileOpen = Application.FileDialog(msoFileDialogFilePicker)
dlgFileOpen.AllowMultiSelect = False
If dlgFileOpen.Show() Then
MsgBox "Ausgewählt: " & dlgFileOpen.SelectedItems(1)
Else
MsgBox "Nix ausgewählt"
End If
End Sub

Wollen Sie mehrere Dateien auswählen, setzen Sie dlgFileOpen.AllowMultiSelect = True und werten mit einer For/Next-Schleife die Inhalte des Arrays SelectedItems aus.

Access kennt keine Eigenschaft, um den angezeigten Cursor für ein Formularfeld zu ändern. Trotzdem können Sie den Mauszeiger mittels API-Funktionen ziemlich einfach nach Belieben ändern. Die beiden benötigten Funktionen sind LoadCursorFromFileA und SetCursor. Schreiben Sie in einem Modul folgenden Code:

Declare Function LoadCursorFromFileA Lib "user32" ( _
ByVal lpFileName As String) As Long
Declare Function SetCursor Lib "user32" (ByVal hCursor As Long) As Long
 
Sub MausHand()
Dim strPfadCursor As String
Dim lngCursor As Long
 
strPfadCursor = CurrentProject.Path & "Hand.cur"
'strPfadCursor = CurrentProject.Path & "Banana.ani"
 
lngCursor = LoadCursorFromFileA(strPfadCursor)
If lngCursor = 0 Then
Exit Sub
Else
Call SetCursor(lngCursor)
End If
End Sub

Jetzt ist die Prozedur fertig und kann aufgerufen werden. Dazu können Sie in einem beliebigen Formular-Modul die MouseMove-Ereignisse von dessen Textboxen oder Schaltflächen nutzen:

Private Sub btnSchliessen_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
MausHand
End Sub
 
Private Sub edtDatum_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
MausHand
End Sub
 
Private Sub edtText_MouseMove(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
MausHand
End Sub

Bei der Kombination Bezeichnungsfeld/Textbox ist auch über dem Bezeichnungsfeld der geänderte Cursor zu sehen. Um das zu vermeiden, müssen Sie das Bezeichnungsfeld von der Textbox trennen: markieren Sie es im Entwurf, schneiden es in die Zwischenablage aus und fügen es direkt wieder ein.

Wenn eine Datenbank sehr groß wird, kann es hilfreich sein, zu sehen, in welchen Tabellen das Volumen versteckt ist. Sowohl die Menge der Daten als auch der evtl. zu groß gewählte Datentyp können das verursachen. Das zu ermitteln ist jedoch mehr als mühsam, weil es sowohl im Tabellenentwurf als auch in der angezeigten Tabelle enthalten ist.

Der folgende Code schreibt für alle Tabellen und alle Felder deren Feldgröße, mittlere und maximale Belegung (nur für Textfelder wichtig) und die Anzahl der Datensätze automatisch in eine Textdatei, die bei Bedarf direkt in Excel importiert werden kann:

Sub ErmittleTabellenGroesse()
Dim tblDiese As DAO.TableDef
Dim rcsTabelle As DAO.Recordset
Dim fldDieses As DAO.Field
Dim varMW As Variant
Dim varMax As Variant
Dim varAnzDS As Variant
Dim lngKanal As Long
 
lngKanal = FreeFile()
 
Open CurrentProject.Path & "TabellenGroessen.txt" For Output As lngKanal
Print #lngKanal, "Tabellenname" & vbTab & "Feldname" & vbTab & _
"Feldgröße" & vbTab & "Mittelwert" & vbTab & "Max"
 
For Each tblDiese In CurrentDb.TableDefs
If Not (tblDiese.Name Like "?Sys*" Or tblDiese.Name Like "~*") Then
Print #lngKanal, tblDiese.Name
 
For Each fldDieses In tblDiese.Fields
Set rcsTabelle = CurrentDb.OpenRecordset( _
"SELECT AVG(Len([" & fldDieses.Name & "])) AS x FROM [" & _
tblDiese.Name & "];", dbOpenDynaset)
varMW = rcsTabelle.Fields("x").Value
rcsTabelle.Close
 
Set rcsTabelle = CurrentDb.OpenRecordset( _
"SELECT MAX(Len([" & fldDieses.Name & "])) AS x FROM [" & _
tblDiese.Name & "];", dbOpenDynaset)
varMax = rcsTabelle.Fields("x").Value
rcsTabelle.Close
 
Print #lngKanal, tblDiese.Name & vbTab & fldDieses.Name & vbTab & _
fldDieses.Size & vbTab & varMW & vbTab & varMax
Next
 
Set rcsTabelle = CurrentDb.OpenRecordset(tblDiese.Name, dbOpenTable)
varAnzDS = rcsTabelle.RecordCount
rcsTabelle.Close
Print #lngKanal, varAnzDS & vbTab & "Datensätze"
Print #lngKanal, ""
Print #lngKanal, ""
Print #lngKanal, ""
End If
Next

Close #lngKanal
End Sub

Wegen des CurrentProject-Objects läuft dieser Code nur ab Access 2000, für ältere Versionen müssen Sie stattdessen einen konkreten Pfad einsetzen oder beispielsweise die CurDir()-Funktion nutzen.

Oft ist es notwendig zu wissen, ob Access in der Vollversion läuft oder nur als Runtime ausgeführt wird. Die Runtime-Umgebung kann beispielsweise ein Formular nicht in den Filtermodus umschaltet und enthält kein Datenbank-Fenster. Sie können das mit

If SysCmd(acSysCmdRuntime) Then
'also eine Runtime-Umgebung
End If

herausbekommen. Die Funktion liefert den Werte True zurück, wenn Access nur als Runtime installiert ist.

Access bietet nach wie vor keine Möglichkeit, Zeitangaben über einen Tag hinaus anzuzeigen, denn alle Zeitformate kürzen die Anzeige auf maximal 24 Stunden. In Excel gäbe es eine Format-Anweisung [hh]:mm:ss (Achtung, bei Excel sind m die Minuten, bei Access ist es n!), die wenigstens über 24 Stunden hinaus anzeigt, aber Access kann das ärgerlicherweise immer noch nicht.

Sie müssen sich also mit einer Funktion behelfen, die aus dem Datum/Zeit-Datentyp eine Zeichenkette macht. Das bedeutet, dass Sie mit dem Ergebnis nicht mehr weiterrechnen können und es in einem berechneten Feld (siehe auch Tipp "Berechnete Felder in Abfragen") stehen muß. Wenn Sie mit dieser Einschränkung leben können, können Sie die folgende Funktion einsetzen:

Function meinDatumsFormat(datWert As Date) As String
Select Case datWert
Case #12:00:00 AM# 'nur, falls Sie Mitternacht als 24:00:00 anzeigen wollen
meinDatumsFormat = "24:00:00"
Case Else
If CLng(datWert) = 0 Then
meinDatumsFormat = Format(Hour(datWert), "00") & ":" & _
Format(datWert, "nn:ss")
Else
meinDatumsFormat = Format(Day(datWert) * 24 + Hour(datWert), "00") & _
":" & Format(datWert, "nn:ss")
End If
End Select
End Function

Um das direkt in einem Modul zu testen, schreiben Sie die folgende Prozedur:

Sub TesteDas()
Debug.Print meinDatumsFormat(#12/24/2008 11:59:59 AM#)
Debug.Print meinDatumsFormat(#12:00:00 AM#)
Debug.Print meinDatumsFormat(#12:00:01 AM#)
Debug.Print meinDatumsFormat(3.99)
End Sub

Die Eingabe der verschiedenen Beispielwerte führt zur Anzeige dieser Daten im Direktfenster (welches Sie mit Strg+G anzeigen können):

Eingabe: 24.12.2008 11:59:59 = 24.12.2008 11:59:59= 587:59:59
Eingabe: 00:00:00 = 30.12.1899 00:00:00= 24:00:00
Eingabe: 00:00:01 = 30.12.1899 00:00:01= 00:00:01
Eingabe: 02.01.1900 23:45:36 = 02.01.1900 23:45:36= 71:45:36

Beachten Sie insbesondere die letzte Zeile, die zeigt, dass auch summierte Datum/Zeit-Werte über einen Tag hinaus funktionieren, selbst wenn sie als Dezimalzahl eingegeben werden.

Bevor Sie via VBA auf die Daten aus einem Formular zugreifen, sollten Sie sicherstellen, dass es überhaupt geöffnet ist. Dann lässt sich im laufenden Code so prüfen, ob das Formular geöffnet ist:

Sub TestFormOffen()
If IstFormularOffen("frmBeliebigerName") Then
'...hier beliebiger Code
Else
'...also muss es erst geöffnet werden!
End If
End Sub

Für die Funktion IstFormularOffen gibt es verschiedene Methoden, von denen meistens die folgende gewählt wird. Dabei wird die Namensliste aller geöffneten Formulare mit dem gesuchten Formularnamen verglichen:

Function IstFormularOffen(strFormName As String)
Dim i As Integer
 
IstFormularOffen = False
For i = 0 To Forms.Count - 1
If LCase(Forms(i).FormName) = LCase(strFormName) Then
IstFormularOffen = True
Exit For
End If
Next
End Function

Das lässt sich aber viel besser und vor allem kürzer programmieren, denn Access stellt mit der SysCmd-Funktion eine Möglichkeit zur Verfügung, die außerdem auch den Status des Formulars zurückgibt. Die ist allerdings in der Hilfe sehr gut versteckt, so dass sie kaum bekannt ist:

Function IstFormularOffen(strFormName As String)
IstFormularOffen = (SysCmd(acSysCmdGetObjectState, _
acForm, strFormName) = acObjStateOpen)
End Function

Mit der Konstanten acObjStateOpen lässt sich nicht nur feststellen, dass das Formular geöffnet ist, sondern auch, ob es ungespeicherte Daten enthält (acObjStateDirty) oder ob es neu ist (acObjStateNew). Zudem erlaubt der zweite Parameter (hier mit acForm) statt Formularen auch alle anderen Objekte der Datenbank (z.B. acReport für Berichte) ebenfalls auf ihren Status zu prüfen.

Sobald Sie in VBA einen SQL-Befehl mit Datumsanteil erstellen, haben Sie Ärger mit der automatisch deutschen Datumsformatierung. Typischerweise steht in Ihrem Code eine Zeile wie die folgende:

Dim strSQL As String
 
strSQL = "SELECT * FROM [Tabelle1] WHERE [Datum]<=" & Date
MsgBox strSQL 'nur zum Prüfen

Mit der MsgBox sehen Sie, dass als Ergebnis SELECT * FROM [Tabelle1] WHERE [Datum]<=24.12.2007 ermittelt wird. In einem SQL-Befehl ist aber amerikanische Syntax und damit ein anderes Datumsformat erforderlich. Während eines manuellen Abfrage-Entwurfs übernimmt der Access-Abfrageeditor die automatische Umwandlung, aber hier nicht.

Da dies Problem im Code sehr häufig vorkommt, sollten Sie sich direkt eine Funktion SQLDatum() schreiben, welche das Datum im gewünschten Format liefert:

Function SQLDatum(datDatum As Date) As String
SQLDatum = "#" & Format(datDatum, "mm/dd/yyyy") & "#"
End Function

Damit trotz deutscher Ländereinstellung in der Systemsteuerung die Schrägstriche im Datum erscheinen, müssen diese mit / als so genanntes "Literal" erzwungen werden. Auch die Reihenfolge ist ja verändert, daher steht zuerst der Monat und dann der Tag. Der Bequemlichkeit halber sind die für ein SQL-Datum vorgeschriebenen Doppelkreuze (#) auch schon angefügt. Damit kann der Code oben so verbessert werden:

strSQL = "SELECT * FROM [Tabelle1] WHERE [Datum]<=" & SQLDatum(Date)

Damit liefert die MsgBox nun das korrekte Ergebnis SELECT * FROM [Tabelle1] WHERE [Datum]<=#12/24/2007#. Karl Donaubauer zeigt auf seiner FAQ-Seite alternativ noch eine zweite Version für ein korrektes (ISO-)Datum.

Für einen einfachen Überblick über die Datenbank können Sie Access-VBA sehr einfach ermitteln lassen, wie viele Objekte in welchem Bereich enthalten sind:

Sub ZaehleObjekte1()
Dim cts As Containers
 
Set cts = CurrentDb.Containers
MsgBox "Es gibt " & vbCrLf & _
cts("Tables").Documents.Count & " Tabellen und Abfragen," & vbCrLf & _
cts("Forms").Documents.Count & " Formulare," & vbCrLf & _
cts("Reports").Documents.Count & " Berichte," & vbCrLf & _
cts("Scripts").Documents.Count & " Makros," & vbCrLf & _
cts("Modules").Documents.Count & " Module" & vbCrLf
End Sub

Die Zuweisung von CurrentDb.Containers an die Variable cts dient nur der kürzeren Schreibweise. Allerdings werden mit dieser Technik Tabellen und Abfragen gemeinsam gezählt. Seit Access 2000 steht mit dem CurrentProject-Objekt eine Alternative zur Verfügung:

Sub ZaehleObjekte2()
MsgBox "Es gibt " & vbCrLf & _
CurrentDb.TableDefs.Count & " Tabellen," & vbCrLf & _
CurrentDb.QueryDefs.Count & " Abfragen," & vbCrLf & _
CurrentProject.AllForms.Count & " Formulare," & vbCrLf & _
CurrentProject.AllReports.Count & " Berichte," & vbCrLf & _
CurrentProject.AllMacros.Count & " Makros," & vbCrLf & _
CurrentProject.AllModules.Count & " Module" & vbCrLf
End Sub

Beachten Sie dazu auch die übrigen Tipps zu den Themen "Alle ... der Datenbank ermitteln mit VBA" auf dieser Seite.

Nachdem Sie eventuell im Tipp "Zeilen fortlaufend nummerieren mit SQL" schon gelesen haben, dass bei vielen Datensätzen ganz erhebliche Laufzeiten entstehen, liegt die Versuchung nahe, dieses Problem per VBA-Function zu lösen. Tatsächlich gibt es dazu eine Lösung:

Option Explicit
 
Dim mlngNr As Long
 
Function StartNr() As Long
'ohne Parameter für einmaligen Aufruf
mlngNr = 0
End Function
 
Function LfdNr(varEgal As Variant) As Long
'muss Parameter haben, damit es mehrfach aufgerufen wird
LfdNr = mlngNr
mlngNr = mlngNr + 1
End Function

Dabei machen sich die Funktionen jeweils zunutze, dass sie ohne Parameter nur einmal pro Abfrage, mit Parameter aber für jede Zeile neu aufgerufen werden. Über diesen Trick können Sie den Startwert der Modul-öffentlichen Long-Variablen mlngNr vorgeben. Tatsächlich wird jede Zeile mit einer laufenden Nummer versehen, wenn Sie die folgende SQL-Anweisung ausführen:

SELECT StartNr() AS x, LfdNr([KundenNr]) AS Nummer, tblAdressen.*
FROM tblAdressen
ORDER BY tblAdressen.KundenNr;

Die Anzeige der ersten Datenseite ist sogar schon nach 1 Seite fertig, es ist also um ein Vielfaches schneller als die SQL-Variante. Das sieht auch noch gut aus, solange Sie vorwärts durch die Datensätze blättern. Beim Hin- und Herblättern werden Sie aber feststellen, dass Access bei jedem Anzeigen eines Datensatzes weiterzählt, also sogar beim Wechsel zwischen Access und einem anderen Programm.

Die Zeilen sind daher zwar innerhalb einer Seite fortlaufend nummeriert, aber beim Wechsel zu anderen Datensätzen ist das Ergebnis eher unkalkulierbar. Als Lösungen bleiben daher für die meisten Anlässe die langsame und sichere SQL-Variante oder die schnelle und auf Berichte beschränkte "LaufendeSumme"-Variante aus den anderen Tipps.