Summe=Anzahl+MWst
Flexible Popup-Menüs für Formulare
Access bietet zwar die Möglichkeit, benutzerdefinierte Popup-Menüs einzusetzen, das setzt aber voraus, dass zunächst über die Funktion ANSICHT-SYMBOLLEISTEN- ANPASSEN ein entsprechendes Kontextmenü definiert und einem Formular über dessen Eigenschaften „Kontextmenü = Ja“ und „Kontextmenüleiste = Name“ zugeordnet wird. In vielen Fällen ist das aber zu umständlich und zu wenig flexibel, da zum Beispiel die Deaktivierung eines Eintrages abhängig vom Kontext recht aufwändig zu programmieren ist. Ein häufiger Wunsch vieler Entwickler ist deshalb eine einfachere Methode für die Anzeige und Auswertung eines Kontextoder Popup-Menüs. Diesem Wunsch kann durch den Einsatz entsprechender API-Funktionen entsprochen werden:
Declare Function CreatePopupMenu Lib „user32“ () As Long
Declare Function AppendMenu Lib „user32“ Alias „AppendMenuA“ (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As String) As Long
Declare Function DestroyMenu Lib „user32“ (ByVal hMenu As Long) As Long
Declare Function TrackPopUpMenu Lib „user32“ Alias „TrackPopupMenu“ (ByVal hMenu As Long, ByVal wFlags As Long, ByVal X As Long, ByVal Y As Long, ByVal nReserved As Long, ByVal hWnd As Long, lprc As tRect) As Long
Declare Function GetMessage Lib „user32“ Alias „GetMessageA“ (lpMsg As tMsg, ByVal hWnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long) As Long
Declare Function GetCursorPos Lib „user32“ (lpPoint As tPoint) As Long
‚ Ein Abschnitt ist immer eine Zeile
Ähnlich wie beim Zugriff auf die Zwischenablage sind für die Anzeige eines Popup-Menüs mehrere Aufrufe notwendig: „CreatePopupMenu()“ legt zunächst die leere Basisstruktur eines Popup-Menüs an und liefert als Ergebnis einen Handle auf diese Struktur.
Über diesen Handle können nun die Funktionen „AppendMenu()“ und „TrackPopupMenu()“ die anzuzeigenden Einträge aufbauen, anzeigen und den ausgewählten Eintrag als Ergebnis liefern. „Destroy- Menu()“ gibt anschließend die Datenstruktur des Popup-Menüs wieder frei.
Statt dieser Einzelaufrufe können Sie die von uns vorbereitete Funktion „DoPopup()“ aus dem Modul „modPopup“ der Beispieldatenbank POPUP.MDB einsetzen. Die Funktion erwartet als Parameter eine Zeichenkette, in der die zur Auswahl stehenden Einträge definiert sind. Als Ergebnis liefert die Funktion die Nummer des gewählten Eintrages.
Ein Aufruf der Funktion könnte zum Beispiel wie folgt aussehen:
Die einzelnen anzuzeigenden Einträge werden zunächst durch das Pipe- Zeichen getrennt. Über weitere Sonderzeichen können Sie spezielle Einträge in das Popup-Menü aufnehmen lassen oder Anzeigezustände steuern:
Result = DoPopup(„1. Eintrag|2. Eintrag|=|3.Eintrag|=|+4. Eintrag|~5. Eintrag|>6. Eintrag|7. Eintrag“)
Beispiel:
Private Sub Detailbereich_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim Result As Long, strMsg
If Button = RIGHT_BUTTON Then
Result = DoPopup(„1. Eintrag|2. Eintrag|=|3.Eintrag|=|+4. Eintrag|~5. Eintrag|>6. Eintrag|7. Eintrag“)
Select Case Result
Case 0
strMsg = „keinen Eintrag ausgewählt…“
Case Else
strMsg = „Eintrag “ + CStr(Result) + “ ausgewählt…“
End Select
MsgBox „Sie haben “ + strMsg, vbOKOnly + vbInformation, „DoPopup():“
End If
End Sub
Sonder-zeichen: |
Bedeutung: |
= |
Ein einzelnes Gleichheitszeichen fügt hinter dem vorhergegangenen |
+ |
Ist das erste Zeichen eines Eintrages ein Plus-Zeichen, wird |
~ |
Wenn das erste Zeichen eines Eintrages eine Tilde ist, wird |
> |
Über das Größer-Zeichen als erstes Zeichen eines Eintrages |
So binden Sie den Aufruf von „DoPopup()“ ein
Der Aufruf von „DoPopup()“ erfolgt über die Eigenschaft „Bei Maustaste Ab“ (MouseDown) eines Objektes wie des Detailbereichs oder eines Textfeldes. Die folgende Prozedur reagiert beispielsweise auf einen Rechtsklick in ein Textfeld und fügt die aus dem Popup-Menü ausgewählte Versandart in das Textfeld ein:
Private Sub txtVersandart_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim Result As Long, strResult As String
If Button = RIGHT_BUTTON Then
Result = DoPopup(„UPS|DPD|Post/Normal|Post/Express|=|Abholung“)
Select Case Result
Case 1: Me.txtVersandart = „UPS“
Case 2: Me.txtVersandart = „DPD“
Case 3: Me.txtVersandart = „Post/Normal“
Case 4: Me.txtVersandart = „Post/Express“
Case 5: Me.txtVersandart = „Abholung“
End Select
End If
End Sub
ACHTUNG! Wichtig in den Prozeduren, über die „DoPopup()“ aufgerufen werden soll, ist die Abfrage
If Button = RIGHT_BUTTON Then…
Andernfalls würde das Popup-Menü auch dann angezeigt werden, wenn Sie mit der linken Maustaste beispielsweise in ein Textfeld klicken, um den Cursor für eine Änderung zu positionieren.
Mithilfe der Funktion „DoPopup()“ können Sie zum
Beispiel „Ausfüllhilfen“ in Formularen zur Verfügung stellen
Speichern Sie das Modul „modPopup“ ab.
Filterkriterien aus dem Formular an einem Bericht übergeben
Sicherlich kennen Sie die Situation: In einem Formular haben Sie einige Datensätze gefiltert und möchten nun auf dieser Basis Adressetiketten drucken.
Ein entsprechender Bericht für den Druck der Etiketten liegt zwar vor, wie aber wird nun erreicht, dass der Bericht exakt die gleichen Datensätze druckt, die momentan im Formular angezeigt werden?
Die Lösung ist einfacher, als es zunächst scheint: Wenn Sie mit der formularbasierten Suche arbeiten oder eine andere Filterfunktion benutzen, stellt Access die Eigenschaft „Filter“ des Formulars auf die Filterkriterien ein und aktiviert die Filterung über die Eigenschaft „Filter On“.
Erfreulicherweise kann beim Öffnen eines Berichtes über „DoCmd.OpenReport“ ein Filterkriterium angegeben werden, dessen Syntax der Eigenschaft „Filter“ entspricht.
Es ist also nur notwendig, bei „DoCmd.OpenReport“ den Inhalt der Eigenschaft „Filter“ des Formulars anzugeben.
Eine kleine Stolperfalle ist allerdings zu beachten: Wenn der Filter deaktiviert wird, löscht Access nicht etwa die Kriterien in der Eigenschaft „Filter“, sondern schaltet lediglich die Filterung über „FilterOn = False“ aus.
Sie müssen also dafür sorgen, dass der Bericht bei deaktiviertem Filter ohne zusätzlichen Parameter bzw. ohne Filterkriterien aufgerufen wird:
Private Sub btnPrintSelected_Click()
strReport = „Kundenetiketten“
If Me.FilterOn Then
DoCmd.OpenReport strReport, acViewPreview, , Me.Filter
Else
DoCmd.OpenReport strReport, acViewPreview
End If
End Sub
In diesem Beispiel wird der Bericht „Kundenetiketten“ über eine Schaltfläche ETIKETTEN DRUCKEN aus einem Formular „Kunden“ heraus geöffnet.
Über die Eigenschaft „FilterOn“ prüfen wir zu nächst, ob ein Filter aktiviert ist.
Wenn ja, übergeben wir als Parameter den Inhalt der Eigenschaft „Filter“ des Formulars.
Etwas komplizierter wird es, wenn Sie eine im Formular per Filter definierte Sortierung ebenfalls an den Bericht übergeben möchten. Das ist nicht per Parameter möglich.
Sie können den Bericht aber „on the fly“ wie folgt modifizieren:
strReport = „Kundenetiketten/Auswahl“
DoCmd.OpenReport strReport, acViewDesign
Set R = Reports(strReport)
R.Filter = Me.Filter
R.FilterOn = Me.FilterOn
R.OrderBy = Me.OrderBy
R.OrderByOn = Me.OrderByOn
DoCmd.Save acReport, strReport
DoCmd.OpenReport strReport, acViewPreview
Hier wird der Bericht zunächst im Entwurfsmodus geöffnet. Anschließend setzen wir eine Referenz auf den Bericht in einer Objektvariable und können so direkt auf alle Eigenschaften zugreifen. Das nutzen wir, um die Einstellungen bezüglich Filter und Sortierung aus dem Formular in den Bericht zu übertragen. Danach wird der Bericht gespeichert und angezeigt.
Bitte beachten Sie, dass je doch eine im Bericht eingestellte Sortierung Vorrang hat!
Die Speicherung er folgt zur Vermeidung der Abfrage „Änderungen speichern?“ beim Schließen des Berichtes.
Es empfiehlt sich deshalb, hier mit einer anders benannten Kopie des ursprünglichen Berichtes zu arbeiten, da dieser sonst immer nur die Datensätze der letzten Filterung ausgeben würde.
Filter komfortabel definieren
Nehmen wir an, Sie möchten in einer Artikelverwaltung möglichst schnell alle Artikel anzeigen, die Sie von einem bestimmten Lieferanten beziehen, wissen aber nur noch, dass der Name des Lieferanten ein bestimmtes Wort wie beispielsweise „Liquids“ beinhaltet. Normalerweise müssten Sie dazu über das Menü DATENSÄTZE-FILTER-FORMULARBASIERTERFILTER das Feld „Lieferant“ mit der Zeichenfolge „*liquids*“ füllen und den Filter einschalten.
Wesentlich einfacher geht die Suche übereine Schaltfläche, einen kleinen Eingabedialog und mithilfe der wenig bekannten Access-Funktion „BuildCriteria“. Diese Funktion setzt anhand einer Suchmaske wie „*liquids*“ eine Zeichenkette zusammen, die direkt der Eigenschaft „Filter“ zugewiesen werden kann. Statt also aufwändig über das Menü und das Formular zu filtern, klicken Sie aufeine Schaltfläche, geben den Suchbegriff ein und drücken die Return-Taste. Und so können Sie diese Funktion in Ihren Formularen nutzen:
1. Öffnen Sie das Formular, für das Sie eine schnelle Filterung einsetzen möchten, im Entwurfsmodus.
2. Legen Sie im Formularfuß oder an anderer passender Stelle eine Schaltfläche mit der Bezeichnung LIEFERANTSUCHEN und dem Namen „btn-Suchen“ an.
3. Stellen Sie die Eigenschaft „BeimKlicken“ der Schaltfläche auf den Eintrag „[Ereignisprozedur]“.
4. Klicken Sie auf die Schaltfläche mit den drei Punkten, um den VBA-Editor zu öffnen.
5. Geben Sie die folgenden Anweisungen ein:
Private Sub btnSuch_Click()
Dim strEingabe As String
Dim strFilter As String
strEingabe = InputBox$
(„Suchbegriff eingeben:“,
„Suchen:“, „“)
If strEingabe = „“ Then
Me.Filter = „“
Me.FilterOn = False
Exit Sub
End If
strFilter = BuildCriteria
(„Lieferant“, dbText,
strEingabe)
Me.Filter = strFilter
Me.FilterOn = True
End Sub
„Lieferant“ ersetzen Sie dabei durch den Namen des Feldes, das durchsucht werden soll. Handelt es sich um ein numerisches Feld, eine Fließkommazahl, eine Währung, ein Memo oder ein Datum, ersetzen Sie den zweiten Parameter durch die Konstante „dbLong“, „dbDouble“, „dbCurrency“,„dbMemo“ oder „dbDate“.
Diese Anweisungen nehmen den Suchbegriff über „InputBox$()“ entgegen, lassen dann über „BuildCriteria()“ den Ausdruck für den Filter zusammensetzen und weisen ihn abschließend zu.
6. Lassen Sie das Formular über das Menü ANSICHT-FORMULARANSICHT anzeigen und testen Sie die Funktion. Um einen auf diese Art gesetzten Filter wieder aufzuheben, klicken Sie einfach auf das Symbol FILTER ENTFERNEN. Das Formular zeigt dann wieder alle Datensätze an.
Filter entfernen
DoCmd.ShowAllRecords
Fensterpositionen speichern und wiederherstellen
Formulare öffnet Access entweder immer zentriert oder an der im Entwurfsmodus zuletzt gewählten Position. Häufig möchten Sie die Formulare aber genauso positionieren, wie sie beim Verlassen der Datenbank angeordnet waren. Gleiches gilt für die Größe: Auch hier wäre es extrem arbeitssparend, wenn einmal eingestellte Fenstergrößen wiederhergestellt werden könnten. Wir möchten Ihnen eine Lösung vorstellen, mit der Sie eine solche Funktion universell in beliebige Datenbanken einbinden und nach geringen Anpassungen in allen Ihren Formularen verwenden können.
Am schnellsten und einfachsten könnten Sie eine solche Lösung realisieren, wenn Access-Formulare zur Positionierung die Eigenschaften „Top“ und „Left“ zur Verfügung stellen würden, aber leider gibt es sie nicht. Das Entwicklerteam von Access ist hier etwas inkonsequent gewesen. Die Position können Sie zwar setzen, aber nirgendwo auslesen. Die einzige Alternative dazu ist der Einsatz von API-Funktionen. Unsere Lösung ist so aufgebaut, dass ein Formular jedes Mal beim Entladen eine Prozedur aufruft, die seine aktuelle Position und Größe speichert. Beim Laden des Formulars erfolgt der Aufruf einer zweiten Prozedur, die die zuvor gespeicherten Werte ausliest, das Formular an die entsprechende Position verschiebt und die zuletzt eingestellte Größe setzt.
Für die Speicherung verwenden wir die Registry, da sie zentral aus allen Datenbanken heraus erreichbar ist und Access mit „SaveSetting“ und „GetSetting“ einfach zu handhabende Anweisungen für den Zugriff zur Verfügung stellt. Als Kriterium für das Speichern der Werte kommt eine Kombination aus Datenbankund Formularnamen zum Einsatz, sodass auch Formulare korrekt behandelt werden, die zwar den gleichen Namen haben, aber in verschiedenen Datenbanken gespeichert sind.
Wir haben für Sie eine Beispieldatenbank vorbereitet, in der Sie unsere Technik sofort einmal ausprobieren können. Starten Sie die Datenbank.
Unser Beispiel enthält die Formulare „Test 1“, „Test 2“ und „Test 3“, die Sie einfach einmal öffnen, verschieben, schließen und dann erneut öffnen sollten. Sie werden feststellen, dass jedes Formular beim erneuten Öffnen wieder exakt an der Position erscheint, an die Sie es zuletzt verschoben hatten. Die Formulare „Test 1“ und „Test 2“ sind übrigens auf feste Fenstergrößen eingestellt, das Speichern/ Setzen geänderter Größen können Sie mit dem Formular „Test 3“ testen.
So statten Sie Ihre Formulare mit der neuen Funktion aus
Alle notwendigen Deklarationen und Funktionen haben wir in dem Modul „modFormPos“ zusammengefasst, das zunächst aus unserer Beispieldatei in die Datenbank übertragen werden muss, in der Sie die Lösung einsetzen möchten. Danach können Sie die Prozeduren „FormPosSave“ und „FormPosSet“, wie im Folgenden erläutert, einsetzen.
Die Anbindung der beiden Prozeduren erfolgt über die Ereignisprozeduren „Beim Entladen“ und „Beim Laden“ eines Formulars. Die Aufrufe dieser beiden Prozeduren müssen also in die entsprechenden Ereignisprozeduren für alle Formulare aufgenommen werden, deren Positionen und/oder Größen gespeichert und gesetzt werden sollen:
- Öffnen Sie das Formular, in dem die Lösung eingesetzt werden soll, im Entwurfsmodus.
- Wählen Sie das Menü ANSICHT-EIGENSCHAFTEN an.
-
Stellen Sie die Eigenschaft „Beim Laden“ auf den Eintrag „[Ereignisprozedur]“ ein und klicken Sie auf die Schaltfläche mit den drei Punkten, um den VBA-Editor zu öffnen. Hier geben Sie die folgende Anweisung ein:
Sub Form_Load()
FormPosSet Me
End SubDiese Anweisung sorgt nun dafür, dass beim Öffnen/Laden eines Formulars dessen zuvor gespeicherte Position/ Größe gesetzt wird. Verlassen Sie dann den VBA-Editor wieder.
- Stellen Sie die Eigenschaft „Beim Entladen“ auf den Eintrag „[Ereignisprozedur]“ und klicken Sie auf die Schaltfläche mit den drei Punkten. Geben Sie dann die folgende Anweisung ein:
Sub Form_Load()
FormPosSave Me
End Sub
Diese Anweisung sorgt dafür, dass Position und Größe des Formulars bei jedem Schließen/Entladen gespeichert werden. Verlassen Sie dann wieder den VBA-Editor.
- Wiederholen Sie Schritt 1 bis 4 für alle Formulare, deren Positionen/ Größen gespeichert/gesetzt werden sollen.
Wenn die beiden Ereignisprozeduren mit den notwendigen Anweisungen versehen sind, ist die Lösung sofort einsatzbereit.
Mit diesen API-Funktionen wird die Anwendung erst möglich
Das Windows-API stellt die Funktionen „GetWindowRect()“ und „MoveWindow()“ zur Verfügung, über die sich die aktuelle Position und Größe eines Fensters auslesen beziehungsweise setzen lassen. Mithilfe von „GetWindowRect()“ sind wir also in der Lage, beim Schließen eines Formulars Position und Größe zu ermitteln. Beim Laden eines Formulars übergeben wir die gespeicherten Daten dann an „MoveWindow()“, um das Formular an die ursprüngliche Position in der derzeit eingestellten Größe zu setzen.
Die Methode „DoCmd.MoveSize“ kann übrigens nicht verwendet werden, da sie mit der Maßeinheit „Twips“ arbeitet, die Daten aber hier in der Maßeinheit „Pixel“ vorliegen.
Für die Speicherung verwenden wir, wie eingangs erwähnt, die Registry und darin den für Office-Anwendungen vorgesehenen Bereich „VB and VBA Program Settings“. Dort legen wir einen Abschnitt „FormPos“ an, der pro Datenbank weitere Abschnitte unter deren Namen beinhaltet, in denen dann Positionen und Größen unter den Namen der einzelnen Formulare gespeichert sind. Alle notwendigen Anweisungen und die Aufrufe der API-Funktionen haben wir in zwei Prozeduren, „FormPosSave“ und „FormPosSet“, zusammengefasst. Das Speichern der aktuellen Positionen/Größen sieht folgendermaßen aus:
Sub FormPosSave(F As Form)
Dim rectForm As tRECT
Dim rectParent As tRECT
Dim strDBName As String, strSection As String
Dim hWndParent As Long
Dim R As Variant
‚Datenbank-Name ermitteln
strDBName = CurrentDb.Name ‚Laufwerk:\Pfad\Dateiname.Erw
strDBName = NameOnly(strDBName) ‚Laufwerk/Pfad und Erweiterung raus…
…
strSection = strDBName & „\“ & F.Name
Hier ermitteln wir zunächst über die Eigenschaft „Name“ den Namen der aktuellen Datenbank, die über CurrentDb“ referenziert wird. Dieser Name beinhaltet Laufwerk, Pfad und Erweiterung, die wir allerdings nicht benötigen und über die Funktion „NameOnly()“ herausfiltern.
Übrig bleibt der reine Name der Datenbank. Daraus und aus dem Namen des Formulars setzen wir den Namen des Registry-Abschnitts zusammen, unter dem die Werte gespeichert werden sollen.
‚Handle des Access-Fensters ermitteln
‚hWndParent = Application.hWndAccessApp
hWndParent = GetParent(F.Hwnd)
Anschließend ermitteln wir das Window- Handle des dem Formular übergeordneten Fensters, also des Access-Anwendungsfensters, da wir Positionen/Größen bezogen auf dieses Fenster und nicht bezogen auf den Bildschirm benötigen.
Aus unerfindlichen Gründen kann „Application. hWndAccessApp“ nicht verwendet werden. Das Handle zeigt vermutlich auf den Innenbereich des Access-Fensters ohne Titelleiste, Menüs und Symbolleisten, sodass eine spätere falsche Positionierung die Folge wäre. Hier hilft uns die API-Funktion „GetParent()“, die für das Formular das richtige Handle auf das übergeordnete Fenster meldet.
‚Koordinaten des Formulars bestimmen
R = GetWindowRect(F.Hwnd, rectForm)
If Not R Then
MsgBox „Fehler beim Auslesen der Fensterposition…“, vbCritical, „FormPosSave“
Exit Sub ‚Keine weiteren Aktionen…
End If
In diesen Bereichen lesen wir die Positionen/Größen des Formulars und des Access- Fensters aus, speichern diese in speziellen Datenstrukturen …
‚Werte in Registry speichern
strSection = strDBName & „\“ & F.Name
SaveSetting „FormPos“, strSection, „X1“, rectForm.lngX1 – rectParent.lngX1
SaveSetting „FormPos“, strSection, „Y1“, rectForm.lngY1 – rectParent.lngY1
SaveSetting „FormPos“, strSection, „X2“, rectForm.lngX2 – rectParent.lngX1
SaveSetting „FormPos“, strSection, „Y2“, rectForm.lngY2 – rectParent.lngY1
End Sub
… und schreiben die Ergebnisse dann in die Registry, wobei die absolute Positionierung im Access-Fenster berücksichtigt wird.
Das Auslesen und Setzen der gespeicherten Werte übernimmt die folgende Prozedur:
Sub FormPosSet(F As Form)
Dim rectForm As tRECT
Dim strDBName As String, strSection As String
Dim lngBreite As Integer
Dim lngHoehe As Integer
Dim R As Variant
‚Datenbank-Name ermitteln
strDBName = CurrentDb.Name ‚Laufwerk:\Pfad\Dateiname.Erw
strDBName = NameOnly(strDBName) ‚Laufwerk/Pfad und Erweiterung raus…
‚Position/Größe aus Registry lesen
strSection = strDBName & „\“ & F.Name
Hier ermitteln wir zunächst wieder über die Eigenschaft „Name“ den Namen der aktuellen Datenbank, filtern über die Hilfsfunktion „NameOnly()“ Laufwerk, Pfad und Erweiterung heraus und setzen den Abschnittsnamen für die Speicherung in der Registry zusammen.
‚Position/Größe aus Registry lesen
strSection = strDBName & „\“ & F.Name
With rectForm
.lngX1 = Val(GetSetting(„FormPos“, strSection, „X1“, „0“))
If .lngX1 = 0 Then Exit Sub ‚Keine/Ungültige Settings…
.lngY1 = Val(GetSetting(„FormPos“, strSection, „Y1“, „0“))
If .lngY1 = 0 Then Exit Sub ‚Keine/Ungültige Settings…
.lngX2 = Val(GetSetting(„FormPos“, strSection, „X2“, „0“))
If .lngX2 = 0 Then Exit Sub ‚Keine/Ungültige Settings…
.lngY2 = Val(GetSetting(„FormPos“, strSection, „Y2“, „0“))
If .lngY2 = 0 Then Exit Sub ‚Keine/Ungültige Settings…
lngBreite = .lngX2 – .lngX1
lngHoehe = .lngY2 – .lngY1
‚und setzen…
R = MoveWindow(F.Hwnd, .lngX1, .lngY1, lngBreite, lngHoehe, 1)
End With
End Sub
Die aus der Registry gelesenen Werte übertragen wir dann in eine Datenstruktur, die der API-Funktion „MoveWindow()“ als Parameter übergeben wird. Sie beinhaltet die X/Y-Koordinaten (top/left, linke obere Ecke) sowie Angaben zur Breite/Höhe, die für das jeweilige Fenster gesetzt werden sollen.
Modul: modFormPos
Felder per Kennwort schützen
Wenn Datenbanken von mehreren Mitarbeitern eingesetzt werden, kommt es immer wieder zu unbeabsichtigten oder unbefugten Änderungen in einzelnen Feldern. Sie können diese Felder zwar über die Eigenschaften „Aktiviert = Nein“ und „Gesperrt = Ja“ schützen, aber dann lässt sich der Inhalt generell nicht mehr ändern.
Sie können dieses Problem aber recht einfach lösen, indem Sie für die zu schützen den Felder die Bearbeitung erst nach Abfrage eines Kennwortes erlauben. Das Kennwort erhalten dann nur ausgewählte Mitarbeiter, die zu Änderungen berechtigt sind.
Um ein Feld (Textfeld oder Kombinationsfeld) in einem Formular für diesen Schutz einzurichten, gehen Sie wie folgt vor:
- Öffnen Sie das Formular im Entwurfsmodus.
- Legen Sie neben dem zu schützenden Textfeld eine Schaltfläche mit den folgenden Eigenschaften an:Name: btnUnprotect
Bild: Sperre(Blau)
Breite: 0,6 cm
Höhe: 0,6 cmWenn Sie mehrere Felder in einem Formular schützen möchten, benennen Sie die Schaltflächen „btnUnprotectFirma“, „btnUnprotectGehalt“ oder ähnlich, nehmen Sie also die jeweilige Feldbezeichnung zur besseren Unterscheidung in den Namen auf.
- Stellen Sie die Eigenschaft „Beim Klicken“ der Schaltfläche auf den Eintrag „[Ereignisprozedur]“ und klicken Sie auf die Schaltfläche mit den drei Punkten, um den VBA-Editor zu öffnen.
-
Im VBA-Editor geben Sie folgende Anweisungen ein:
Private Sub btnUnprotect_Click()
Dim strPW As String
Const cstrPW = „geheim“
strPW = InputBox$(„Bitte das Kennwort zur Bearbeitung
eingeben:“, _
„Kennwort erforderlich“, „“)
If strPW <> cstrPW Then
Beep
MsgBox „Ungültiges Kennwort!“, _
vbOKOnly + vbExclamation, „Kennworteingabe“
Exit Sub
End If
With Me.Firma
.Enabled = True
.Locked = False
.SetFocus
End With
End SubDen Feldnamen „Firma“ ersetzen Sie dabei durch den Namen des zu schützenden Feldes. Für die Konstante „cstrPW“ geben Sie das Kennwort ein, das später zur Freischaltung des Feldes benötigt wird. Verlassen Sie anschließend den VBA-Editor wieder.
- Markieren Sie das zu schützende Textfeld und stellen Sie die Eigenschaften „Aktiviert“ auf „Nein“ und „Gesperrt“ auf „Ja“.
- Stellen Sie die Eigenschaft „Bei Fokusverlust“ des Textfeldes auf den Eintrag „[Ereignisprozedur]“ und klicken Sie auf die Schaltfläche mit den drei Punkten.
- Geben Sie im VBA-Editor die folgenden Anweisungen ein:Me.btnUnprotect.SetFocus
Me.Firma.Enabled = False
Me.Firma.Locked = True
Den Feldnamen „Firma“ ersetzen Sie dabei wieder durch den Namen des zu schützenden Feldes. Verlassen Sie anschließend den VBA-Editor.
Wenn Sie das Formular nun anzeigen lassen, ist das geschützte Feld nicht aktivierbar und kann somit auch nicht geändert werden.
Ein Klick auf die Schaltfläche hinter dem Feld zeigt einen Dialog zur Eingabe eines Kennwortes an.
Ist das Kennwort nicht korrekt, wird eine entsprechende Meldung „Ungültiges Kennwort“ angezeigt und das Feld bleibt gesperrt. Andernfalls werden die Eigenschaften „Enabled“ (Aktiviert) und „Locked“ (Gesperrt) zurückgesetzt. „Set Focus“ aktiviert das Feld schließlich für die Änderung oder Eingabe.
Bei einem Feld- oder Datensatzwechsel verliert das Feld den Fokus, sodass die Ereignisprozedur „Bei Fokusverlust“ ausgeführt und das Feld wieder geschützt wird. Damit ein Steuerelement deaktiviert werden kann, darf es nicht den Fokus haben, sonst zeigt Access einen Laufzeitfehler an. Deshalb wird der Fokus kurzerhand auf die Schaltfläche „btnUnprotect“ gesetzt.
Ereignisprozedur | Eintrag | Bedeutung |
Beim Klicken (Schaltfläche) |
=UnprotectField ([Feldname]) |
Fragt das Kennwort für das Feld „Feldname“ gemäß Eigenschaft „Tag“ ab und schaltet es gegebenenfalls frei. |
Bei Fokusverlust (Feld) |
=ProtectField ([Feldname];[Aktivieren]) |
Schützt das Feld „Feldname“ wieder, wenn es den Fokus verliert. Der zweite Parameter spezifiziert das zu aktivierende Steuer element (z. B. das nächste Feld in der Aktivierreihenfolge oder eine Schaltfläche), damit eine Fehlermeldung unterbunden wird. |
Anschließend kann das Feld problemlos über die Eigenschaften „Enabled“ und „Locked“ geschützt werden. Wenn Sie mehrere Felder in einem Formular auf die gezeigte Art schützen möchten, nutzen Sie zur Vereinfachung das von uns vorbereitete Modul „modProtect“, das Sie in der Beispieldatenbank finden und zunächst in Ihre Datenbank übertragen. Es enthält die Funktionen „UnprotectField()“ und „Protect Field()“, die die eben erläuterten Funktionalitätenparameter gesteuert bereitstellen und sich einfach über Eintragungen in den Eigenschaften „Beim Klicken“ der Schaltfläche bzw. „Bei Fokusverlust“ des Feldes aufrufen lassen. Sie sparen so die Eingabe der eben gezeigten Prozeduren für jedes zu schützende Feld. Um den Aufruf möglichst einfach zu halten, wird das Kennwort bei dieser Lösung in der Eigenschaft „Tag“ des jeweiligen Feldes hinterlegt und dort von der Funktion „UnprotectField()“ für die Abfrage ausgelesen. Die Einzelheiten zum Aufruf der Funktionen entnehmen Sie bitte der Tabelle auf dieser Seite.
Feld aus einem Unterformular übernehmen
Ein Feld aus einem Unterformular übernehmen. Z.B. In dem Formular Adressen gibt es ein Feld mit dem Namen Strasse. Es existiert auch ein Formular Archiv mit einem Unterformular Adressendaten. In diesem Unterformular ist ein Feld mit dem Namen Strasse. Diese Daten die gerade auf dem Bildschirm angezeigt werden, sollen in dem Formular Adressen Strasse übernommen werden.
Strasse = Forms!Archiv.Adressendaten!Strasse
ESC-Taste im Memofeld deaktivieren
Hier kann eine kleine VBA-Routine Abhilfe schaffen:
1. Öffnen Sie das betreffende Formular im Entwurfsmodus.
2. Markieren Sie das Memofeld.
3. Wählen Sie im Menü ANSICHT den Eintrag EIGENSCHAFTEN an.
4. Stellen Sie die Eigenschaft „Bei Taste Ab“ auf „Ereignisprozedur“ ein und klicken Sie auf die Schaltfläche mit den drei Punkten.
5. Geben Sie im VBA-Editor folgende Anweisungen ein:
If KeyCode = 27 Then
Beep
KeyCode = 0
End If
6. Schließen Sie den VBA-Editor und lassen Sie das Formular anzeigen.
Wenn nun in einem Memofeld Esc gedrückt wird, ertönt lediglich ein akustischer Hinweis, die Eingabe bleibt aber erhalten.
Achtung!
Normalerweise verwenden Sie Esc auch, um Änderungen an einem Datensatz zurückzunehmen. Das funktioniert dann natürlich nicht mehr, wenn sich der Cursor im Memofeld befindet. Aktivieren Sie in diesem Fall ein anderes Feld und drücken Sie dort Esc.
Eingaben ohne Datensatzwechsel
Wenn Sie bei einer Dateneingabe das letzte Feld in einem Formular mit der Tab-, Return– oder einer der Cursor– Tasten verlassen, springt Access normalerweise automatisch zum nächsten Datensatz. Vor allem bei weniger erfahrenen Anwendern kann dieses Verhalten zu Verwirrung führen.
Eine wenig bekannte Formular-Einstellung schafft Abhilfe: Mithilfe der Eigenschaft „Zyklus“ können Sie festlegen, wie sich der Cursor beim Verlassen des letzten Feldes verhält.
Die Standardeinstellung ist „Alle Datensätze“ und entspricht dem bekannten Verhalten: Der Cursor springt nach dem Verlassen des letzten Feldes in den folgenden Datensatz bzw. legt einen neuen Datensatz an. Die Einstellung „Aktueller Datensatz“ sorgt hingegen dafür, dass der Cursor nach dem Verlassen des letzten Feldes wieder zum ersten Feld des aktuellen Datensatzes springt. So lässt sich verhindern, dass Access unkontrolliert den Datensatz wechselt oder womöglich einen neuen, leeren Datensatz anlegt.
Für mehrseitige Formulare ist dabei die Einstellung „Aktuelle Seite“ sehr hilfreich: Sie verhindert das automatische Scrollen in den Seiten und setzt den Cursor nach Verlassen des letzten Feldes der aktuellen Formularseite wieder zurück in das erste Feld der aktuellen Formularseite.
Wenn sowohl weniger erfahrene als auch fortgeschrittene Anwender mit einer Datenbank arbeiten, empfiehlt es sich, den Zyklus standardmäßig auf „Aktueller Datensatz“ zu setzen, aber eine Umschaltmöglichkeit per Kontrollkästchen vorzusehen. Gehen Sie dazu wie folgt vor:
- Legen Sie im Formularfuß ein Kontrollkästchen „cbHalten“ an, dessen Beschriftung Sie auf „Cursor im Datensatz halten“ setzen.
- Geben Sie in der Ereignisprozedur „Beim Laden“ des Formulars die folgenden Anweisungen ein:
Private Sub Form_Load()
Me.cbHalten = True
Me.Cycle =
1 End Sub - Für die Ereignisprozedur „Nach Aktualisierung“ erfassen Sie:
Private Sub cbHalten_AfterUpdate()
If Me.cbHalten Then
Me.Cycle = 1
Else
Me.Cycle = 0
End If End Sub
Fortgeschrittene Anwender können nun bei Bedarf den „alten“ Zustand durch Deaktivierung des Kontrollkästchen wiederherstellen. Diese Lösung wird im Formular „Kunden“ der Beispieldatenbank demonstriert.