ListView-Steuerelemente unterstützen im Gegensatz zum Listenfeld sogar den Einsatz von Drag and Drop. Damit können Sie nicht nur Einträge von einem ListView-Steuerelement zum nächsten ziehen, sondern auch die Reihenfolge der Einträge eines ListView-Steuerelements einstellen. Im zweiten Teil dieser Mini-Artikelreihe zeigen wir, wie Sie per Drag and Drop die Reihenfolge von ListView-Einträgen anpassen.
Beispieldatenbank
Die Beispiele dieses Artikels finden Sie in der Datenbank 1302_ListView.mdb.
ändern der Reihenfolge per Drag and Drop
In der Datenblattansicht, der Endlosansicht oder in Listenfeldern lässt sich mit viel Trickserei ein Drag-and-Drop-Vorgang nachbauen. Das ist allerdings mit viel Aufwand verbunden. Viel einfacher wird es mit dem ListView-Steuerelement. Dieses liefert von Haus aus grundlegende Drag-and-Drop-Funktionen mit, die Sie nur noch ausprogrammieren müssen.
Und damit lassen sich natürlich nicht nur Einträge von einem ListView-Steuerelement zum nächsten bewegen, wie im ersten Teil dieser Artikelserie beschrieben, sondern Sie können damit auch die Reihenfolge der Elemente eines einzelnen ListView-Steuerelements einstellen.
Beispieldaten
Das ListView-Steuerelement soll das Sortieren der Datensätze der Tabelle tblKunden nach dem Wert eines neuen Feldes namens ReihenfolgeID ermöglichen. Dieses Feld fügen wir der entsprechenden Tabelle der Beispieldatenbank hinzu; es erhält den Datentyp Zahl (siehe Bild 1).
Bild 1: Vorbereitung der Tabelle tblKunden
Dieses Feld müssen wir noch initial füllen, was wir gleich beim öffnen des Formulars erledigen. Damit ist auch sichergestellt, dass zwischenzeitlich hinzugefügte Felder oder entfernte Felder berücksichtigt werden.
Beispielformular
Das Beispielformular heißt frmListView-Drag-Drop-Rei-hen-folge. Fügen Sie diesem zunächst ein einfaches ListView-Steuerelement hinzu (Steuer-ele-mente|ActiveX-Steuerelemente, dort Microsoft List-View Control 6.0 (SP6) auswählen). Benennen Sie dieses Steuerelement mit lvwKunden.
Nun sorgen Sie dafür, dass das ListView-Steuerelement beim Laden des Formulars mit den gewünschten Daten gefüllt wird – allerdings nicht, ohne den Wert des Feldes ReihenfolgeID zuvor anzupassen.
Doch zunächst zu der Prozedur, die beim Laden des Formulars ausgelöst wird. Diese legen Sie durch Auswählen des Eintrags [Ereignisprozedur] für die Eigenschaft Beim Laden des Formulars und anschließendes Anklicken der Schaltfläche mit den drei Punkten (…) an.
Die nun erscheinende Prozedur, die gleichzeitig mit dem Klassenmodul Form_frmListViewDragDropReihenfolge angelegt wird, füllen Sie wie in Listing 1 abgebildet. Damit die dort verwendete Variable objLvwKunden, mit der die Prozedur auf das ListView-Steuerelement verweist, bekannt ist, deklarieren Sie diese in einer eigenen Zeile im Kopf des Moduls – also gleich unter den beiden Option …-Zeilen:
Private Sub Form_Load() Call ReihenfolgeAktualisieren Set objLvwKunden = Me!lvwKunden.Object With objLvwKunden .View = lvwReport .Appearance = ccFlat .BorderStyle = ccNone .FlatScrollBar = False .ColumnHeaders.Clear .ColumnHeaders.Add , , "Kunde", Me!lvwKunden.Width .OLEDragMode = ccOLEDragAutomatic .OLEDropMode = ccOLEDropManual End With KundenFuellen End Sub
Listing 1: Einrichten und Füllen des ListView-Steuerelements
Dim WithEvents objLvwKunden As MSComctlLib.ListView
Das Schlüsselwort WithEvents verwenden wir, damit wir im Klassenmodul des Formulars ganz einfach Ereignisprozeduren anlegen können, die durch das ListView-Steuerelement ausgelöst werden. Dies ist für die Programmierung der Drag-and-Drop-Funktionalität wichtig.
Die Prozedur ruft zunächst die Prozedur ReihenfolgeAktualisieren auf, die sich um das Füllen des Feldes ReihenfolgeID kümmert – mehr dazu weiter unten.
Danach füllt sie die Variable objLvwKunden mit einem Verweis auf das entsprechende Steuerelement. Anschließend stellt es einige Eigenschaften dieses Steuerelements ein. Dies könnten Sie auch über den Eigenschaften-Dialog des Steuerelements durchführen, aber wir erledigen das per Code.
Neben einigen optischen Einstellungen sorgt die Methode Add der ColumnHeaders-Auflistung für das Anlegen einer einzigen Spalte, welche später die Werte des Feldes Firma der Kundendatensätze aufnehmen soll. Da dies die einzige Spalte ist, stellt die Prozedur die Spaltenbreite auf die Breite des Steuerelements ein. Schließlich folgen zwei Einstellungen, die für die Programmierbarkeit von Drag and Drop wichtig sind: OLEDragMode und OLEDropMode.
Den Abschluss macht ein Aufruf der Prozedur KundenFuellen, die schließlich die Kundennamen in das ListView-Steuerelement füllt.
Reihenfolge aktualisieren
Die Prozedur ReihenfolgeAktualisieren aus Listing 2 verwendet die Abfrage qryKundenNachReihenfolgeID als Basis eines Recordsets. Die Prozedur durchläuft alle Datensätze dieser Abfrage in einer Do While-Schleife und bearbeitet dabei den jeweils aktuelle Datensatz, indem sie den Wert des Feldes ReihenfolgeID auf einen Wert einstellt, welcher der Eigenschaft AbsolutePosition des aktuellen Recordsets plus eins entspricht. Der Wert 1 wird deshalb addiert, weil AbsolutePosition für den ersten Datensatz den Wert 0 liefert, die Werte des Feldes ReihenfolgeID jedoch mit 1 beginnen sollen.
Public Sub ReihenfolgeAktualisieren() Dim db As DAO.Database Dim rst As DAO.Recordset Set db = CurrentDb Set rst = db.OpenRecordset("SELECT * FROM qryKundenNachReihenfolgeID", dbOpenDynaset) Do While Not rst.EOF rst.Edit rst!ReihenfolgeID = rst.AbsolutePosition + 1 rst.Update rst.MoveNext Loop Set db = Nothing End Sub
Listing 2: Einstellen der ReihenfolgeID der enthaltenen Datensätze
Zum Einstellen dieses Wertes versetzt die Prozedur den Datensatz mit der Edit-Methode in den Bearbeitungsmodus, ändert den Wert des Feldes ReihenfolgeID und speichert die änderung mit der Update-Methode. Die MoveNext-Methode verschiebt den Datensatzzeiger auf den nächsten Datensatz. Dieser Vorgang wird solange wiederholt, bis die Eigenschaft EOF des Recordset-Objekts den Wert True annimmt – der Datensatzzeiger befindet sich somit hinter dem letzten Datensatz.
Interessant ist die Abfrage qryKundenNachReihenfolgeID, welche festlegt, in welcher Reihenfolge die Kundendatensätze tatsächlich nummeriert werden. Die Abfrage finden Sie in Bild 2. Sie basiert auf der Tabelle tblKunden und enthält drei Felder, von denen nur das Feld ReihenfolgeID angezeigt wird. Das zweite und das dritte Feld dienen der korrekten Sortierung vor dem Aktualisieren der Reihenfolge.
Bild 2: Abfrage zum Einstellen der ReihenfolgeID der Kundendatensätze
Wichtig ist, dass diese Abfrage die Reihenfolge der vorhandenen Kundendatensätze nicht durcheinander bringt und dass neue Datensätze hinten eingereiht werden.
Daher sortiert die Abfrage die Datensätze zunächst nach dem Feld ReihenfolgeID und erst danach nach dem Feld KundeID. Würde man dies so belassen, würde die Abfrage jedoch zuerst die neu hinzugefügten Datensätze liefern. Diese weisen nämlich den Wert Null im Feld ReihenfolgeID auf und sind in der Reihenfolge vor den mit Zahlenwerten gefüllten Feldern zu finden.
Also müssen wir dafür sorgen, dass der Wert Null durch einen Wert ersetzt wird, der größer als die bisher vergebenen Werte im Feld ReihenfolgeID ist. Da die Sortierung per Drag and Drop ohnehin nur für eine überschaubare Anzahl Datensätze sinnvoll ist, gehen wir davon aus, dass der Wert 999.999 ausreichend ist. Der folgende Ausdruck prüft, ob ReihenfolgeID leer ist (also den Wert Null enthält) und fügt in diesem Fall den Wert 999.999 ein:
Reihenfolge: ZLong(Nz([ReihenfolgeID];999999))
Das Ergebnis der Nz-Funktion wird in der Abfrage aber dummerweise als String interpretiert. Sie können sich dies in der Abfrage qryKundenNachReihenfolgeIDFalsch ansehen, die das Ergebnis aus Bild 3 liefert.
Bild 3: Fehlerhafte Interpretation der Ergebnisse von Nz
Zumindest erfolgt dort die Sortierung so, als ob es sich bei dem Feld um ein Textfeld handelt – 10 landet so beispielsweise vor 2.
Dies lässt sich allerdings beheben, indem wir das Ergebnis der Nz-Funktion noch mit der CLng-Funktion in einen Long-Wert konvertieren.
Eintragen der ListView-Werte
Zuletzt ruft die Prozedur Form_Load die Routine KundenFuellen auf (siehe Listing 3). Diese erzeugt ein Recordset auf Basis der Tabelle tblKunden, wobei die Reihenfolge durch das soeben frisch gefüllte Feld ReihenfolgeID festgelegt wird.
Private Sub KundenFuellen() Dim db As DAO.Database Dim rst As DAO.Recordset Set db = CurrentDb Set rst = db.OpenRecordset("SELECT * FROM tblKunden ORDER BY ReihenfolgeID", dbOpenDynaset) objLvwKunden.ListItems.Clear Do While Not rst.EOF objLvwKunden.ListItems.Add , "a" & rst!KundeID, rst!Firma rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing End Sub
Listing 3: Einlesen der Datensätze und Einfügen in das ListView-Steuerelement
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: