Mit „AllowZooming“ und „ZoomResizesWindow“ hat Microsoft zwei Formulareigenschaften eingeführt, die sich ausschließlich über die Properties-Auflistung ansprechen lassen – und das auch nur, wenn das Formular in der Entwurfsansicht geöffnet ist. Wer diese Eigenschaften für eine gewachsene Anwendung mit einigen Dutzend Formularen einstellen möchte, hat stumpfe Fleißarbeit vor sich. Ein guter Anlass, sich ein Werkzeug zu bauen, das beliebige Eigenschaften für alle Formulare und Berichte einer Anwendung ausliest, sichert und setzt. Dieser Beitrag zeigt, wie das gelingt – und wofür sich so ein Werkzeug jenseits der Zoom-Funktion noch alles einsetzen lässt.
Wofür braucht man so etwas?
Die neuen Zoom-Eigenschaften, auf die wir im Beitrag Zoomen in Access, Teil 2 (www.access-im-unternehmen.de/1614) eingehen, sind nur der aktuelle Anlassfall. Wenn Sie einmal darüber nachdenken, welche Einstellungen in einer Anwendung eigentlich für alle Formulare gleich sein sollten, kommt schnell eine ansehnliche Liste zusammen:
- Neue Eigenschaften nachrüsten, die Microsoft ergänzt hat – neben den Zoom-Eigenschaften etwa die angekündigte Eigenschaft für abgerundete Ecken
- Ein einheitliches Erscheinungsbild herstellen: Datensatzmarkierer, Navigationsschaltflächen, Bildlaufleisten, Rahmenart und Trennlinien
- Von überlappenden Fenstern auf Registerkarten umstellen – dabei müssen Popup, Modal, AutoCenter und die Rahmenart bei jedem Formular angefasst werden
- Nach dem Umstieg auf ein SQL Server-Backend die Datensatzsperrung und den Recordset-Typ anpassen
- Eine Anwendung vor der Auslieferung härten: Kontextmenüs abschalten, Filter sperren, Entwurfsänderungen unterbinden
- Aus einer Vollversion eine Nur-Lese-Variante erzeugen, indem AllowEdits, AllowAdditions und AllowDeletions flächendeckend abgeschaltet werden
- Gespeicherte Filter und Sortierungen aufspüren: FilterOnLoad und OrderByOnLoad schleichen sich beim Entwickeln ein und sorgen beim Kunden für leere oder quälend langsame Formulare
Der letzte Punkt zeigt schon, dass wir nicht nur schreiben, sondern auch lesen wollen. Ein Werkzeug, das uns erst einmal auflistet, wie die Dinge stehen, ist oft nützlicher als eines, das blind überall den gleichen Wert einträgt.
Das Grundmuster
Der Ablauf ist bei allen Eigenschaften derselbe: Formular in der Entwurfsansicht öffnen, Eigenschaft setzen, Formular speichern und schließen. In der einfachsten Form sieht das aus wie in Listing 1.
Public Sub ZoomResizesWindowSetzen(ByVal blnWert As Boolean) Dim strFormular As String Dim i As Long For i = 0 To CurrentProject.AllForms.Count - 1 strFormular = CurrentProject.AllForms(i).Name DoCmd.OpenForm strFormular, acDesign, , , , acHidden Forms(strFormular).Properties("ZoomResizesWindow") = blnWert DoCmd.Close acForm, strFormular, acSaveYes Next i End Sub
Listing 1: Das Grundmuster in seiner einfachsten Form
Die Schleife läuft über die Auflistung AllForms des CurrentProject-Objekts. Diese enthält alle Formulare der Anwendung – im Gegensatz zur Auflistung Forms, die nur die aktuell geöffneten Formulare liefert.
Der Parameter acHidden sorgt dafür, dass das Formular unsichtbar geöffnet wird, was den Vorgang deutlich beschleunigt.
Rufen wir diese Prozedur wie folgt auf, finden wir im Eigenschaftenfenster aller Formulare nun den neuen Wert für die Eigenschaft Zoom ändert die Fenstergröße vor (siehe Bild 1).

Bild 1: Per VBA-Code eingestellte Eigenschaft
Warum über die Properties-Auflistung?
Die meisten Formulareigenschaften lassen sich direkt ansprechen, etwa mit Me.AllowEdits = False. Bei neu hinzugekommenen Eigenschaften funktioniert das jedoch meist nicht: Sie sind noch nicht im Objektmodell hinterlegt, sodass der Compiler den Ausdruck bereits beim Übersetzen bemängelt.
Das ist auch bei einigen älteren Eigenschaften der Fall. Der Umweg über die Properties-Auflistung löst das Problem, weil der Eigenschaftsname dort als Zeichenkette übergeben wird und erst zur Laufzeit ausgewertet wird.
Genau daraus ergibt sich aber auch die erste Fehlerquelle. Läuft die Anwendung unter einer älteren Access-Version, in der es die Eigenschaft noch gar nicht gibt, quittiert Access den Zugriff mit dem Laufzeitfehler 3270 (Eigenschaft nicht gefunden) beziehungsweise mit Fehler 2455.
Da unsere Schleife dann mittendrin abbricht, bleibt womöglich ein Formular in der Entwurfsansicht offen zurück.
Weitere Schwachstellen des einfachen Musters:
- Ist ein Formular bereits geöffnet, schlägt das Öffnen in der Entwurfsansicht fehl.
- Der Bildschirm flackert während des gesamten Durchlaufs.
- Es gibt keine Möglichkeit, einzelne Formulare auszunehmen.
- Die alten Werte sind unwiederbringlich verloren.
Diese vier Punkte arbeiten wir nun der Reihe nach ab.
Eine Eigenschaft für ein Formular setzen
Zunächst kapseln wir den Vorgang für ein einzelnes Formular in einer eigenen Funktion. Sie liefert 0 zurück, wenn alles geklappt hat, und andernfalls die Fehlernummer.
Wichtig ist der Fehlerbehandler: Er schließt das Formular ohne zu speichern, damit kein halb bearbeiteter Entwurf zurückbleibt (siehe Listing 2).
Private Function EigenschaftSetzen(ByVal strFormular As String, ByVal strEigenschaft As String, _ ByVal varWert As Variant) As Long On Error GoTo Fehler DoCmd.OpenForm strFormular, acDesign, , , , acHidden Forms(strFormular).Properties(strEigenschaft) = varWert DoCmd.Close acForm, strFormular, acSaveYes Exit Function Fehler: EigenschaftSetzen = Err.Number On Error Resume Next DoCmd.Close acForm, strFormular, acSaveNo End Function
Listing 2: Setzen einer Eigenschaft mit Fehlerbehandlung
Der Durchlauf über alle Formulare
Darauf setzt die eigentliche Hauptprozedur auf. Sie erwartet den Eigenschaftsnamen, den gewünschten Wert und optional eine durch Semikolon getrennte Liste von Formularen, die übersprungen werden sollen.
Zurückgeliefert wird die Anzahl der geänderten Formulare – Listing 3 zeigt den Code.
Public Function EigenschaftFuerAlleFormulare(ByVal strEigenschaft As String, ByVal varWert As Variant, _ Optional ByVal strAusnahmen As String = "") As Long Dim strFormular As String Dim lngFehler As Long Dim lngGeaendert As Long Dim i As Long On Error GoTo Fehler Application.Echo False For i = 0 To CurrentProject.AllForms.Count - 1 strFormular = CurrentProject.AllForms(i).Name ' Statusleiste aktualisieren Application.Echo True, "Bearbeite " & strFormular & " ..." DoEvents Application.Echo False If Not IstInListe(strFormular, strAusnahmen) Then If CurrentProject.AllForms(i).IsLoaded Then DoCmd.Close acForm, strFormular, acSaveYes End If lngFehler = EigenschaftSetzen(strFormular, strEigenschaft, varWert) If lngFehler = 0 Then lngGeaendert = lngGeaendert + 1 Else Debug.Print "Fehler " & lngFehler & " bei " & strFormular End If End If Next i Ende: Application.Echo True EigenschaftFuerAlleFormulare = lngGeaendert Exit Function Fehler: MsgBox "Fehler " & Err.Number & ": " & _ Err.Description, vbExclamation Resume Ende End Function
Listing 3: Die Hauptprozedur mit Ausnahmeliste und Fortschrittsanzeige
Application.Echo False unterdrückt die Bildschirmaktualisierung – ohne diese Zeile flackert der Bildschirm während des gesamten Durchlaufs. Entscheidend ist, dass Echo in jedem Fall wieder eingeschaltet wird, auch im Fehlerfall; genau dafür sorgt die Sprungmarke Ende in Verbindung mit Resume Ende.
Die drei Zeilen zur Statusleiste innerhalb der Schleife sehen umständlich aus, sind aber nötig. Der naheliegende Aufruf SysCmd acSysCmdSetStatus bleibt bei abgeschalteter Bildschirmaktualisierung wirkungslos, weil Access die Statusleiste dann ebenfalls nicht neu zeichnet.
Der zweite Parameter von Application.Echo setzt dagegen den Text der Statusleiste, und das kurze Einschalten erzwingt genau eine Aktualisierung. DoEvents lässt sie durch, danach geht die Anzeige wieder aus. Weil die Formulare ohnehin unsichtbar geöffnet werden, ist von diesem Umschalten auf dem Bildschirm nichts zu sehen.
Aus demselben Grund braucht es am Ende kein SysCmd acSysCmdClearStatus: Das abschließende Application.Echo True ohne Textparameter setzt die Statusleiste selbst wieder zurück.
Die Abfrage von IsLoaded schließt ein bereits geöffnetes Formular, bevor wir es in der Entwurfsansicht öffnen.
Die Hilfsfunktion zum Prüfen der Ausnahmeliste fällt kurz aus. Indem wir sowohl die Liste als auch den Suchwert in Semikola einfassen, verhindern wir, dass frmKunde auch frmKundeDetail trifft:
Private Function IstInListe( _ ByVal strWert As String, _ ByVal strListe As String) As Boolean IstInListe = InStr(1, ";" & strListe & ";", _ ";" & strWert & ";", vbTextCompare) \> 0 End Function
Der Aufruf sieht dann zum Beispiel so aus, wobei zwei Formulare unangetastet bleiben sollen:
Debug.Print EigenschaftFuerAlleFormulare( _
"ZoomResizesWindow", True, _
"frmIntro;frmEigenschaften")
Erst sichern, dann ändern
Unser exklusives Angebot für Dich!
(Gilt für den Abschluss eines Jahres-Abonnements im ersten Jahr, danach 189,-/Jahr)
Hier geht’s weiter →Die ersten 4 Wochen kostenlos testen – voller Zugriff auf alle Artikel, vollständigen Code und Beispieldatenbanken. Kein Risiko: Wenn es nicht passt, kündigst Du einfach innerhalb der ersten vier Wochen.
Hast Du eine konkrete Frage zu Deiner eigenen Access-Anwendung?
Vielleicht stellt Deine Anwendung Dich vor eine Herausforderung, zu der Du bisher keine Lösung findest. Schlechte Performance, kein ausreichender Zugriffsschutz, Du bist unsicher über Dein Datenmodell oder Dein Code liefert unerklärliche Fehler?
In unserem kostenlosen Access-Audit schaut sich André Minhorst persönlich gemeinsam mit Dir Deine Lösung per Zoom an – und zeigt Dir, wo Datenmodell, VBA-Code, Ergonomie und Sicherheit Optimierungspotenzial bieten.
Jetzt kostenloses Access-Audit anfordern →