Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.
Datenblattmarkierung füllen
In der Datenblattansicht lassen sich ja bereits eine Menge Dinge erledigen – Daten einfügen, löschen, bearbeiten, kopieren, ausschneiden ... Sie können sogar komplette Bereiche kopieren und in andere Bereiche einfügen, sofern diese Bereiche zueinander kompatibel sind, und Access ist hier recht tolerant. Was aber fehlt, ist die Markierung eines Zielbereichs, dessen Felder dann alle mit dem gleichen Wert gefüllt werden. Wenn Sie also etwa für alle Datensätze ein Ja/Nein-Feld anhaken möchten, müssen Sie dies immer noch manuell erledigen. Dieser Beitrag zeigt eine passende Lösung für Datenblätter in Formularen und Unterformularen.
Wenn Sie einen Bereich eines Formulars oder Unterformulars in der Datenblattansicht mit den gleichen Werten füllen wollten, waren Sie bislang auf zwei Möglichkeiten angewiesen:
- das Absetzen einer entsprechenden UPDATE-SQL-Aktionsabfrage, was aber den Nachteil hat, dass dies selbst die Fähigkeiten von Powerusern mitunter überschreitet, oder
- das manuelle Füllen der Felder mit dem gewünschten Wert.
Letzteres geschieht für eine bessere Effizienz am besten so, dass man eine gewisse Menge Felder mit dem Wert füllt (sagen wir zehn untereinander liegende Felder), dann diesen Bereich kopiert und in eine Markierung unter den gefüllten Feldern mit einer Spalte Breite und zehn Zeilen Höhe wieder einfügt. Wenn man viele Felder füllen muss, kann man nochmal größere Bereiche markieren und kopieren und dann in entsprechend größere Bereiche einfügen.
Der Nachteil: Man müsste immer ungefähr die gewünschte Menge Felder ermitteln, damit alle kopierten Werte dort hineinpassen. Der Vorteil: Access ist beim Einfügen nicht pingelig, die Größe von Quell- und Zielfeldern muss nicht unbedingt übereinstimmen. Das heißt, wenn Sie beispielsweise zehn Felder in einen Bereich von weniger als zehn Feldern einfügen, dann werden nur die markierten Felder gefüllt.
Wenn der Zielbereich größer ist als der Quellbereich, dann werden ebenfalls nur die entsprechend dem kopierten Bereich gefüllt.
Befriedigend ist das alles nicht: Fehler können so leicht auftreten, sei es durch das Auslassen eines zu füllenden Feldes oder durch Überschreiben von Bereichen, die gar nicht geändert werden sollen. Es wäre also am einfachsten, wenn man etwa die in Bild 1 markierten Felder mit einem Klick etwa aktivieren oder deaktivieren oder mit einem Wert füllen könnte.
Bild 1: Das wäre schön: Die markierten Felder alle mit einem Schlag beispielsweise aus- oder abwählenDie Lösung
Ein viel besserer Ansatz wäre etwa ein Kontextmenü-Eintrag, den man für eine Markierung in der Datenblattansicht auswählen kann und der dann eine InputBox öffnet, der man den einzufügenden Wert übergibt. Nach Betätigen der OK-Schaltfläche soll dieser Wert in alle markierten Zellen eingefügt werden. Dabei soll es keine Rolle spielen, wie groß die Markierung ist – es sollen also sowohl mehrere Spalten als auch mehrere Zeilen markierbar sein, auch in Kombination miteinander. Noch schöner wäre es, wenn ein in der Zwischenablage befindlicher Wert gleich als Standardwert in der InputBox angezeigt würde.
Dies gilt es nun zu realisieren – machen wir uns ans Werk!
Einsatz der fertigen Lösung
Die fertige Lösung wird in Form einer Klasse kommen, die alle notwendigen Funktionen liefert. Die Klasse heißt clsDatasheetInsert und sollte in dem Hauptformular, welches das in der Datenblattansicht erscheinende Unterformular enthält, mit der Objektvariablen objDatasheetInsert deklariert werden:
Dim objDatasheetInsert As clsDatasheetInsert
In die Prozedur, die durch das Ereignis Beim Laden des Hauptformulars ausgelöst wird, fügen wir die folgenden Anweisungen ein:
Private Sub Form_Load()
Set objDatasheetInsert = New clsDatasheetInsert
With objDatasheetInsert
Set .Form = Me!sfmArtikel.Form
End With
End Sub
Die erste Anweisung instanziert das neue Objekt und speichert einen Verweis darauf in der Variablen objDatasheetInsert. Die Anweisung innerhalb des With-Konstrukts weist der Eigenschaft Form des Objekts einen Verweis auf das Unterformular in der Datenblattansicht zu, das mit den Funktionen zum Füllen mehrerer Felder gleichzeitig versehen werden soll.
Danach können Sie dann wie in Bild 2 die Zielfelder markieren, mit der rechten Maustaste das Kontextmenü aufrufen und dann den Eintrag Wert einfügen auswählen, um die gewünschten Daten in die markierten Felder einzufügen.
Bild 2: Einfügen von Werten per KontextmenüKontextmenü-Eintrag hinzufügen
Für diese Funktion benötigen wir zunächst einmal einen Kontextmenü-Eintrag – und zwar nicht in irgendeinem Kontextmenü, sondern genau in dem, das beim Rechtsklick auf eines der Felder oder auf mehrere markierte Felder erscheint.
Für einen groben Überblick, um welches Kontextmenü es sich handeln könnte, schauen wir uns die Liste aller Commandbar-Objekte an, die den Typ msoBarTypePopup aufweisen. Das erledigt die folgende Prozedur, welche die Namen der Kontextmenüs im Direktbereich ausgibt (für diese und weitere Prozeduren benötigen Sie einen Verweis auf die Bibliothek Microsoft Office x.0 Object Library – s. Bild 3):
Bild 3: Verweis auf die Office-BibliothekPublic Sub CommandbarsAusgeben()
Dim cbr As Office.CommandBar
For Each cbr In CommandBars
If cbr.Type = msoBarTypePopup Then
Debug.Print cbr.Name
End If
Next cbr
End Sub
Hier erscheinen gleich zu Beginn die folgenden beiden Einträge:
- Form Datasheet
- Form Datasheet Cell
Nun müssen wir nur noch herausfinden, welches der beiden Kontextmenüs beim Anklicken eines Feldes im Datenblatt erscheint. Dazu legen wir einfach in allen betroffenen Kontextmenüs einen neuen Eintrag an, der den Namen des Kontextmenüs trägt:
Public Sub CommandbarsTesten()
Dim cbr As Office.CommandBar
Dim cbb As Office.CommandBarButton
Set cbr = CommandBars.Item("Form Datasheet Cell")
Set cbb = cbr.Controls.Add(msoControlButton, , , , True)
cbb.Caption = "Form Datasheet Cell"
Set cbr = CommandBars.Item("Form Datasheet")
Set cbb = cbr.Controls.Add(msoControlButton, , , , True)
cbb.Caption = "Form Datasheet"
End Sub
Die Set cbr ...-Anweisung referenziert jeweils eines der betroffenen Kontextmenüs, die Set cbb ...-Anweisung fügt ein neues Steuerelement des Typs msoControlButton hinzu. Über die Caption-Eigenschaft legt die Prozedur die Beschriftung des jeweiligen Eintrags fest.
Danach klicken wir einfach mit der rechten Maustaste auf das gewünschte Element im Datenblatt und erhalten ganz unten die Antwort auf unsere Frage: Das Kontextmenü Form Datasheet Cell ist unser gesuchtes Objekt (s. Bild 4).
Bild 4: Ermitteln des Kontextmenüs für das DatenblattWerte einfügen per Klasse
Weiter oben haben wir ja bereits erläutert, dass wir die Funktionalität zum Einfügen von Daten in mehrere Felder gleichzeitig in einer Klasse kapseln möchten. Das hat den Vorteil, dass Sie den Code ganz einfach in mehreren Formularen wiederverwenden können.
Diese Klasse heißt clsDatasheetFill und enthält eine Property Set-Prozedur, die einen Verweis auf das zu unterstützende Formular erwartet. Diesen Verweis speichert die Klasse in der wie folgt im Klassenmodul deklarierten Variablen:
Dim m_Form As Form
Die Prozedur selbst finden Sie in Listing 1. Sie trägt zuerst den Verweis auf das per Parameter übergebene Formular-Objekt in die Variable m_Form ein. Dann sorgt sie noch für die Erweiterung des Kontextmenüs um einen Eintrag mit dem Text Wert einfügen. Dazu füllt sie die Variable cbr mit einem Verweis auf das Element Form Datasheet Cell der CommandBars-Auflistung.
Public Property Set Form(frm As Form)
Dim cbr As Office.CommandBar
Dim i As Integer
Set m_Form = frm
Set cbr = CommandBars.Item("Form Datasheet Cell")
For i = cbr.Controls.Count To 1 Step -1
If cbr.Controls.Item(i).Caption = "Wert einfügen" Then
cbr.Controls.Item(i).Delete
End If
Next i
Set cbbInsert = cbr.Controls.Add(msoControlButton, , , , True)
cbbInsert.Caption = "Wert einfügen"
End Property
Listing 1: Einrichten des Kontextmenüs
Anschließend durchläuft sie alle Einträge dieses Kontextmenüs und prüft diese auf die Beschriftung Wert einfügen. Sind bereits Einträge mit dieser Beschriftung vorhanden, entfernt die Prozedur diese mit der Delete-Methode des jeweiligen Elements. Danach legt sie diesen Eintrag neu an und speichert einen Verweis darauf in der Variablen cbbInsert. Die folgende Anweisung stellt nur noch die Beschriftung auf Wert einfügen ein.
Die Variable cbbInsert wurde noch nicht deklariert. Da wir für den neu hinzugefügten Eintrag zum Kontextmenü auch eine Ereignisprozedur hinterlegen möchten, die beim Anklicken des Eintrags ausgelöst wird, benötigen wir noch eine entsprechende, mit dem Schlüsselwort WithEvents ausgestattete Variable.
Auch diese landet wieder im Kopf des Klassenmoduls:
Dim WithEvents cbbInsert As CommandBarButton
Wie legen Sie nun die benötigte Ereignisprozedur an? Dazu wählen Sie einfach im Klassenmodul im linken Kombinationsfeld den Eintrag cbbInsert aus, der dort nur deshalb erscheint, weil Sie die Objektvariable mit WithEvents deklariert haben. Nun erscheint im rechten Kombinationsfeld das Standardereignis Click (im Übrigen auch das einzige Ereignis dieses Objekts) und der VBA-Editor legt die passende Ereignisprozedur an (s. Bild 5).
Bild 5: Anlegen einer Ereignisprozedur, die beim Anklicken eines Kontextmenü-Eintrags ausgelöst wird
Diese Prozedur ergänzen Sie nun wie in Listing 2. Die Prozedur fragt per Inputbox den einzufügenden Inhalt ab. Dabei verwendet sie als Standardwert einen Wert, den die Funktion AusZwischenablage liefert.
Private Sub cbbInsert_Click(ByVal Ctrl As Office.CommandBarButton, CancelDefault As Boolean)
Dim strInhalt As String
Dim bolFill As Boolean
strInhalt = InputBox("Geben Sie den einzufügenden Wert an:", "Zellen füllen", AusZwischenablage)
If Len(strInhalt) > 0 Then
bolFill = True
Else
If MsgBox("Felder leeren?", vbYesNo) = vbYes Then
bolFill = True
End If
End If
If bolFill Then
Fill strInhalt
End If
End Sub
Listing 2: Die Ereignisprozedur, die beim Auswählen des Kontextmenü-Eintrags ausgelöst wird
Diese finden Sie im Modul mdlTools. Die Funktion gibt den aktuellen Inhalt der Zwischenablage zurück. Auf diese Weise könnte der Benutzer wie gewohnt den einzufügenden Text per Strg + C oder mit dem Kontextmenü-Befehl Kopieren ermitteln.
Enthält die Variable strInhalt nach dem Eintragen des Ergebnisses der InputBox-Funktion keine leere Zeichenfolge, stellt die Prozedur die Variable bolFill auf den Wert True ein. Falls nicht, soll die Prozedur prüfen, ob der Benutzer vielleicht einfach nur die Abbrechen-Schaltfläche betätigt hat (was ebenfalls eine leere Zeichenkette zurückliefert) oder ob er tatsächlich eine leere Zeichenkette eingegeben hat, um die markierten Felder der Datenblattansicht zu leeren beziehungsweise mit einer leeren Zeichenkette zu füllen. Wählt der Benutzer hier die Antwort Ja (vbYes), wird bolFill ebenfalls auf True eingestellt. Hat bolFill im Anschluss den Wert True, ruft die Prozedur die Routine Fill mit dem einzusetzenden Wert aus der Variablen strInhalt als Parameter auf.
Füllen der markierten Felder
Nun folgt der interessante Teil der Lösung. Hier benötigen wir zunächst einen Ansatz, um die markierten Felder zu füllen.
Um die entsprechenden Inhalte zu ändern, gibt es zwei Wege:
- Bearbeiten der Datenherkunft des Formulars in der Datenblattansicht und Aktualisieren des Datenblatts mit den geänderten Daten oder
- Durchlaufen der markierten Felder und direktes Eintragen der Werte per VBA.
Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.