Zugriff auf Zwischenablage per API

Obwohl die Zwischenablage zu den wichtigsten Elementen von Windows gehört, verfügt Access selbst in der aktuellsten Version über keinerlei Funktionen, um Daten in die Zwischenablage übertragen oder aus der Zwischenablage übernehmen zu können. So ist es nicht möglich, beispielsweise eine Adresse über die Zwischenablage an eine andere Office- Anwendung zu übergeben oder das Ergebnis einer Berechnung aus Excel in einen Datensatz einzufügen. Glücklicherweise stellt das API jedoch verschiedene Funktionen bereit, mit deren Hilfe sich von Access aus auf die Zwischenablage zugreifen lässt:

Declare Function OpenClipboard Lib „user32“ (ByVal hwnd As Long) As Long
Declare Function SetClipboardData Lib „user32“ (ByVal wFormat As Long, ByVal hMem As Long) As Long
Declare Function GetClipboardData Lib „user32“ (ByVal wFormat As Long) As Long
Declare Function CloseClipboard Lib „user32“ () As Long

Der Einsatz dieser API-Funktionen gestaltet sich jedoch recht kompliziert: Da Windows ein Multitasking-Betriebssystem ist und somit Anwendungen gleichzeitig auf die Zwischenablage zugreifen können, sind bestimmte Regeln einzuhalten.

So muss für den Zugriff auf die Zwischenablage zunächst über „OpenClipboard()“ ein eindeutiger Handle angefordert werden, der beim Aufruf weiterer Zwischenablage- Funktionen wie „SetClipboard- Data()“ (Daten in der Zwischenablage ablegen) oder „GetClipboardData()“ (Daten aus der Zwischenablage abrufen) jeweils als Parameter anzugeben ist.

Die Daten werden nicht einfach als Zeichenkette in der Zwischenablage abgelegt oder von dort in eine Zeichenkette eingelesen, vielmehr erfolgt der Austausch über einen geschützten Speicherblock, dessen Adresse zum Beispiel bei „SetClipboard- Data()“ als Parameter „hMem“ anzugeben ist beziehungsweise dessen Adresse von „GetClipboardData()“ als Funktionsergebnis geliefert wird. Da VBA keine Speicheroperationen unterstützt, müssen weitere API-Funktionen wie „Global- Alloc()“ oder „lStrCpy()“ für die Reservierung von Speicherblöcken und die Übertragung von Daten in diesen Speicherblock eingesetzt werden.

Um also zum Beispiel einen Text in der Zwischenablage abzulegen, sind hintereinander die Funktionen „OpenClipboard()“ (Zugriff öffnen), „GlobalAlloc()“ (Speicherblock reservieren), „lStrCpy()“ (Daten in Speicherblock übertragen), „SetClipboardData()“ (Speicherblock an Zwischenablage übergeben), „CloseClipboard()“ (Zugriff schließen) und „GlobalFree()“ (Speicherblock wieder freigeben) aufzurufen.

So nutzen Sie das vorbereitete Klassenmodul

Damit Sie sich mit diesen „Aufruforgien“ nicht herumplagen müssen, haben wir ein Klassenmodul „ClpBrd“ vorbereitet, das Sie universell in eigene Projekte einbinden können und das es Ihnen erlaubt, Texte aus Datensätzen in der Zwischenablage abzulegen oder Texte aus der Zwischenablage auszulesen und in Felder oder Datensätze einzufügen. In der Beispieldatenbank ZWIABLG.MDB (kostenloser Download auf www.access-aktuell. de mit dem Download-Code DXF) finden Sie das bereits erwähnte Klassenmodul „ClpBrd“, das Ihnen vier Methoden zur Verfügung stellt:

Methode

Funktion

SetData

zum Ablegen von Texten
in der Zwischenablage

GetData


zum Auslesen von Texten
aus der Zwischenablage

Clear

zum Löschen
der Zwischenablage

ClpBrdEmpty

zum Prüfen
der Zwischenablage

Der Zugriff auf die Methoden/Eigenschaften eines Klassenmoduls erfolgt über eine Objektvariable, die zunächst initialisiert werden muss:

Dim ZA As New ClpBrd

Hier wird eine Objektvariable „ZA“ vom Typ „ClpBrd“ deklariert, die für den Aufruf der im Klassenmodul definierten Methoden verwendet wird. Durch das Schlüsselwort „New“ generiert Access eine neue Instanz des Klassenmoduls und lädt es für den sofortigen Zugriff auf dessen Methoden/ Eigenschaften in den Speicher. Diese Anweisung müssen Sie in jede Ereignisprozedur oder VBA-Routine, aus der heraus Sie auf die Zwischenablage zugreifen möchten, aufnehmen.

Daten in der Zwischenablage ablegen

Um nun beispielsweise einen Feldinhalt über die Methode „SetData“ in die Zwischenablage zu kopieren, käme folgende Anweisung zum Einsatz:

Dim ZA As New ClpBrd
…..
ZA.SetData Me.Ort
…..

„SetData“ erwartet lediglich einen einzigen Parameter: Den in die Zwischenablage zu übertragenden Text. Diesen können Sie, wie oben gezeigt, als Feldnamen, aber auch als Konstante, Variable oder als Ausdruck angeben:

Dim ZA As New ClpBrd, strOrt as String
…..
strOrt = Me.Ort
ZA.SetData strOrt
…..
ZA.SetData „Hamburg“
…..
ZA.SetData
DLookup(„[Ort]“,“PLZOrte“, „[PLZ]= 20111“)
…..

Der zu übertragene Text kann beliebig lang sein und beispielsweise ein komplettes Memofeld umfassen, er sollte aber eine maximale Länge von ca. 64.000 Zeichen nicht überschreiten. Diese Beschränkung resultiert daraus, dass der Zugriff auf die Zwischenablage über Windows-API-Funktionen mithilfe eines geschützten Speicherblocks erfolgt, der (ebenfalls über API-Funktionen) separat angefordert und reserviert werden muss. Mit Access-Variablen kann hier nicht gearbeitet werden, da sich diese „beweglich“ im Speicher befinden und ihre Adresse ändern können – schlimmstenfalls würde eine später aufgerufene API-Funktion dadurch auf einen nicht initialisierten Speicherbereich zugreifen und Access oder andere Anwendungen zum Absturz bringen. Die Größe von ca. 64.000 Zeichen ergibt sich sozusagen aus historischen Gründen: Früher war die Zwischenablage auf Objekte von maximal 64 KB Größe beschränkt, viele Anwendungen, aber auch Windows-internes Zubehör, verwenden immer noch Speicherbereiche in dieser Größe, sodass die Übertragung von größeren Objekten unter Umständen zu Problemen führen kann.

Bei Bedarf können Sie „SetData“ auch als Funktion einsetzen. Das Funktionsergebnis ist „True“, wenn die Daten erfolgreich in der Zwischenablage abgelegt werden konnten, andernfalls ist es „False“:

PDim ZA As New ClpBrd, strOrt as String
…..
strOrt = Me.Ort
If ZA.SetData(strOrt) = False Then
Beep
MsgBox „Fehler beim Zugriff auf Zwischenablage…“
Exit Sub
End If

Daten aus der Zwischenablage lesen

Analog zu „SetData“ setzen Sie die Methode „GetData“ ein. Diese überträgt den in der Zwischenablage abgelegten Text in eine Variable oder in ein Feld:

PDim ZA As New ClpBrd, strOrt as String
Dim db as Database, rs as Recordset
…..
strOrt = ZA.GetData()
…..
Me.Ort = ZA.GetData()
…..
Set db = CurrentDb()
Set rs = db.OpenRecordset(„Adressen“)
rs.AddNew
…..
rs(„Ort“) = ZA.GetData()
…..
rs.Update
rs.Close
…..

Bitte beachten Sie: „GetData()“ liefert nur Text als Ergebnis. Wenn sich in der Zwischenablage ein Objekt mit anderem Format, beispielsweise eine Bitmap, befindet, gibt „SetData“ eine Fehlermeldung aus und liefert als Ergebnis eine leere Zeichenkette („“)! Die Größe des Puffers für die Übertragung in die Zwischenablage haben wir aus Geschwindigkeitsgründen auf 32 KB beschränkt. Wenn Sie umfangreichere Texte zu übertragen haben, können Sie die Größe des Puffers im Klassenmodul „ClpBrd“ über die Konstante „MAXSIZE“ ändern.

Inhalt der Zwischenablage löschen

Über die Methode „Clear“ können Sie den Inhalt der Zwischenablage löschen. Das sollten Sie beispielsweise in Datenbanken, in denen Sie sensible Informationen verarbeiten, vor dem Beenden der Datenbank unbedingt tun. Andernfalls könnte ein Anwender, der nach Ihnen mit dem PC arbeitet, die Daten zum Beispiel in Word einfügen und dort einsehen. Am einfachsten erfolgt die Löschung der Zwischenablage automatisch beim Schließen eines jeden Formulars:

Private Sub Form_Close()
Dim ZA As New ClpBrd
ZA.Clear
End Sub

Zwischenablage prüfen

Außerdem haben wir im Klassenmodul „ClpBrd“ noch die Methode „ClpBrdEmpty()“ implementiert, über die Sie prüfen können, ob sich ein Objekt in der Zwischenablage befindet und ob es sich dabei um den Datentyp „Text/String“ handelt. Auf diese Weise lässt sich beispielsweise in einer Ereignisprozedur einer Schaltfläche zunächst prüfen, ob einfügbarer Text vorhanden ist, und gegebenenfalls eine Meldung anzeigen:

Private Sub btnCheck_Click()
Dim ZA As New ClpBrd, strCBData As String
Beep
If ZA.ClpBrdEmpty() Then
MsgBox „Zwischenablage ist leer “ & „oder enthält keinen Text…“
Else
strCBData = ZA.GetData()
MsgBox „Zwischenablage enthält Text: “ + vbCrLf + vbCrLf + Left$(strCBData, 50) + „…“
End If
End Sub

Dieses einfache Beispiel prüft, ob die Zwischenablage einfügbaren Text enthält – wenn ja, werden davon die ersten 50 Zeichen als „Muster“ angezeigt, wenn nicht, geben wir eine entsprechende Meldung aus.

Damit Sie sich die Funktionsweise gleich einmal in der Praxis anschauen können, haben wir in der Beispieldatenbank ZWIABLG.MDB eine kleine Adressverwaltung vorbereitet, deren Formular „Adressen“ beim Start der Datenbank automatisch geöffnet wird. In diesem Formular finden Sie unter anderem zwei Schaltflächen „Adresse in ZA“ und „Import aus ZA“.

Über die Schaltfläche ADRESSE IN ZA wird die aktuell angezeigte Adresse als Text in die Zwischenablage übertragen und kann von dort aus zum Beispiel in Word als Basis für einen Brief eingefügt werden.

Über die Schaltfläche IMPORT AUS ZA können Sie per Mausklick einen in Word erstellten und dort in die Zwischenablage kopierten Brief in das Memofeld „Briefe“ einfügen bzw. an eventuell vorhandene Inhalte anhängen. So ist eine schnelle Übersicht der bislang abgewickelten Korrespondenz von hier aus möglich, ohne dass Word dazu extra gestartet werden muss.

Anpassung an individuelle Anforderungen

Wie bereits erwähnt, haben wir den Puffer für die Übertragung von Daten aus der Zwischenablage auf 32 KB begrenzt, um nicht über Gebühr Speicher zu belegen und um die Ausführungsgeschwindigkeit von „GetData()“ nicht unnötig zu verlängern. Bei Bedarf ändern Sie die Größe des Puffers wie folgt:

1. Wechseln Sie im Datenbankfenster in den Bereich „Module“ und öffnen Sie das Klassenmodul „ClpBrd“ mit einem Klick auf die Schaltfläche ENTWURF.

2. Im allgemeinen Teil finden Sie im Bereich „Deklarationen“ am Ende die Konstante „MaxSize“.

3. Ändern Sie sie auf den gewünschten Wert.

Fehlermeldungen unterdrücken

Wir haben in allen Methoden verschiedene Prüfungen eingebaut, die im Falle eines Falles Fehlermeldungen anzeigen. Um diese zu unterdrücken und nur die Funktionsergebnisse auszuwerten, kommentieren Sie die entsprechenden Zeilen wie am folgenden Beispiel gezeigt aus:

Function GetData()
strCBData = „“
If ClpBrdEmpty() Then
‚Beep
‚MsgBox „ClpBrd/Get:
Zwischenablage ist leer…“,_
vbCritical
Exit Function
End If
…..


Modul: modAdressen 


Modul: ClpBrd