Selektieren in langen Texten

Wenn Sie einen Text in einem Textfeld selektieren wollen, erledigen Sie das in der Regel per Maus oder Tastatur. Das geht jedoch auch per Code – in der Regel durch das Setzen der Eigenschaften SelStart und SelLength. Damit lässt sich auch die Position der Markierung auslesen, wenn diese von Hand gesetzt wurde. Die genannten Eigenschaften haben jedoch einen Haken: Sie können damit nur in Texten mit bis zu 32.767 Zeichen arbeiten, da die Eigenschaften als Integer definiert sind. Abhilfe schafft die Windows API – alle notwendigen Informationen dazu finden Sie in diesem Beitrag.

Anlass für die Untersuchung dieses Problems ist die Lösung aus dem Beitrag Volltextsuche mit Fundstellen (www.access-im-unternehmen.de/1119), wo wir einen Suchbegriff an der entsprechenden Stelle im Text durch eine Markierung hervorheben wollen.

Die dort verwendeten Texte sind jedoch mitunter länger als 32.767 Zeichen, enthalten also mehr Zeichen, als durch den Datentyp Integer erfasst werden können.

Zum Setzen der Markierung wollten wir aber gern die beiden Eigenschaften SelStart und SelLength verwenden. Wenn wir in einem Textfeld mit einem langen Text eine Markierung setzen wollen, die hinter dem 32.767ten Zeichen liegt, lösen wir damit einen überlauf-Fehler aus.

Als Spielwiese für die nachfolgend entwickelte Lösung erstellen wir eine Tabelle namens tblTexte mit dem Primärschlüsselfeld TextID und dem Feld Inhalt mit dem Datentyp Langer Text beziehungsweise Memo (s. Bild 1).

Tabelle zum Speichern langer Texte

Bild 1: Tabelle zum Speichern langer Texte

Das Formular, mit dem wir das Selektieren ausprobieren wollen, sieht im Entwurf wie in Bild 2 aus. Es ist an die Tabelle tblTexte gebunden. Damit wir möglichst viel Text sehen, haben wir die Eigenschaften Horizontaler Anker und Vertikaler Anker für das Textfeld, das an das Feld Inhalt gebunden ist, auf Beide eingestellt. Das Textfeld haben wir außerdem txtInhalte benannt.

Entwurf des Testformulars

Bild 2: Entwurf des Testformulars

Oben finden Sie noch zwei Textfelder, in die wir die gewünschten Werte für SelStart und SelLength eintragen können und eine Schaltfläche namens cmdGo, welche die Markierung anwenden soll. Die Schaltfläche cmdGo soll die folgende Ereignisprozedur auslösen:

Private Sub cmdGo_Click()
     With Me!txtInhalt
         .SetFocus
         .SelStart = Me!txtSelStart
         .SelLength = Me!txtSelLength
     End With
End Sub

Wenn wir nun etwa die Werte 10 für SelStart und 20 für SelLength eingeben, erhalten wir im Textfeld eine Markierung wie in Bild 3.

Setzen einer Markierung am Anfang des Textes

Bild 3: Setzen einer Markierung am Anfang des Textes

Nun geben wir einmal einen Wert größer als 32.767 für die Eigenschaft SelStart ein und klicken auf die Schaltfläche cmdGo. Dies löst nun den Fehler aus Bild 4 aus. Die Ursache für das Problem können wir uns gleich im Direktbereich nochmal bestätigen lassen.

Fehler beim Einsatz von Werten größer als 32.767

Bild 4: Fehler beim Einsatz von Werten größer als 32.767

Dort geben wir eine Debug.Print-Anweisung ein, die mit der Funktion TypeName den Datentyp der SelStart-Eigenschaft liefert:

Debug.Print TypeName( Me!txtInhalt.SelStart)
     Integer

Alternative: API-Funktionen

An dieser Stelle können wir also wohl nicht ändern und müssen uns eine Alternative überlegen.

Diese finden wir in den API-Funktionen von Windows.

Damit lassen sich die meisten Dinge bezüglich Benutzeroberfläche und Steuer-elemente erledigen, die Sie auch über den Befehlssatz von Access/VBA einstellen können – allerdings sieht das auf diesem Wege immer ein wenig komplizierter aus.

Für unsere Anforderung nutzen wir den Code aus Listing 1. Hier definieren wir zunächst zwei API-Funktionen, um diese innerhalb des VBA-Codes zu nutzen. Die erste API-Funktion heißt SendMessage und wird für das Senden aller möglichen Nachrichten verwendet.

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
     ByVal wParam As Long, lParam As Any) As Long
Private Declare Function GetFocus Lib "user32" () As Long
Private Const EM_SETSEL  As Long = &HB1
Private Sub cmdGo_Click()
     Dim lngHandle As Long
     Dim lngSelStart As Long
     Dim lngSelLength As Long
     With Me!txtInhalt
         .SetFocus
         lngHandle = GetFocus
         lngSelStart = Me!txtSelStart
         lngSelLength = Me!txtSelLength
       SendMessage lngHandle, EM_SETSEL, lngSelStart, ByVal lngSelStart + lngSelLength
     End With
End Sub

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder bist Du bereits Abonnent? Dann logge Dich gleich hier ein. Die Zugangsdaten findest Du entweder in der aktuellen Print-Ausgabe auf Seite U2 oder beim Online-Abo in der E-Mail, die Du als Abonnent regelmäßig erhältst:

Schreibe einen Kommentar