Die VBA-With-Anweisung

Unter den Elementen, die den Programm-Code unter VBA strukturierter erscheinen lassen, findet die With-Anweisung oft wenig Berücksichtigung. Dabei spart man mit ihr nicht nur Programmtext ein, sondern erleichtert sich über IntelliSense zusätzlich das Schreiben von Objektmethoden.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1501_WithAnweisung.mdb.

Grundlegende Syntax

Die With-Anweisung stellt einen Bezug zu einer Variablen her, der entweder ein benutzerdefinierter Datentyp (UDT) zugrunde liegt, oder ein Objekt. Ob diese in ihren eigenen Modulen deklariert sind, oder in einer Verweisbibliothek, spielt dabei keine Rolle. Die Blockanweisung besteht aus zwei Elementen, dem Blockstart und dem Blockende:

Dim Variable As ...
With [Variable]  'Blockstart
.[Methode oder]
.[Eigenschaft] = ...
End With  'Blockende

Nach dem reservierten Wort With folgt der Name einer Variablen, auf die sich die Methoden, Eigenschaften oder Typelemente im Folgenden beziehen sollen.

Wird in einer Prozedur die Variable nicht mehr weiter benötigt, so schließt man den Bezug mit der Anweisung End With.

With im Einsatz

Einen Code aus dem wahren Datenbankprogrammiererleben finden Sie im Listing 1 der Beispieldatenbank, wo auf eine Tabelle tblTest eine Datensatzgruppe (Recordset) geöffnet wird, um sie mit Datensätzen zu füllen und jene anschließend im VBA-Direktfenster auszugeben. In der ersten Zeile der Routine wird die Tabelle zunächst mit einer SQL-Anweisung per Database.Execute geleert. Dann erfolgt das Setzen des Recordsets rsTest auf die Tabelle. Die Recordset-Variable rsTest wurde übrigens bereits im Modulkopf deklariert, ebenso die Zählervariable i:

Sub OhneWITH()
     CurrentDb.Execute "DELETE * FROM tblTest"
     Set rsTest = CurrentDb.OpenRecordset("SELECT * FROM tblTest", dbOpenDynaset)
     For i = 1 To 100
         rsTest.AddNew
         rsTest!ID = i
         rsTest!Code = Chr$(65 + 28 * Rnd) & Chr$(65 + 28 * Rnd) & Chr$(65 + 28 * Rnd)
         rsTest.Update
     Next i
     
     rsTest.MoveFirst
     Do While Not rsTest.EOF
         Debug.Print rsTest!ID, rsTest!Code
         rsTest.MoveNext
     Loop
     rsTest.Close
End Sub

Listing 1: Durchlaufen der Datensätze einer Tabelle

Private rsTest As DAO.Recordset
Private i As Long

Im weiteren Verlauf werden in einer Schleife auf den Zähler i der Tabelle hundert Datensätze hinzugefügt, wobei für das Feld Code jeweils ein dreistelliger zufälliger Buchstabencode generiert wird. Zum Schluss werden alle Datensatzinhalte wieder in einer Schleife über Debug.Print in das VBA-Direktfenster ausgegeben. Das Ergebnis wäre etwa dieses:

  1            J\Q
  2            PEZ
  3            BWU
  4            H[N
  5            ULG
...

Auffallend ist, dass der Variablenname rsTest sehr häufig in der Routine auftaucht. Genau dies lässt sich mit der With-Anweisung umgehen, indem zum Blockstart der Verweis auf rsTest gesetzt wird und im Folgenden darauf nur noch indirekt Bezug genommen wird. Der abgewandelte Code steht in Listing 2.

Sub MitWITH()
     CurrentDb.Execute "DELETE * FROM tblTest"
     Set rsTest = CurrentDb.OpenRecordset("SELECT * FROM tblTest", dbOpenDynaset)
     With rsTest
         For i = 1 To 100
             .AddNew
             !ID = i
             !Code = Chr$(65 + 28 * Rnd) & Chr$(65 + 28 * Rnd) & Chr$(65 + 28 * Rnd)
             .Update
         Next i
         .MoveFirst
         Do While Not .EOF
             Debug.Print !ID, !Code
             .MoveNext
         Loop
         .Close
     End With
End Sub

Listing 2: Der gleiche Code unter Einsatz der With-Anweisung

Statt rsTest.AddNew zum Anlegen eines neuen Datensatzes wird nun nur noch der Ausdruck .AddNew benötigt – VBA denkt sich vor den Punkt den oben definierten Objektbezug.

Statt des Punktes ist auch der VBA-Ausrufezeichen-Operator für Auflistungen erlaubt. Deshalb lässt sich nun ein Feld des Recordsets statt über rsTest!Code einfach mit !Code ansprechen.

Kürzer wird die Routine damit nicht. Sie ist im Gegenteil wegen der With-Anweisungen sogar um zwei Zeilen länger. Der Zeichenumfang ist jedoch geringer. Das spielt allerdings weniger eine Rolle als die nun erhöhte übersichtlichkeit des Codes. Die Methoden, Eigenschaften und Feldbezeichnungen des Recordsets treten nun optisch deutlicher zutage, weil sie isolierter dastehen.

Aber nicht nur die Gestalt des Programmcodes ändert sich damit, sondern auch die Art, wie VBA das Modul kompiliert. Denn bei jedem Ansprechen der Variablen rsTest in der ersten Variante sucht es sich gesondert einen Zeiger auf die Objektvariable, um dann deren Methoden auszuführen. Bei With-Blöcken wird intern nur ein Zeiger auf die Objektvariable angelegt und dann für die Methodenaufrufe mehrfach verwendet. Das führt zu einer geringfügig besseren Ausführungsgeschwindigkeit der Routine. Ehemals wurde die With-Anweisung deshalb auch in Sammlungen zu Performance-Tipps aufgenommen, spielt aber in dieser Hinsicht heute keine nennenswerte Rolle mehr – ein paar Nanosekunden mehr oder weniger sind unerheblich.

Objektvariablen überflüssig machen

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar