Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 5/2011.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Definieren Sie eine Standardmethode für eine Klasse und nutzen Sie diese beispielsweise zum Implementieren bestimmter Ereignisse.

Techniken

Klassenprogrammierung

Voraussetzungen

Access 2000 und höher

Beispieldateien

Standardmethode.mdb

Shortlink

www.access-im-unternehmen.de/796

Standardmethode von Klassen nutzen

André Minhorst, Duisburg

Wussten Sie, dass Sie für ein Klassenmodul eine Standardmethode festlegen können? Es funktioniert, und eine solche Methode rufen Sie allein durch die Angabe des entsprechenden Objektnamens auf. Wofür man das braucht? Na, zum Beispiel, um Ereignisprozeduren für Eigenschaften zu implementieren, bei denen dies normalerweise nicht gelingt. So können Sie nun etwa per Ereignisprozedur auf das vollständige Laden einer Webseite mit dem Webbrowser-Steuerelement reagieren anstatt eine Do-While-Schleife so lange laufen zu lassen, bis der gewünschte Status erreicht wird.

Wenn Sie beispielsweise ein Formular programmieren und einer Schaltfläche auf diesem Formular eine Ereignisprozedur zuweisen möchten, also eine Prozedur, die beim Anklicken der Schaltfläche ausgelöst wird, brauchen Sie dazu nur zwei Schritte: Sie tragen im Eigenschaftsfenster den Wert [Ereignisprozedur] für die Eigenschaft Beim Klicken ein und wechseln dann zum VBA-Editor, um die automatisch erstellte Prozedur mit den gewünschten Codezeilen zu ergänzen.

Wenn Sie die Ereignisse eines Objekts von außen, also beispielsweise von einem Klassenmodul aus abgreifen möchten, deklarieren Sie dieses Objekt mit dem Schlüsselwort WithEvents, also beispielsweise so:

Dim WithEvents objForm as Form

Über die beiden Kombinationsfelder des Codefensters des Klassenmoduls greifen Sie dann auf die Ereignisse des jeweiligen Objekts zu und versehen diese mit entsprechenden Ereignisprozeduren.

Es gibt aber auch Ereignisse, auf die Sie nicht wie gewohnt reagieren können. Ein Beispiel ist das Objekt XMLHTTP der Bibliothek Microsoft XML, v x.0.

Damit können Sie beispielsweise Webseiten oder sogar komplette Dateien aus dem Internet herunterladen, wie der Beitrag Webservice light zeigt (www.access-im-unternehmen.de/798).

Abb. 1 liefert einen Einblick in die Member dieser Klasse, wobei onReadyStateChange nach einem Kandidaten für ein Ereignis aussieht, aber eigentlich eine Eigenschaft ist.

pic001.png

Abb. 1: Eventhandler der XMLHTTP-Klasse

In diesem Fall wäre eine Ereigniseigenschaft namens onReadyStateChange nützlich, weil man mit einer entsprechenden Ereignisprozedur etwa ermitteln könnte, wann die zu ladende Quelle vollständig ist.

Der Objektkatalog gibt preis, dass Sie dieser Eigenschaft ein Objekt zuweisen können und nicht etwa eine Zeichenkette, um den Namen einer beim Eintreten dieses vermeintlichen Ereignisses auszulösenden Prozedur anzugeben.

Außerdem steht in der Beschreibung noch Register a complete event handler. Was können wir damit anfangen?

Klasse mit Standardmethode

Der Eigenschaft onReadyStateChange können Sie ein Objekt auf Basis einer Klasse zuweisen, die über eine Standardmethode verfügt, also eine Methode, die nicht explizit aufgerufen werden muss.

Wahrscheinlich kennen Sie Standardeigenschaften von Objekten: Wenn Sie beispielsweise auf den Inhalt eines Textfelds in einem Formular zugreifen möchten, können Sie dies auf zwei Arten erledigen. Die korrekte Art wäre die folgende:

Debug.Print Me!txtText.Value

Eingebürgert hat sich aber die zweite Variante, die es sich zunutze macht, dass Value die Standardeigenschaft dieses Steuerelements ist und Sie diese nicht extra angeben müssen:

Debug.Print Me!txtText

Auf die gleiche Weise arbeiten verkappte Ereigniseigenschaften wie onReadyStateChange. Dieser können Sie ein Objekt zuweisen, das eine Standardmethode besitzt. Schade nur, dass Sie mit dem VBA-Editor keine Standardmethode für eine Klasse festlegen können!

Zum Glück gibt es die Möglichkeit, dies außerhalb des VBA-Editors zu erledigen, und zwar mit einem Text-Editor.

Wir betrachten die Vorgehensweise zunächst anhand eines einfachen Beispiels. Eine Klasse mit einer Standardmethode soll nach dem Aufruf schlicht ein Meldungsfenster anzeigen. Dazu legen Sie in einer Datenbank eine neue Klasse namens clsDefaultMethod an und fügen dieser lediglich die folgende Prozedur hinzu:

Public Sub DefaultMethod()

    MsgBox "Standardmethode aufgerufen!"

End Sub

Speichern Sie die Klasse. Danach legen Sie ein Standardmodul an und erstellen darin eine Prozedur, welche die Standardmethode der neuen Klasse testen soll. Diese Prozedur sieht wie folgt aus:

Public Sub TestDefaultMethod()

    Dim objDefaultMethod As clsDefaultMethod

    Set objDefaultMethod = New clsDefaultMethod

    objDefaultMethod

End Sub

Wenn Sie die Prozedur TestDefaultMethod aufrufen, löst dies den Fehler Objekt unterstützt diese Eigenschaft oder Methode nicht aus - und zwar wie erwartet.

Wie sollen wir die Methode namens DefaultMethode nun zu einer Standardmethode machen, um diese durch den reinen Aufruf des Objekts auszuführen? Dies gelingt in drei Schritten:

  • Speichern Sie die Klasse über den Kontextmenübefehl Datei exportieren... des Eintrags clsDefaultMethode im Objekt-Explorer in einem beliebigen Verzeichnis.
  • Öffnen Sie die Datei in einem Texteditor Ihrer Wahl und fügen Sie die Zeile Attribute DefaultMethod.VB_UserMemId = 0 als erste Zeile der Prozedur DefaultMethod hinzu (s. Abb. 2).
  • pic002.png

    Abb. 2: Eine Methode zur Standardmethode machen

  • Kehren Sie zum VBA-Editor zurück. Entfernen Sie die Klasse clsDefaultMethode mit dem Kontextmenüeintrag Entfernen von clsDefaultMethod... und importieren Sie die geänderte Fassung (Menüeintrag Datei|Datei importieren...).

Fertig! Wenn Sie die Klasse nun im VBA-Editor betrachten, sieht alles wie zuvor aus (s. Abb. 3). Unter der Haube hat sich jedoch einiges getan - dies zeigt sich, wenn Sie die Prozedur TestDefaultMethod nochmals aufrufen.

pic003.png

Abb. 3: Im VBA-Editor sind keine Änderungen erkennbar.

Nun gelingt der Aufruf der Standardmethode nur durch Angabe des Objektnamens - das Meldungsfenster erscheint!

Ereignis per Standardmethode

Mit dieser Erkenntnis im Gepäck kehren wir zur eigentlichen Aufgabenstellung zurück - dem Auslösen eines Ereignisses, wenn sich der Zustand beim Herunterladen einer Webseite oder einer Datei ändert.

Wir verwenden zunächst eine einfache Variante, bei der die Klasse mit der Ereignisprozedur den Großteil der Arbeit übernimmt. Damit dies gelingt, übergeben wir der Klasse einen Verweis auf das XMLHTTP-Objekt - so kann die Klasse direkt auf die enthaltenen Informationen zugreifen.

Der Prozess beginnt mit dem Aufruf der Prozedur GetWebpageOrFile und der Übergabe der aufzurufenden Adresse:

GetWebpageOrFile "http://www.ebay.de"

Die Prozedur GetWebpageOrFile finden Sie in Listing 1. Die Prozedur erstellt zunächst ein neues XMLHTTP-Objekt und speichert den Verweis darauf in der Variablen objXMLHTTPRequest. Außerdem erzeugt sie eine neue Instanz der Klasse clsXMLHTTPHandler (s. Listing 2).

Listing 1: Herunterladen einer Webseite oder Datei

Public Function GetWebpageOrFile(ByVal strDateiadresse As String) As Long

    Dim objXMLHTTPRequest As MSXML2.XMLHTTP

    Dim objXMLHTTPHandler As clsXMLHTTPHandler

    Set objXMLHTTPRequest = New MSXML2.XMLHTTP

    Set objXMLHTTPHandler = New clsXMLHTTPHandler

    Set objXMLHTTPHandler.XMLHTTPRequest = objXMLHTTPRequest

    With objXMLHTTPRequest

        .OnReadyStateChange = objXMLHTTPHandler

        .Open "GET", strDateiadresse, True

        .send ""

    End With

End Function

Listing 2: Klasse mit Standardmethode

Dim mXMLHttpRequest As MSXML2.XMLHTTP

Public Property Set XMLHTTPRequest(objXMLHTTPRequest As MSXML2.XMLHTTP)

    Set mXMLHttpRequest = objXMLHTTPRequest

End Property

Sub OnReadyStateChangeHandler()

    Debug.Print mXMLHttpRequest.ReadyState

    If mXMLHttpRequest.ReadyState = 4 Then

        If mXMLHttpRequest.status = 200 Then

            Debug.Print "Fertig"

        End If

    End If

End Sub

Damit die Standardmethode dieser Klasse später auf die Informationen des XMLHTTP-Objekts zugreifen kann, übermitteln Sie dieser einen Verweis darauf. Die Klasse clsXMLHTTPHandler bietet dazu eine Property Set-Methode an, die den Verweis in der Member-Variablen mXMLHttpRequest speichert.

Sie enthält außerdem eine Prozedur namens OnReadyStateChangeHandler. Diese wird, wie oben beschrieben, durch die Zeile Attribute DefaultMethod.VB_UserMemId = 0 als Standardmethode der Klasse festgelegt.

In der Prozedur GetWebpageOrFile weisen Sie nun der Eigenschaft OnReadyStateChange einen Verweis auf die Instanz der Klasse clsXMLHTTPHandler zu. Dadurch wird beim Eintreten dieses Ereignisses die Standardmethode dieser Klasse, also OnReadyStateChangeHandler, aufgerufen. Diese erledigt in dieser Version nicht viel mehr, als einfach nur bei jedem Aufruf den Status auszugeben und den Ausdruck Fertig im Direktfenster anzuzeigen, wenn der Ladevorgang beendet ist.

In der Praxis bedeutet dies, dass Sie für jede Ereigniseigenschaft, die einen Objektverweis als Wert erwartet, eine neue Klasse anlegen müssen, da jede Klasse ja nur über eine Standardmethode verfügen kann.

Allzu viele Beispiele für Bibliotheken mit solchen Klassen scheint es jedoch nicht zu geben, sodass der Aufwand und die zusätzlichen Klassen überschaubar bleiben.

Praxisbeispiel: Sourcecode von Webseiten

Im folgenden Beispiel soll der Benutzer eine URL in ein Textfeld eingeben (Achtung: http:// nicht vergessen!). Ein Klick auf die Schaltfläche sorgt dann dafür, dass der Quellcode der Seite geladen und in einem Textfeld angezeigt wird.

Die nachfolgend beschriebenen Code-Elemente stammen aus dem Klassenmodul des Formulars frmLoadURL und dem Klassenmodul clsXMLHTTPHandlerWithEvents (s. Abb. 4).

pic004.png

Abb. 4: Dieses Beispielformular lädt den Quellcode von Webseiten.

Das Klassenmodul clsXMLHTTPHandlerWithEvents soll im Gegensatz zum Klassenmodul des vorherigen Beispiels noch zwei Ereignisse auslösen, die dann innerhalb der erzeugenden Klasse, in diesem Fall dem Klassenmodul des Formulars frmLoadURL, mit Code gefüllt werden können.

Außerdem soll das Klassenmodul clsXMLHTTPHandlerWithEvents zusätzlich den eigentlichen Ladevorgang übernehmen.

Dazu benötigen wir in dieser Klasse zunächst eine Objektvariable zum Speichern des Verweises auf ein XMLHTTP-Objekt, das die Methoden zum Laden der Webseite bereitstellt:

Dim objXMLHTTPRequest As MSXML2.XMLHTTP

Beim Instanzieren der Klasse soll gleich ein Objekt des Typs XMLHTTP erzeugt werden. Dazu legen Sie das Initialize-Ereignis an und füllen dieses wie folgt:

Private Sub Class_Initialize()

    Set objXMLHTTPRequest = New MSXML2.XMLHTTP

End Sub

Die Klasse soll den Sourcecode der geladenen Webseite laden und bereitstellen, also richten wir zu diesem Zweck eine Membervariable namens m_SourceCode ein:

Dim m_SourceCode As String

Der Inhalt dieser Variablen soll über eine Eigenschaft namens SourceCode von außen lesbar sein.

Dazu legen Sie eine entsprechende Property Get-Prozedur an:

Public Property Get SourceCode() As String

    SourceCode = m_SourceCode

End Property

An dieser Stelle wechseln wir kurz zum Klassenmodul des Formulars frmLoadURL. Dieses soll die Eigenschaften und Methoden der Klasse clsXMLHTTPHandlerWithEvents nutzen.

Damit auf die noch zu definierenden Ereignisse der Klasse reagiert werden kann, deklarieren wir eine Objektvariable auf Basis dieses Klassenmoduls mit dem Schlüsselwort WithEvents:

Dim WithEvents objXMLHTTPHandler

As clsXMLHTTPHandlerWithEvents

Um die Klasse einsatzbereit zu machen, legen Sie gleich beim Laden des Formulars ein neues Objekt auf Basis des entsprechenden Klassenmoduls an:

Private Sub Form_Load()

    Set objXMLHTTPHandler = New clsXMLHTTPHandlerWithEvents

End Sub

Laden der URL

Damit Sie der Klasse clsXMLHTTPHandlerWithEvents mitteilen können, dass sie den Sourcecode einer Webseite laden soll, legen Sie im Klassenmodul eine entsprechende Methode an. Diese sieht wie folgt aus:

Public Sub Load(strURL As String)

    With objXMLHTTPRequest

        .OnReadyStateChange = Me

        .Open "GET", strURL, True

        .send ""

    End With

End Sub

Neben den bereits bekannten Methoden zum Öffnen und Laden der angegebenen URL enthält diese Methode eine sehr wichtige Anweisung:

.OnReadyStateChange = Me

Diese sorgt dafür, dass ein Verweis auf die Klasse selbst als Wert der Eigenschaft OnReadyStateChange festgelegt wird.

Damit sorgen Sie dafür, dass beim Auslösen des Ereignisses OnReadyStateChange die Standardmethode der angegebenen Klasse, also der Klasse clsXMLHTTPHandlerWithEvents selbst, ausgelöst wird.

Diese sieht etwas umfangreicher als im vorherigen Beispiel aus (s. Listing 3). Sie prüft jeweils den Status des Ladevorgangs. Hat die entsprechende Eigenschaft den Wert 200, wird der Quelltext aus der Eigenschaft responseText in die Membervariable m_SourceCode eingetragen. Außerdem wird mit RaiseEvents ein Ereignis namens LoadComplete ausgelöst!

Listing 3: Diese Prozedur wird bei Statusänderungen des Ladevorgangs ausgelöst.

Sub OnReadyStateChange()

    If objXMLHTTPRequest.ReadyState = 4 Then

        Select Case objXMLHTTPRequest.status

            Case 200

                m_SourceCode = objXMLHTTPRequest.responseText

                RaiseEvent LoadComplete

            Case Else

                RaiseEvent LoadError(objXMLHTTPRequest.status, objXMLHTTPRequest.statusText)

        End Select

    End If

End Sub

Damit dieses in der instanzierenden Klasse, also etwa im Klassenmodul des Formulars frmLoadURL, implementiert werden kann, deklarieren Sie es wie folgt im Klassenmodul clsXMLHTTPHandlerWithEvents:

Public Event LoadComplete()

Im Klassenmodul des Formulars implementieren Sie das Ereignis dann wie folgt:

Private Sub objXMLHTTPHandler_LoadComplete()

    Me!txtSourcecode = objXMLHTTPHandler.SourceCode

End Sub

Die einzige Anweisung dieser Ereignisprozedur trägt den Sourcecode der fertig geladenen Webseite in die Membervariable m_SourceCode ein. Damit der Ladevorgang überhaupt startet, rufen Sie die Methode Load der Klasse etwa beim Anklicken der Schaltfläche cmdLaden des Formulars auf:

Private Sub cmdLaden_Click()

    objXMLHTTPHandler.Load Me!txtURL

End Sub

Bei Fehler

Nun kann es auch geschehen, dass die angegebene Seite nicht geladen werden konnte. In diesem Fall soll ein weiteres Ereignis ausgelöst werden, das Sie wie folgt festlegen:

Public Event LoadError(lngErr As Long, strDescription As String)

Die Implementierung erfolgt beispielsweise durch die Ausgabe von Fehlernummer und -meldung in einem einfachen Meldungsfenster:

Private Sub objXMLHTTPHandler_LoadError(lngErr As Long, strDescription As String)

    MsgBox lngErr & " " & strDescription

End Sub

Das Ereignis LoadError wird ebenfalls von der Prozedur OnReadyStateChange ausgelöst, allerdings nur, wenn der Status nach vollständigem Ladevorgang nicht den Wert 200 enthält. Wenn die Seite nicht gefunden werden konnte, liefert das XMLHTTP-Objekt beispielsweise den Wert 404 zurück.

Zusammenfassung und Ausblick

Mit der hier vorgestellten Technik umgehen Sie beispielsweise die wenig elegante Do While-Schleife, die sonst nötig wäre, um auf das Ende des Ladevorgangs einer Webseite zu warten. Außerdem ist es spannend, welche versteckten Möglichkeiten VBA bietet. Haben Sie weitere Ideen, was sich mit den neuen Möglichkeiten anfangen lässt? Dann senden Sie diese einfach per E-Mail an info@access-im-unternehmen.de!

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Download

Download

Die .zip-Datei enthält folgende Dateien:

Standardmethode.mdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.