Formulareigenschaften global ändern

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).

Per VBA-Code eingestellte Eigenschaft

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

Access im Unternehmen

Unser exklusives Angebot für Dich!

Access im Unternehmen
13,25 € im Monat*

(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.

PayPal VISA Mastercard SEPA
Kostenlos & unverbindlich

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 →