4. Formulare

4.1   Verschiedene Farben im Endlosformular 4.22 Standardwert aus vorherigem Datensatz
4.2   Bezug auf Unterformular/bericht 4.23 Tasten BildAuf/BildAb deaktivieren
4.3   Formulare synchronisieren 4.24 Cursor/Markierung positionieren
4.4   Datensatz suchen 4.25 Doppelte Eingabe vermeiden
4.5   Gleicher Datensatz nach Requery 4.26 Bezeichnungsfeld zuordnen
4.6   Formular mehrfach anzeigen 4.27 Email mit Adresse aus Textfeld
4.7   Sortierung im Formular ändern 4.28 Tiptext funktioniert nicht
4.8   Unterformular wechseln 4.29 Mausrad wechselt den Datensatz
4.9   Speichern/Löschen funktioniert nicht im A97-PopUp 4.30 Spaltenüberschrift in Datenblattansicht
4.10 Zeilenwechsel mit Pfeiltasten 4.31 Animierte GIFs darstellen
4.11 Berechnetes Feld speichern 4.32 Rückfrage vor dem Speichern
4.12 Kombi/Listenfeld - Eintrag auswählen 4.33 Prüfen ob erster/letzter/neuer Datensatz
4.13 Kombinationsfeld - Eintrag hinzufügen 4.34 Alle Steuerelemente sind verschwunden
4.14 Kombinationsfeld per Code öffnen 4.35 Schließen-Schaltfläche vermeiden in A97-Formular
4.15 Kombi/Listenfeld - Zugriff auf Spalte n 4.36 Abhängige Kombi/Listenfelder
4.16 Listenfeld - Rechtsbündig ausrichten 4.37 Rechnen in Textfeldern
4.17 Register - Seitenwechsel-Ereignis 4.38 Datensatzwechsel per Tastatur verhindern
4.18 Register - Seitenwechsel mit Tastatur 4.39 Laufende Nummer/Summe in Formularen
4.19 Prüfen ob Formular geöffnet 4.40 Mehrere markierte Datensätze ermitteln
4.20 Bildschirmauflösung ermitteln 4.41 Textfeld zur Passwort-Eingabe
4.21 Formulare an Auflösung anpassen
   
4.1 Verschiedene Farben im Endlosformular
http://www.donkarl.com?FAQ4.1 aktualisiert 2007-05-18

Problem

Du möchtest in einem Endlosformular bestimmte Datensätze (bzw. Felder) durch spezielle Formatierungen kennzeichnen. Wenn du eine solche Zuweisung (z.B. per Code oder Ausdruck mit irgendeiner Bedingung) versuchst, wird die Formatierung in allen Datensätzen geändert.

Ursache

Format-Einstellungen für Formulare werden in Access gemeinsam gespeichert und gelten daher für alle Datensätze.

Lösung

Ab A00 lässt sich das mit der Bedingten Formatierung einstellen. Dazu in der Entwurfsansicht des Formulares ein Steuerelement markieren und Menü Format/Bedingte Formatierung wählen. Die Einstellungen sind auch per VBA möglich, s. <F1> zur FormatConditions-Eigenschaft.

Möglichkeiten in älteren Access-Versionen:
Bei der Textfarbe können mit der Format-Einstellung 4 Zustände unterschieden und entsprechend eingefärbt werden. s. Online-Hilfe unter "Format-Eigenschaft - Datentypen Zahl und Währung"

Für die Hintergrundfarbe gibt es versch. Trixereien (hinterlegte Steuerelemente, formatfüllende Textzeichen, BMPs etc.) Ein kleines Beispiel könnt ihr hier downloaden colorend.zip (11 KB)

Bei Stephen Lebans gibt's Lösungen unter Verwendung von APIs:
http://www.lebans.com/formatbycriteria.htm

Bei Dev Ashish gibt's ein Beispiel für den aktuellen Datensatz: http://www.mvps.org/access/forms/frm0047.htm

nach oben

4.2 Bezug auf Unterformular/bericht
http://www.donkarl.com?FAQ4.2 aktualisiert 2012-12-14

Problem

Der Bezug auf ein Feld oder eine Eigenschaft im Unterformular/-bericht funktioniert nicht.

Lösung

Die Syntax für den Bezug auf ein Steuerelement im Ufo lautet:

Forms![Hauptformular]![UFoSteuerelement_im_Hauptformular].Form![Steuerelement_im_Ufo]

"UFoSteuerelement_im_Hauptformular" ist dabei der Name des Steuerelementes, in dem sich das Unterformular befindet. Diese Bezeichnung steht in der Eigenschaft Name des Steuerelementes und muss nicht ident sein mit dem Namen des Formulares, das als Unterformular dient, also der Eigenschaft Herkunftsobjekt. Diese Verwechslung ist die häufigste Fehlerquelle bei Bezügen.

Vom Hauptformular aus reicht:
Me![UFoSteuerelement_im_Hauptformular].Form![Steuerelement_im_Ufo]

Um den Fokus auf ein Element im Ufo setzen zu können, oder z.B. die Methode GoToRecord im Ufo anwenden zu können, ist es notwendig, vorher den Fokus auf das Ufo-Steuerelement im Hauptformular zu setzen:

Me![UFoSteuerelement_im_Hauptformular].SetFocus
Me![UFoSteuerelement_im_Hauptformular].Form![Steuerelement_im_Ufo].SetFocus


bzw.

Me![UFoSteuerelement_im_Hauptformular].SetFocus
DoCmd.GoToRecord , , acNext


Analog funktioniert es mit Berichten. Lediglich "Forms" ist durch "Reports" zu ersetzen und "Form" durch "Report".

Syntaxbeispiele für alle mögl. Varianten bei Dev Ashish:
http://www.mvps.org/access/forms/frm0031.htm

nach oben

4.3 Formulare synchronisieren
http://www.donkarl.com?FAQ4.3 aktualisiert 2012-12-14

Problem

Du möchtest, wenn ein Datensatz in einem Formular ausgewählt wird, dass in einem anderen Formular der selbe Datensatz angezeigt wird.

Lösung

Angenommen, das eindeutige und zu vergleichende Feld in beiden Formularen heißt "Id". Dann bei einem passenden Ereignis z. B. Beim Anzeigen des 1. Formulares:

Forms!frmFormular2.Recordset.FindFirst "Id = " & Me!Id

Die Verwendung des Formular-Recordsets ist ab Access 2000 möglich. In älteren Versionen kann man mit dem RecordsetClone arbeiten. Ein Beispiel dafür zeige ich hier: KB-Artikel mit Beispiel-DB

nach oben

4.4 Datensatz suchen
http://www.donkarl.com?FAQ4.4 aktualisiert 2012-12-14

Problem

Du hast ein ungebundenes Text- oder Kombifeld z.B. "txtSuch". Nach Eingabe oder Auswahl eines Wertes z.B. einer RechnungsNr, möchtest du, dass der Datensatz mit dieser RechnungsNr gefunden und angezeigt wird.

Lösung

Wenn dein Feld "RechnungsNr" im Formular sichtbar ist und den Fokus haben kann, dann kannst du beim Ereignis Nach Aktualisierung von "txtSuch" die FindRecord-Methode verwenden:

Me!RechnungsNr.SetFocus
DoCmd.FindRecord Me!txtSuch


Ansonsten kannst du ebenfalls bei Nach Aktualisierung von "txtSuch" folgendes veranstalten:

Me.Recordset.FindFirst "RechnungsNr = " & Me!txtSuch
'oder falls RechnungsNr kein Zahlenfeld ist sondern vom Typ Text:
'Me.Recordset.FindFirst "RechnungsNr = '" & Me!txtSuch & "'"


Die Verwendung des Formular-Recordsets ist ab Access 2000 möglich. In älteren Versionen kann man mit dem RecordsetClone arbeiten. Ein Beispiel dafür zeige ich hier: KB-Artikel mit Beispiel-DB

nach oben

4.5 Gleicher Datensatz nach Requery
http://www.donkarl.com?FAQ4.5 aktualisiert 2012-12-14

Problem

Du musst zur Aktualisierung der Daten ein Requery durchführen. Der Fokus geht dabei auf den 1. Datensatz des Formulares zurück. Du möchtest aber beim vorher aktuellen Datensatz bleiben.

Lösung

Speichere die Id (ein eindeutiges Feld) des aktuellen Datensatzes. Dann kannst du nach dem Requery zurückkehren.

Dim lngStore As Long

lngStore = Me!Id

'Bildschirmflackern reduzieren
Me.Painting = False

Me.Requery
Me.Recordset.FindFirst "Id = " & lngStore

Me.Painting = True

nach oben

4.6 Formular mehrfach anzeigen
http://www.donkarl.com?FAQ4.6

Problem

Du möchtest ein Formular mehrfach aufrufen d.h mehrmals am Bildschirm haben um z.B. mehrere Datensätze neben- und übereinander darstellen zu können.

Lösung

Du kannst (ab A95) mehrere Instanzen eines Formulares öffnen. Bissel Info dazu gibt's in der Online-Hilfe unter "Instanzen von Formularen".
z.B. schreibst du im Deklarationsbereich des Formularmoduls:

Dim FormNochmal As New Form_DeinFormular

Bei einem passenden Ereignis machst du dann die 2. Instanz sichtbar und setzt sie an eine andere Stelle am Bildschirm, sonst liegt sie genau über der 1. Instanz:

With FormNochmal
  .Visible = True
  DoCmd.MoveSize 2000, 2000
End With


s.a. http://support.microsoft.com/?kbid=210248
KB-Artikel mit Beispiel-DB

nach oben

4.7 Sortierung im Formular ändern
http://www.donkarl.com?FAQ4.7

Problem

Du möchtest die Sortierreihenfolge im Formular ändern, ohne die Menü- oder Symbolleistenpunkte Aufsteigend/Absteigend Sortieren zu verwenden, sondern z.B. beim Klicken einer selbst erstellten Schaltfläche.

Lösung

Entweder du bastelst dir einen SQL-String mit einer entsprechenden Order By-Klausel als Datenherkunft des Formulares oder du setzt die Formular-Eigenschaften OrderBy und OrderByOn mit VBA:

Beispiel mit SQL-String:

Dim strSQL As String
strSQL = "SELECT tbl_Kunden.* FROM tbl_Kunden ORDER BY tbl_Kunden.Vorname;"
Me.RecordSource = strSQL


Wenn man nicht besonders SQL-erfahren ist oder bei komplizierteren Statements, ist es am einfachsten, eine Abfrage im Abfrageeditor von Access zu erzeugen und sich den SQL-Text dann aus der SQL-Ansicht des Abfrageentwurfs zu kopieren.

Das Sortieren durch Änderung der Datenherkunft ist i.d.R. die bessere Variante. Nicht nur, weil's professioneller wirkt, sondern auch weil Access bei Sortierung über die Formular-Eigenschaften (egal ob über die Benutzeroberfläche oder per Code) die letzte Sortierung in der Sortiert nach-Eigenschaft fix speichert. Dennoch auch dafür Beispiele:

'aufsteigend nach dem Feld Vorname sortieren
Me.OrderBy = "Vorname"
Me.OrderByOn = True


'absteigend
Me.OrderBy = "Vorname desc"
Me.OrderByOn = True


Access speichert die letzte Sortierung. Um sie beim nächsten Öffnen des Formulares nicht anzuwenden, kann man im Ereigniscode beim Öffnen schreiben:
Me.OrderBy = ""

s.a. http://support.microsoft.com/?kbid=207769
KB-Artikel mit Beispiel-DB

nach oben

4.8 Unterformular wechseln
http://www.donkarl.com?FAQ4.8 aktualisiert 2012-06-08

Problem

Du möchtest während der Laufzeit in einem Formular verschiedene Unterformulare im selben Unterformular-Steuerelement verwenden.

Lösung

Du kannst mit VBA die Eigenschaft Herkunftsobjekt des Ufo-Steuerelementes im Hauptformular (hier: "UFoElement") ändern:

Me!UFoElement.SourceObject = "NächstesUFo"

Wenn dadurch auch die Felder für die Verknüpfung zwischen Haupt- und Unterformular anders heißen, musst du die Eigenschaften Verknüpfen von und Verknüpfen nach des UFoElements ändern:

Me!UFoElement.LinkChildFields = "FeldimUFo"
Me!UFoElement.LinkMasterFields = "FeldimHauptFormular"


Access verknüpft automatisch über das Primärschlüsselfeld, sofern vorhanden. Wenn du bei einem Ufo-Wechsel nicht über ein vorhandenes Primärschlüsselfeld verknüpfen willst, musst du vor dem Neuzuweisen der Verknüpfungsfelder die Eigenschaften auf einen Leerstring setzen:

Me!UFoElement.SourceObject = "NächstesUFo"
Me!UFoElement.LinkChildFields = ""
Me!UFoElement.LinkMasterFields = ""
Me!UFoElement.LinkChildFields = "FeldimUFo"
Me!UFoElement.LinkMasterFields = "FeldimHauptFormular"


KB-Artikel mit Beispiel-DB

nach oben

4.9 Speichern/Löschen funktioniert nicht im A97-PopUp
http://www.donkarl.com?FAQ4.9

Problem

Du verwendest in A97 in einem PopUp-Formular Code, den der Assistent erstellt hat. Im Code befinden sich Befehle, die DoMenuItem verwenden z.B. Speichern, Löschen. Diese Befehle funktionieren nicht.

Ursache

In A97 funktioniert DoMenuItem nicht im PopUp, weil die Menübefehle auch per VBA in einem PopUp-Formular nicht zugänglich sind. (in anderen Versionen sollte es funktionieren)

Lösung

Ersetze die DoMenuItem-Befehle durch RunCommands z.B.

Speichern des aktuellen Datensatzes: RunCommand acCmdSaveRecord
Löschen des aktuellen Datensatzes: RunCommand acCmdDeleteRecord

Das Ersetzen der veralteten DoMenuItem-Befehle ist in jedem Fall ratsam. Sie werden nur noch aus Kompatibilitätsgründen mitgeschleppt bzw. weil MS die Assistenten nie aktualisiert hat, und die RunCommand-Befehle sind wesentlich aussagekräftiger.

nach oben

4.10 Zeilenwechsel mit Pfeiltasten
http://www.donkarl.com?FAQ4.10

Problem

Du möchtest in der Formularansicht mit den Tasten PfeilAuf und PfeilAb den Datensatz wechseln, ähnlich wie das in der Datenblattansicht oder in Tabellen und Abfragen möglich ist.

Lösung

Stelle die Eigenschaft Tastenvorschau des Formulares auf Ja ein. In das Ereignis Bei Taste Ab des Formulares kopierst du folgendes:

On Error Resume Next 'falls erster oder letzter Datensatz erreicht
Select Case KeyCode
    Case vbKeyDown
        KeyCode = 0
        DoCmd.GoToRecord , , acNext
    Case vbKeyUp
        KeyCode = 0
        DoCmd.GoToRecord , , acPrevious
End Select


KB-Artikel mit Beispiel-DB

nach oben

4.11 Berechnetes Feld speichern
http://www.donkarl.com?FAQ4.11

Problem

Du möchtest den Wert aus einem berechneten Steuerelement in der Tabelle speichern, auf der das Formular basiert.

Lösung

Prinzipiell ist es keine gute Angewohnheit, einen berechneten Wert zu speichern. Zuerst solltest du dir also überlegen, ob es wirklich nötig ist, weil der Wert i.d.R. jederzeit wieder berechnet werden kann. Sinnvoll ist eine Speicherung evtl., wenn sich einzelne Faktoren im Lauf der Zeit ändern können und du keine separate History-Tabelle führen willst, oder wenn die Formeln komplex sind und sich mit dem Speichern Performance gewinnen lässt.

Du brauchst natürlich in der Tabelle ein Feld, das den Wert aufnimmt.
Dann kannst du entweder Nach Aktualisierung jedes der Felder, die zur Berechnung beitragen, oder Vor Aktualisierung des Formulares folgenden Code verwenden:

Me!MeinTabellenFeld = Me!MeinBerechnetesSteuerelement

nach oben

4.12 Kombi/Listenfeld - Eintrag auswählen
http://www.donkarl.com?FAQ4.12

Problem

Du möchtest eine bestimmte Zeile in einem Kombinations- oder Listenfeld auswählen oder z.B. die erste Zeile als Standardwert definieren, damit sie beim Öffnen eines Formulares ausgewählt ist.

Lösung

Schreib in die Ereignisprozedur Beim Öffnen des Formulares:

Me!KombiName = Me!KombiName.ItemData(0)
oder
schreibe bei der Eigenschaft "Standardwert" des Kombis:
[KombiName].[ItemData](0)

Der Index von ItemData beginnt mit 0 = 1. Zeile, 1 = 2. Zeile etc.

nach oben

4.13 Kombinationsfeld - Eintrag hinzufügen
http://www.donkarl.com?FAQ4.13 aktualisiert 2007-01-08

Problem

Du möchtest zu den Einträgen in einem Kombinationsfeld einen neuen hinzufügen.

Lösung

Variante 1

Wenn du ohne Nachfrage den eingegebenen Wert in die Datenherkunft des Kombis übernehmen willst, dann
- sortiere das Kombi nach dem Feld, dessen Wert eingegeben wird,
- setze die Eigenschaft Nur Listeneinträge auf Ja und
- verwende im Ereignis Bei nicht in Liste des Kombis Code wie diesen:

'************** CODE START **************
Response = acDataErrAdded
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("Tabellenname", dbOpenDynaset)

rs.AddNew
rs!Feldname = NewData
rs.Update

rs.Close : Set rs = Nothing
Set db = Nothing

'************** CODE ENDE **************

Variante 2

Du möchtest z.B. im Formular "frm_Rechnung" bei neuem Eintrag im Kombi "cbo_SuchKunde" (gebundene Spalte ist "KundenID") zuerst nachfragen, dann das Eingabeformular ("frm_NeuKunde") öffnen, den im Kombi eingegebenen Kundennamen in das Eingabeformular übernehmen, dort weitere Details eingeben, und danach im Kombi den neuen Wert anzeigen. Im Ereignis Bei nicht in Liste des Kombis:

'************** CODE START **************
If MsgBox("Der Kunde ist neu. Möchten Sie ihn anlegen?", vbYesNo) = vbYes Then
  Response = acDataErrContinue
  DoCmd.OpenForm "frm_NeuKunde", , , , acFormAdd
  Forms!frm_NeuKunde!Kundenname = NewData
Else  'z.B. bei Tippfehler
  Response = acDataErrContinue
  Me!cbo_SuchKunde.Undo
End If

'************** CODE ENDE **************

Beim Schließen des Eingabeformulars:
Forms!frm_Rechnung!cbo_SuchKunde = Me!KundenID
Forms!frm_Rechnung!cbo_SuchKunde.Requery


KB-Artikel mit Beispiel-DB

nach oben

4.14 Kombinationsfeld per Code öffnen
http://www.donkarl.com?FAQ4.14

Problem

Du möchtest die Auswahlliste eines Kombis öffnen, ohne, dass der User auf den Button des Kombis drücken muss.

Lösung

Dafür gibt es ab A95 eine eigene Methode namens Dropdown:

Me!Mein_Kombinationsfeld.SetFocus
Me!Mein_Kombinationsfeld.Dropdown


In A2 musst du das noch mit Sendkeys "%{down}" oder Sendkeys "{F4}" machen, was nicht zu empfehlen ist, weil Sendkeys buggy ist.

nach oben

4.15 Kombi/Listenfeld - Zugriff auf Spalte n
http://www.donkarl.com?FAQ4.15

Problem

Du möchtest aus einem Listen- oder Kombinationsfeld den Wert einer Spalte übernehmen, die nicht die gebundene Spalte ist.

Lösung

Verwende die Eigenschaft Column(Spalte).
Das Argument "Spalte" beginnt dabei mit 0 für die 1. Spalte zu zählen. Du kannst also z.B. den Wert aus der 2. Spalte eines Kombis in einem anderen Textfeld anzeigen, indem du als dessen Steuerelementinhalt schreibst:

=[Kombi].[Column](1)

Soll der Wert der Spalte in einem anderen Feld gespeichert werden, dann kann per VBA z.B. im Ereignis Nach Aktualisierung des Kombis die Zuweisung erfolgen:

DeinFeld = Me!Kombi.Column(1)

nach oben

4.16 Listenfeld - Rechtsbündig ausrichten
http://www.donkarl.com?FAQ4.16

Problem

Du möchtest eine Spalte (i.d.R. Zahlen) in einem Listenfeld rechtsbündig ausrichten.

Lösung

Es gibt keine eingebaute Eigenschaft oder dergl. mit der sich das einstellen lässt. Spalten in Listenfeldern werden immer linksbündig als Text ausgerichtet.
Ein altbekannter Workaround sieht so aus:
- Stelle für das Listenfeld eine nichtproportionale Schrift ein (z.B. eine der Courier-Schriften)
- Verwende eine Abfrage als Datensatzherkunft
- In der Abfrage schreibst du z.B. für ein Feld [Preis] folgenden Ausdruck

Leerzchn(12-Länge(Format([Preis];"#.##0,00"))) & Format([Preis];"#.##0,00")

Dadurch wird ein Text mit 12 Zeichen erzeugt und vorne mit Leerzeichen aufgefüllt. Das Beispiel hier reicht für eine Zahl bis zu einfachen Millionenbeträgen.

Eine weitere Möglichkeit ist die Verwendung von APIs. Die Sache funktioniert IMO ein bissel wackelig, aber du kannst dir den interessanten Versuch von Stephen Lebans dazu ansehen:
http://www.lebans.com/justicombo.htm

nach oben

4.17 Register - Seitenwechsel-Ereignis
http://www.donkarl.com?FAQ4.17

Problem

Du möchtest auf das Wechseln der Registerseite reagieren und findest kein passendes Ereignis.

Lösung

Beim Wechseln der Seite z.B. mit Klick auf die Registerzunge, wird das Ereignis Bei Änderung des Registersteuerelementes ausgelöst. Dabei lässt sich die Eigenschaft Seitenindex des Registers auslesen. Ist eh ident mit der Standardeigenschaft Value. Also einfach:

Select Case DeinRegisterSteuerelement
  Case 0
    'es wurde auf die 1. Seite gewechselt
  Case 1
    'die 2. Seite
  'usw.
End Select

nach oben

4.18 Register - Seitenwechsel mit Tastatur
http://www.donkarl.com?FAQ4.18

Problem

Du möchtest vom letzten Feld der 1. Registerseite durch Drücken der TAB-, RETURN- oder DOWN-Taste in das erste Feld der 2. Seite gelangen.

Lösung

Schreib im Code Bei Taste Ab deines letzten Feldes auf der 1. Seite:

Select Case KeyCode
  Case vbKeyReturn, vbKeyDown, vbKeyTab And (Shift And acShiftMask) = 0
    KeyCode = 0
    Me!ErstesSteuerelementAufSeite2.SetFocus
End Select


KB-Artikel mit Beispiel-DB

nach oben

4.19 Prüfen ob Formular geöffnet
http://www.donkarl.com?FAQ4.19

Problem

Du möchtest für eine Bedingung in Code oder in einem Ausdruck wissen, ob ein bestimmtes Formular geöffnet ist.

Lösung

Ab A00 gibt es für Access-Objekte die Eigenschaft IsLoaded:

CurrentProject.AllForms("MeinFormular").IsLoaded

gibt True oder False zurück.

Alternativ und v.a. schon in A95 und A97 kann man SysCmd verwenden. Kopier dir dazu folgendes in ein Standardmodul:

Public Function fctIsFormOpen(StrName As String) As Boolean
  fctIsFormOpen = (SysCmd(acSysCmdGetObjectState, acForm, StrName) > 0)
End Function


In VBA kannst du dann abfragen, ob das Formular geöffnet ist z.B.:
If fctIsFormOpen("MeinFormular") Then machwas…

In Ausdrücken an der Access-Oberfläche z.B. in der Bedingungsspalte eines Makros kannst du schreiben:
fctIsFormOpen("MeinFormular")

nach oben

4.20 Bildschirmauflösung ermitteln
http://www.donkarl.com?FAQ4.20

Problem

Du möchtest die aktuelle Auflösung des Bildschirmes ermitteln.

Lösung

Kopiere dir folgendes in den Deklarationsbereich eines Standardmoduls:

Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Const SM_CXSCREEN = 0
Const SM_CYSCREEN = 1


Aufruf dann z.B. über eine Funktion wie:

Public Function fctAufloesung()
  fctAufloesung = "Pixel horizontal: " & GetSystemMetrics(SM_CXSCREEN) & _
    "  vertikal: " & GetSystemMetrics(SM_CYSCREEN)
End Function

nach oben

4.21 Formulare an Auflösung anpassen
http://www.donkarl.com?FAQ4.21 aktualisiert 2012-12-07

Problem

Du möchtest die Größe der Formulare, Position und Größe der Steuerelemente usw. an die aktuelle Bildschirmauflösung anpassen.

Lösung

Eine technisch einfache, aber mit erhöhtem Pflegeaufwand verbundene Methode ist, mehrere Versionen eines Formulares zu erzeugen und je nach Auflösung das passende zu öffnen.

Für die dynamische Anpassung von Steuerelement-Größen gibt es ab Access 2007 die Anker-Eigenschaften.

Für weitergehende Anpassungen hingegen ist viel Code notwendig. Dabei kommt es oft zu Problemen im Detail mit Proportionen, Schriftgrößen etc. Das gilt manchmal auch für die diversen Tools im Internet wie z.B.

- Form Resizer For Microsoft Access http://jamiessoftware.tk/resizeform/afr.exe
- Access Developer's Handbook scaling/resizing utility http://www.developershandbook.com/Downloads/ADHResize.zip
- ShrinkerStretcher http://www.peterssoftware.com

nach oben

4.22 Standardwert aus vorherigem Datensatz
http://www.donkarl.com?FAQ4.22 aktualisiert 2016-01-07

Problem

Du möchtest einen gerade eingegebenen Wert in einem neuen Datensatz als Standardwert vorgeben, um ihn nur bei Bedarf ändern zu müssen.

Lösung

Schreibe in der Ereignisprozedur Nach Aktualisierung des jeweiligen Steuerelementes oder des Formulares:

bei Textfeldern
Me!MeinSteuerelement.DefaultValue = Chr$(34) & Me!MeinSteuerelement & Chr$(34)

bei Datumsfeldern
Me!MeinSteuerelement.DefaultValue = Str(CDbl(Me!MeinSteuerelement))

bei anderen Felddatentypen (Zahl, Ja/Nein etc.)
Me!MeinSteuerelement.DefaultValue = Me!MeinSteuerelement

KB-Artikel mit Beispiel-DB

nach oben

4.23 Tasten BildAuf/BildAb deaktivieren
http://www.donkarl.com?FAQ4.23 aktualisiert 2005-08-24

Problem

Mit den Tasten <BildAuf> und <BildAb> kann standardmäßig der Datensatz gewechselt werden. Genau das möchtest du unterbinden.

Lösung

Setze die Eigenschaft Tastenvorschau des Formulares auf Ja.

Im Ereignis Bei Taste ab des Formulares:
If KeyCode = vbKeyPageUp Or KeyCode = vbKeyPageDown Then KeyCode = 0

Analog sind sämtliche Tasten auf Formularebene in VBA programmierbar.

Wenn du nur die normalen Access-Funktionstasten sperren willst, kannst du das auch im Menüpunkt Extras/Start machen. Ansonsten schau in die Online-Hilfe unter "Tastatur, Tastaturbelegung-Makrogruppen".

nach oben

4.24 Cursor/Markierung positionieren
http://www.donkarl.com?FAQ4.24

Problem

Du möchtest den Cursor in einem Textfeld "automatisch" an die erste oder letzte Stelle setzen oder den ganzen Inhalt des Feldes markieren.

Lösung

Das Cursorverhalten bei Eintritt in ein Feld lässt sich (für die ganze Datenbank geltend) im Menü Extras/Optionen/Tastatur einstellen.

Für einzelne Steuerelemente lässt es sich programmieren. Entweder man verwendet die folgenden VBA-Anweisungen bei Ereignissen wie Beim Hingehen oder Beim Klicken des Steuerelementes oder man setzt zuvor den Cursor in das Steuerelement z.B. mit:
Me!MeinTextfeld.SetFocus

Cursor an den Anfang des Textes
Me!MeinTextfeld.SelStart = 0

Cursor an das Ende des Textes
Me!MeinTextfeld.SelStart = Len("" & Me!MeinTextfeld)

ganzen Text markieren
Me!MeinTextfeld.SelStart = 0
Me!MeinTextfeld.SelLength = Len("" & Me!MeinTextfeld)


Das Voransetzen des Leer-Strings verhindert eine Fehlermeldung der Len-Funktion bei leeren Feldern. Das gleiche erreicht man auch mit: Len(nz(Me!MeinTextfeld))

KB-Artikel mit Beispiel-DB

nach oben

4.25 Doppelte Eingabe vermeiden
http://www.donkarl.com?FAQ4.25 aktualisiert 2005-12-07

Problem

Du möchtest vermeiden, dass in ein Feld ein Wert eingegeben wird, der schon einmal in der zugrunde liegenden Tabelle drin ist. Wenn das versucht wird, soll eine verständliche Fehlermeldung erscheinen.

Lösung

Variante 1

Setze in der Tabelle bei diesem Feld die Eigenschaft Indiziert auf Ja (Ohne Duplikate).
Im Ereigniscode Bei Fehler (On Error) des Formulares schreibst du:

If DataErr = 3022 Then
  Response = acDataErrContinue
  MsgBox Me!MeinSteuerelement & " gibt es bereits.", vbOKOnly, "Duplikat!"
  Me!MeinSteuerelement.SetFocus
End If


Variante 2

Bei obigem Vorgehen erfolgt die Prüfung erst beim Versuch, den Datensatz zu speichern, also i.d.R. beim Wechseln des Datensatzes. Wenn die Prüfung gleich nach dem Eingeben des Wertes in ein Feld stattfinden soll, kannst du das Ereignis Vor Aktualisierung des Steuerelementes nutzen und Code wie diesen:

If Not IsNull(Dlookup("MeinFeld", "MeineTabelle", _
    "MeinFeld = " & Chr$(34) & Me!MeinSteuerelement & Chr$(34))) _
    And Me!MeinSteuerelement <> nz(Me!MeinSteuerelement.OldValue) Then

  MsgBox Me!MeinSteuerelement & " gibt es bereits.", vbOKOnly, "Duplikat!"
  Cancel = True

End If


In der 2. Zeile des Codes wird der Feldtyp Text vorausgesetzt. Wenn es sich hingegen um eine Zahl handelt, sollte die 2. Zeile lauten:

"MeinFeld = " & Str(Me!MeinSteuerelement))) _

nach oben

4.26 Bezeichnungsfeld zuordnen
http://www.donkarl.com?FAQ4.26

Problem

Du hast bei einem Steuerelement kein zugeordnetes Bezeichnungsfeld und möchtest ein solches nachträglich erstellen, z.B. damit man durch Klick darauf das übergeordnete Steuerelement aktivieren kann, die beiden im Entwurf gemeinsam verschoben werden etc.

Lösung

Erzeuge zunächst mithilfe der Toolbox ein ungebundenes Bezeichnungsfeld.
Schneide das Feld in die Zwischenablage aus.
Markiere das Steuerelement, dem es zugeordnet werden soll.
Füge das Bezeichnungsfeld aus der Zwischenablage wieder ein.
Es ist nun an das zuvor markierte Steuerelement gebunden.

nach oben

4.27 Email mit Adresse aus Textfeld
http://www.donkarl.com?FAQ4.27

Problem

Du hast im Formular ein Textfeld mit einer Emailadresse und möchtest das Standard-Emailprogramm mit einer neuen Email und der Adresse aus dem Feld öffnen.

Lösung

Schreib (ab A97) beim gewünschten Ereignis in der Ereignisprozedur:
DoCmd.SendObject , , , Me!MeinTextfeld , , , , , True

Wenn du den Text im Steuerelement gerade geändert hast und sich der Fokus beim Aufruf der Mail noch im Textfeld befindet, dann musst du die Eigenschaft Text des Steuerelementes verwenden:
DoCmd.SendObject , , , Me!MeinTextfeld.Text , , , , , True

Du kannst mit SendObject auch den Betreff und den Text der Email vorgeben. (s. <F1>)

Wenn du statt des Textfeldes unbedingt ein Hyperlink-Feld verwenden möchtest, besteht das Problem, dass der Anwender i.d.R. nicht weiß, dass er vor der Email-Adresse "mailto:" eingeben müsste. Tut er das nicht, geht Access auch bei einer Mail-Adresse von einer Webseite aus, setzt "http://" davor und öffnet den Webbrowser. Eine Möglichkeit, das zu verhindern, ist, die Eingabe im Ereignis Nach Aktualisierung des Feldes zu korrigieren:

If InStr(Me!MeinTextfeld, "@") > 0 Then
  If InStr(Me!MeinTextfeld, "#http") > 0 Then
    Me!MeinTextfeld = "#mailto:" & Mid(Me!MeinTextfeld, 1, InStr(Me!MeinTextfeld, "#http") - 1) & "#"
  End If
End If

nach oben

4.28 Tiptext funktioniert nicht
http://www.donkarl.com?FAQ4.28

Problem

Du hast bei einem Steuerelement in der Eigenschaft Steuerelement Tip-Text einen Text eingegeben. Wenn du mit der Maus drauf gehst, erscheint der Tiptext aber nicht.

Lösung

Meistens liegt es daran, dass ein transparentes Rechteck oder dergl. über dem Steuerelement liegt und es daher nicht im Vordergrund ist. Auch wenn nichts darüber liegen sollte, markiere das betreffende Steuerelement und wähle den Menüpunkt Format/In den Vordergrund.

nach oben

4.29 Mausrad wechselt den Datensatz
http://www.donkarl.com?FAQ4.29 aktualisiert 2009-10-19

Problem

Bei manchen Mäusen mit Rad (v.a. MS-Intellimouse) kann der Anwender durch Drehen des Rades den Datensatz wechseln, was du eigentlich verhindern möchtest. Es kann auch vorkommen, dass schon leichtes Drehen am Mausrad wildes Scrollen zwischen den Datensätzen zur Folge hat.

Lösung

Ab A07 besteht das Problem nicht mehr, da der Datensatzwechsel per Mausrad deaktiviert wurde.
Für Versionen bis inkl. A03 gibt es Code zum Abfangen der Mausbefehle von Wayne Phillips, der keine externe DLL oder dergl. braucht:
http://www.everythingaccess.com/tutorials.asp?ID=A-new-method-for-disabling-the-Mouse-Scroll-Wheel-in-Access-forms

Die klassischen Lösungen funktionieren mit DLLs:
http://www.lebans.com/mousewheelonoff.htm
http://support.microsoft.com/?kbid=278379
http://www.mvps.org/access/api/api0036.htm

Das wilde DS-Springen mit der Intellimouse wird lt. MS vom SR2 zu O97 bzw. durch neue Maustreiber gefixt:
http://support.microsoft.com/?kbid=192008

nach oben

4.30 Spaltenüberschrift in Datenblattansicht
http://www.donkarl.com?FAQ4.30 aktualisiert 2007-01-03

Problem

Du öffnest ein Formular in der Datenblattansicht und möchtest die Spaltenüberschriften ändern, findest aber keine entsprechende Eigenschaft oder Einstellung.

Lösung

Es gibt zwei Möglichkeiten, woher die Spalten ihre Beschriftung beziehen.

1. Wenn zu einem Steuerelement kein Bezeichnungsfeld zugeordnet ist, dann wird die Eigenschaft Name des Steuerelementes als Überschrift verwendet, d.h. du kannst diese Eigenschaft ändern, um auch die Spaltenüberschrift zu ändern.

2. Existiert ein zugeordnetes Bezeichnungsfeld, dann wird dessen Eigenschaft Beschriftung (in VBA: Caption) als Spaltenüberschrift verwendet, auch wenn in der Datenblattansicht solche Bezeichnungsfelder gar nicht angezeigt werden. Du kannst also in der Entwurfsansicht oder per VBA diese Eigenschaft einstellen und damit die Spaltenüberschrift ändern. Wie man nachträglich Bezeichnungsfelder zuordnet steht in FAQ 4.26.

nach oben

4.31 Animierte GIFs darstellen
http://www.donkarl.com?FAQ4.31 aktualisiert 2008-11-22

Problem

Du möchtest in einem Formular animierte GIFs darstellen.

Lösung

ohne ActiveX:
von Stephen Lebans http://www.lebans.com/animatedgifplayer.htm

ActiveX-Steuerelemente:
von MS gibt es das Microsoft Animation Control (kommt mit irgendwelchen MSComCtl-Klassen bzw. mit ODE/MOD)
s.a. http://support.microsoft.com/?kbid=209919
Shareware: Animation Gif Control http://www.jcomsoft.com/anigif.htm

Eine weitere Möglichkeit ist die Verwendung des Webbrowser- oder DHTML Edit-Steuerelements des MS Internet Explorers.

nach oben

4.32 Rückfrage vor dem Speichern
http://www.donkarl.com?FAQ4.32

Problem

Wenn ein Datensatz geändert wurde, soll er nicht automatisch gespeichert werden, sondern eine Sicherheitsabfrage erscheinen.

Lösung

Verwende in der Ereignisprozedur Vor Aktualisierung des Formulares Code wie diesen:

If MsgBox("Änderungen speichern?", vbYesNo, "Speichern?") = vbNo Then
  Me.Undo  'rückgängig
  Cancel = True  'Ereignisse verhindern
End If

nach oben

4.33 Prüfen ob erster/letzter/neuer Datensatz
http://www.donkarl.com?FAQ4.33

Problem

Du möchtest (programmatorisch) herausfinden, ob der aktuelle DS der erste oder letzte im Formular ist oder ein neuer.

Lösung

Verwende (ab A95) Code wie den folgenden bei einem passenden Ereignis z.B. Beim Anzeigen:

If Me.CurrentRecord = 1 Then MsgBox "Ich bin Erster!"

Me.RecordsetClone.MoveLast
If Me.CurrentRecord = Me.RecordsetClone.RecordCount Then MsgBox "Ich bin Letzter!"

If Me.NewRecord Then MsgBox "Ich bin neu hier."


Erläuterungen gibt's unter den Stichworten "CurrentRecord" und "NewRecord" in der Online-Hilfe.

nach oben

4.34 Alle Steuerelemente sind verschwunden
http://www.donkarl.com?FAQ4.34

Problem

Ein Formular, das in Formularansicht geöffnet wird, ist völlig leer, d.h. enthält keine Steuerelemente mehr (weder Textfelder noch Befehlsschaltflächen etc.). In der Entwurfsansicht sind die Steuerelemente noch vorhanden.

Ursache

Fast immer ist dieses Verhalten "by Design". Die Ursache ist i.d.R., dass die zugrundeliegende Abfrage (eingetragen in der Eigenschaft Datensatzherkunft) keine Datensätze zurückliefert und in der Abfrage oder im Formular keine neuen Datensätze angelegt werden können (z.B. Formulareigenschaft Anfügen zulassen steht auf Nein).

Lösung

Entweder dafür sorgen, dass die Abfrage immer Datensätze liefert oder dass neue Datensätze angelegt werden können, also die Abfrage umbauen bzw. im Formular neue Datensätze zulassen.

Falls du bloß möchtest, dass zumindest deine Schaltflächen (z.B. zum Schließen des Formulares) sichtbar sind, reicht es, die Schaltflächen oder sonst. Steuerelemente in den Kopf- oder Fußbereich des Formulares zu verschieben. Komplett leer ist nämlich nur der Detailbereich.

Weitere Info: http://support.microsoft.com/?kbid=93261

nach oben

4.35 Schließen-Schaltfläche vermeiden in A97-Formular
http://www.donkarl.com?FAQ4.35

Problem

Du möchtest, dass ein Access-Formular keine eigene Schließen-Schaltfläche in seiner Titelleiste hat. Die entsprechende Eigenschaft für Formulare deaktiviert das Schließen-Symbol, wenn das Formular nicht maximiert ist. A97 hat aber den Bug, dass die Schließen-Schaltfläche des Formulars bei maximiertem Formularfenster wieder aktiviert ist. (in neueren Versionen ist das behoben)

Lösung

Wenn du nur das Schließen des Formulares verhindern möchtest, kannst du das Ereignis "Beim Entladen" des Formulares zum Abfangen verwenden (s. FAQ 1.12). Das hat den Vorteil, dass auch Windows-Tastenkombinationen wie <Strg>+<F4> und der Menübefehl zum Schließen des Fensters nicht mehr funktionieren.

Das Fehlverhalten von A97 ist hingegen nur per Windows-API zu verhindern. Das Code-Beispiel von Terry Kreft zeigt, wie man das Formular an die Größe des Access-MDI-Fensters anpassen kann, statt es maximiert zu öffnen:
http://www.mvps.org/access/api/api0022.htm

nach oben

4.36 Abhängige Kombi/Listenfelder
http://www.donkarl.com?FAQ4.36

Problem

Du hast in einem Formular 2 (oder mehr) Kombinations- oder Listenfelder und möchtest, dass der Inhalt des zweiten Kombis vom ersten abhängig ist, also nur mehr jene Datensätze anzeigt, für die im ersten die übergeordnete Kategorie gewählt wurde.

Lösung

Vorbemerkungen: Kombinationsfelder und Listenfelder sind diesbez. ident zu behandeln. Ich gehe auch nicht näher auf die Tabellenstruktur ein. Im Normalfall sollte es zwischen den involvierten Tabellen eine 1:n-Beziehung geben.

Angenommen du hast ein Formular "frm_Artikel" mit 2 Kombis. Eines "cbo_Gruppen" mit den Artikelgruppen, eines "cbo_Artikel" mit Artikeln. Nun möchtest du die Artikelgruppe auswählen und das zweite (abhängige) Kombi soll nur mehr jene Artikel zeigen, die dieser Gruppe angehören.

Enscheidend ist die Datensatzherkunft von cbo_Artikel.
Das kann eine gespeicherte Abfrage sein, in der beim GruppenID-Feld als Kriterium ein Bezug auf das übergeordnete Kombi steht:
Forms!frm_Artikel!cbo_Gruppen

Es kann aber auch ein SQL-Ausdruck sein, der in der Eigenschaft Datensatzherkunft des abhängigen Kombis steht oder der im Ereignis-Code Nach Aktualisierung des übergeordneten Kombis zugewiesen wird:

Me!cbo_Artikel.RowSource = "SELECT ArtikelBezeichnung FROM tbl_Artikel WHERE GruppenID= " & Me!cbo_Gruppen

Wenn die Datensatzherkunft des abhängigen Kombis nicht - wie im letzten Beispiel - dynamisch zugewiesen wird sondern z.B. eine gespeicherte Abfrage ist, dann muss noch die Anzeige aktualisiert werden. Dazu kannst du im Ereigniscode Nach Aktualisierung des übergeordneten Kombis die Requery-Methode verwenden:
Me!cbo_Artikel.Requery

Bei http://www.pc-creativ.de/ (unter "Tools) gibt es eine Beispiel-mdb "CreaKombi" von Anette Ratjen mit verschiedenen Varianten.

nach oben

4.37 Rechnen in Textfeldern
http://www.donkarl.com?FAQ4.37 aktualisiert 2007-01-03

Problem

Du möchtest in einem Textfeld eine Rechenformel eingeben, deren Ergebnis in einem anderen Textfeld erscheinen soll.

Lösung

Dafür lässt sich die Funktion Eval() verwenden. Angenommen das Textfeld heißt "txt_Formel" und das Ergebnisfeld "txt_Ergebnis". Im Steuerelementinhalt von txt_Ergebnis könnte dann stehen:

=Eval([txt_Formel])

Störend ist dabei oft, dass man für Eval den Punkt als Dezimaltrennzeichen verwenden muss. Wenn im Textfeld mit dem Komma gearbeitet werden soll, kann man es mit Stringfunktionen oder ab A00 mit Replace (wesentlich einfacher) für Eval austauschen. Der Ausdruck im Ergebnisfeld könnte dann z.B. lauten:

=Eval(Replace([txt_Formel];",";"."))

Das Ergebnis wird so nur im Steuerelement angezeigt. Falls es gespeichert werden soll s. Berechnetes Feld speichern.

nach oben

4.38 Datensatzwechsel per Tastatur verhindern
http://www.donkarl.com?FAQ4.38 aktualisiert 2007-01-03

Problem

Du möchtest verhindern, dass beim Drücken der Tabulator-, Enter- oder Pfeiltaste im ersten/letzten Steuerelement eines Datensatzes zum vorigen/nächsten Datensatz gewechselt wird.

Lösung

Stelle die Eigenschaft Zyklus des Formulares auf Aktueller Datensatz ein.

s.a. Tasten BildAuf/BildAb deaktivieren

nach oben

4.39 Laufende Nummer/Summe in Formularen
http://www.donkarl.com?FAQ4.39 aktualisiert 2016-09-06

Problem

Du möchtest in einem Formular ein Textfeld mit einer fortlaufenden Nummer oder fortlaufenden Summe haben.

Lösung

Laufende Nummer

Du kannst dafür eine vorbereitende Abfrage verwenden, die bereits die laufende Nummer erzeugt.
Eine andere Variante ist die Verwendung der AbsolutePosition-Eigenschaft des DAO-Recordsets. Kopiere dir dazu den folgenden Code in das Formularmodul:

'************* CODE START ************
Function FctNr()
'gibt eine laufende Nummer im Formular zurück
'Anzeige im Formular durch ein Feld mit Steuerelementinhalt: =FctNr()

  On Error GoTo FctNr_Error

  Me.RecordsetClone.Bookmark = Me.Bookmark
  FctNr = Me.RecordsetClone.AbsolutePosition + 1

FctNr_Exit:
  Exit Function

FctNr_Error:
  If Err.Number = 3021 Then FctNr = 0   'bei neuem DS
  Resume FctNr_Exit

End Function

'************* CODE ENDE ************

Laufende Summe

Dafür gibt's ebenfalls mehrere Varianten, z.B. per DAO-Programmierung
Laufende Summe im Formular
Laufende Summe im Formular mit etwas mehr Code

oder mithilfe der DSum-Funktion:
Laufende Summe im Formular mit DSum

nach oben

4.40 Mehrere markierte Datensätze ermitteln
http://www.donkarl.com?FAQ4.40

Problem

Du möchtest in einem Formular mehrere Datensätze markieren und dann per VBA ermitteln, welche markiert sind.

Lösung

Der Datensatzmarkierer von Access erlaubt nur eine zusammenhängende Markierung von Datensätzen. Die <Strg>-Taste hat hier nicht die sonst in Windows geltende Funktion einer getrennten Markierung. Wenn also mit dem Datensatzmarkierer mehrere DS markiert wurden, so kann man mithilfe der Seltop- und Selheight-Eigenschaften des Formulares eruieren, welche DS markiert sind. Ausführliche Beispiele dazu bieten folgende KB-Artikel:

http://support.microsoft.com/?kbid=294202
http://support.microsoft.com/default.aspx?scid=kb;de;D43397

Wenn es um die Markierung von Datensätzen geht, die sich nicht unmittelbar untereinander befinden, ist der übliche Workaround die Verwendung eines gebundenen Kontrollkästchens, das dann in jedem DS gesetzt werden muss und z.B. mit einer Aktualisierungsabfrage wieder in einem Rutsch zurückgesetzt wird. Eine andere Variante ist die Verwendung eines Listenfeldes, bei dem die Eigenschaft Mehrfachauswahl auf Erweitert eingestellt ist.

nach oben

4.41 Textfeld zur Passwort-Eingabe
http://www.donkarl.com?FAQ4.41 aktualisiert 2011-04-28

Problem

Du möchtest ein Textfeld für eine Passwort-Eingabe verwenden, d.h. man soll beim Tippen nur die üblichen Sternchen sehen.

Lösung

Setze die Eigenschaft Eingabeformat des Textfeldes auf: Kennwort

Zwei Anmerkungen zu diesem Themenbereich:

- Eine häufige Frage ist, ob das auch mit VBA-Inputboxen geht.
Antwort: Nein, man braucht ein Textfeld in einem Formular.

- Wenn sich der Cursor in dem Kennwort-Textfeld befindet und mit <F7> oder per Menüpunkt/Ribbon die Rechtschreibprüfung aktiviert wird, erscheint der eingegebene Text im Rechtschreibdialog in Klarschrift. Falls das ein Problem darstellt, sollte man die Funktionstaste deaktivieren (in den Starteigenschaften oder per Tastaturmakro) und den Menü- bzw. Ribboneintrag ausblenden.

nach oben