Objektpositionen speichern und wiederherstellen

Neulich fragte ein Leser, ob und wie man die Position von Objekten im Access-Fenster speichern und wiederherstellen könne. Der Hintergrund ist, dass er immer wieder mühsam Tabellen, Abfragen und andere Objekte zu einem Arbeitsbereich zusammengestellt hat und wenn er die Anwendung schließt, ist die ganze Arbeit dahin – und am nächsten Tag muss er die Objekte erneut anordnen. Ich fühlte mich ein wenig an Zeiten erinnert, wo man zwar einen Homecomputer zum Programmieren, aber kein Gerät zum Speichern der eingetippten Spiele aus den Computermagazinen hatte … Da sich die Zeiten zum Glück geändert haben, zeige ich in diesem Beitrag, wie Sie die Position und Größe der beim Schließen einer Datenbank geöffneten Objekte abspeichern und beim nächsten Öffnen wieder herstellen können.

Aufgabenstellung

Aus den Anforderungen des Lesers ergeben sich die folgenden Aufgabenstellungen:

  • Herausfinden, wie wir die Position und Größe aller zu einem bestimmten Zeitpunkt geöffneten Objekte ermitteln können
  • Definieren einer Tabelle zum Speichern der geöffneten Objekte mit Name und Objekttyp und ihrer Position und Größe sowie der aktuellen Ansicht
  • Prozedur zum Speichern dieser Informationen in einer geeigneten Tabelle in der jeweilige Datenbankanwendung
  • Herausfinden, wie wir die abgespeicherten Objekte wieder öffnen und die Position und die Größe zu einem bestimmten Zeitpunkt wiederherstellen können
  • Festlegen eines Automatismus, die Position und Größe der Objekte beim Schließen der Datenbank zu speichern.
  • Festlegen eines weiteren Automatismus, um die Position und Größe bei Öffnen der Datenbankanwendung wiederherzustellen

Größe und Position der geöffneten Objekte ermitteln

Die erste Aufgabe ist bereits die anspruchsvollste: Wie können wir alle geöffneten Objekte ermitteln und wie finden wir die aktuelle Position und Größe dieser Objekte heraus?

Für diese Aufgabe gibt es keine Lösung, mit der wir alle Objekte gleichermaßen behandeln können. So gibt es zwar Auflistungen namens Forms und Reports, mit denen direkt auf die aktuell geöffneten Formulare und Berichte zugegriffen werden kann.

Entsprechende Auflistungen für Tabellen und Abfragen beispielsweise namens Tables oder Queries suchen wir jedoch vergeblich.

Wenn wir jedoch nach diesen Schlüsselwörtern im Objektkatalog des VBA-Editors suchen, finden wir schnell passende Einträge, nämlich AllTables und AllQueries (siehe Bild 1).

Finden von geeigneten Auflistungen für den Zugriff auf Tabellen und Abfragen

Bild 1: Finden von geeigneten Auflistungen für den Zugriff auf Tabellen und Abfragen

Damit haben wir zumindest schon einmal Auflistungen für alle Objekttypen gefunden – nun schauen wir uns an, wie wir an die jeweils gewünschten Informationen wie Name, aktuelle Ansicht, Position vom linken und oberen Rand, Höhe und Breite gelangen.

Formulare und Berichte analysieren

Bei Formularen und Berichten macht Access es uns ein wenig leichter als bei Tabellen und Abfragen, die wir uns im Anschluss anschauen. Mit der Forms– und der Reports-Auflistung können wir direkt die aktuell geöffneten Objekte referenzieren. Mit der folgenden Prozedur durchlaufen wir beispielsweise alle Formulare, die aktuell geöffnet sind:

Public Sub Formulare()
     Dim frm As Form
     For Each frm In Forms
         Debug.Print frm.Name,  frm.WindowLeft, frm.WindowTop,  frm.WindowWidth, frm.WindowHeight
     Next frm
End Sub

Die Werte der Eigenschaften WindowLeft, WindowTop, WindowWidth und WindowHeight liefert Access in der Einheit Twips. Vorneweg: Diese Eigenschaften sind schreibgeschützt und wir können diese später nicht nutzen, um die Größe und die Position der Formulare und Berichte wiederherzustellen. Allerdings arbeitet auch die Methode, die wir dazu später nutzen werden, mit Angaben in dieser Einheit. Daher verzichten wir an dieser Stelle auf eine Beschreibung, was Twips genau sind.

Den Namen des jeweiligen Formulars oder Berichts lesen wir einfach aus der Eigenschaft Name aus. Spannend ist nun noch, die aktuelle Ansicht zu ermitteln.

Formulare können in den Ansichten Einzelnes Formular, Endlosformular, Datenblatt oder Geteiltes Formular angezeigt werden (siehe Bild 2). Bei Berichten kommen noch die Ansichten Berichtssicht und Seitenansicht hinzu.

Mögliche Ansichten für ein Formular

Bild 2: Mögliche Ansichten für ein Formular

Diese Eigenschaft können wir per VBA einerseits über CurrentView ermitteln. CurrentView liefert die folgenden Werte:

  • 0 (acCurViewDesign): Entwurfsansicht
  • 1 (acCurViewFormBrowse): Formularansicht
  • 2 (acCurViewDatasheet): Datenblattansicht
  • 5 (acCurViewPreview): Seitenansicht (bei Berichten)
  • 6 (acCurViewReportBrowse): Berichtssicht (bei Berichten)
  • 7 (acCurViewLayout): Layoutansicht

Aber Moment – das sind ja gar nicht die Werte, die wir für die Eigenschaft Standardansicht aus dem Eigenschaftenblatt auswählen können. Diese können wir der VBA-Eigenschaft DefaultView eines Form-Objekts entnehmen und die Werte stimmen nicht mit den Zahlenwerten für die Eigenschaft CurrentView überein.

Im Gegenteil – es gibt sogar für Formulare und Berichte teilweise gleiche Werte mit unterschiedlicher Bedeutung:

  • 0: Einzelnes Formular
  • 1: Endlosformular
  • 2: Datenblatt
  • 3: PivotTable
  • 4: PivotChart
  • 5: Geteiltes Formular

Für Berichte gibt es die folgenden beiden Werte:

  • 0: Seitenansicht
  • 1: Berichtsansicht

Wie aber kommen wir an die aktuelle Ansicht? Immerhin kann der Benutzer diese ja, wenn die möglichen Ansichten nicht auf eine Ansicht eingeschränkt ist, wechseln. Daher verwenden wir die Eigenschaft CurrentView, um die aktuelle Ansicht zu ermitteln.

Tabellen und Abfragen analysieren

Etwas komplizierter wird die Analyse bei Tabellen und Abfragen. Wie bereits erwähnt, gibt es keine Auflistung, die alle derzeit geöffneten Tabellen oder Abfragen auflistet.

Also schauen wir, was wir mit den beiden Auflistungen AllTables und AllQueries, die wir weiter oben im Objektkatalog gefunden haben, für unsere Zwecke nutzen können.

Um diese Auflistungen zu durchlaufen, wollen wir zunächst herausfinden, welchen Datentyp die damit referenzierten Elemente überhaupt aufweisen. Dazu greifen wir einfach auf das erste Element einer solchen Auflistung zu und lassen uns den Objekttyp mit der Funktion Typename im Direktbereich ausgeben:

  Typename(CurrentData.AllTables(0))
AccessObject

Jetzt, da wir den Objekttypen kennen, können wir die Elemente direkt in einer For Each-Schleife durchlaufen und auch per IntelliSense auf die Eigenschaften der Elemente zugreifen (siehe Bild 3).

Erkunden der Eigenschaften von AccessObject-Elementen

Bild 3: Erkunden der Eigenschaften von AccessObject-Elementen

Um herauszufinden, welche Objekte geöffnet sind und in welcher Ansicht sie dann angezeigt werden, verwenden wir die folgende Prozedur:

Public Sub GeoeffneteTabellenDurchlaufen()
     Dim objTable As AccessObject
     For Each objTable In CurrentData.AllTables
         Debug.Print objTable.Name;
         If objTable.IsLoaded Then
             Debug.Print objTable.CurrentView
         Else
             Debug.Print
         End If
     Next objTable
End Sub

Damit erhalten wir beispielsweise folgendes Ergebnis, wenn die beiden Tabellen tblObjecttypes und tblTest in der Datenblattansicht und die Tabelle tblObjects in der Entwurfsansicht geöffnet sind:

MSysAccessStorage
MSysACEs
... weitere nicht geöffnete Systemtabellen
MSysRelationships
MSysResources
tblObjects 0 
tblObjecttypes 2 
tblTest 2 

Interessant sind für Tabellen die folgenden Ansichten:

  • 0: Entwurfsansicht
  • 2: Datenblattansicht

Abfragen durchlaufen wir auf ähnliche Weise – wir verwenden hier lediglich die Auflistung AllQueries:

Public Sub GeoeffneteAbfragenDurchlaufen()
     Dim objQuery As AccessObject
     For Each objQuery In CurrentData.AllQueries
         Debug.Print objQuery.Name;
         If objQuery.IsLoaded Then
             Debug.Print objQuery.CurrentView
         Else
             Debug.Print
         End If
     Next objQuery
End Sub

Interessant ist hier, dass es eigentlich noch eine weitere Ansicht gibt, nämlich die SQL-Ansicht (siehe Bild 4). Wenn wir eine Abfrage in dieser Ansicht öffnen und die Prozedur GeoeffneteAbfrageDurchlaufen starten, gibt diese ebenfalls den Wert 0 für die Eigenschaft CurrentView zurück.

Die SQL-Ansicht einer Abfrage

Bild 4: Die SQL-Ansicht einer Abfrage

Davon ausgehend, dass der Benutzer nicht den Zustand von in der SQL-Ansicht geöffneten Abfragen speichern möchte, stellt das aber auch im Rahmen dieses Beitrags kein Problem dar.

Position und Größe von Tabellen und Abfragen ermitteln

Nachdem wir die Größe und Position von Formularen und Berichten direkt über die Eigenschaften der Form– beziehungsweise Report-Objekte ermitteln können, schauen wir uns nun die Tabellen und Abfragen an. Da das AccessObject-Element keine diesbezüglichen Eigenschaften offeriert, müssen wir einen kleinen Umweg gehen, um die Informationen zu beschaffen.

Ausgehend davon, dass wir ohnehin nur geöffnete Elemente verwenden wollen, können wir dann das Screen-Objekt nutzen, welches uns Informationen über die jeweils aktiven Objekte liefert, also die Objekte, die aktuell den Fokus besitzen. Mit dem Screen-Objekt können wir über die folgenden Eigenschaften auf die jeweiligen Objekte zugreifen:

  • Screen.ActiveDatasheet: Aktive Tabellen und Abfragen in der Datenblattansicht
  • Screen.ActiveForm: Aktives Formular
  • Screen.ActiveReport: Aktiver Bericht

Hier sehen wir also eine weitere Einschränkung bezüglich der Ansichten, die wir beim Speichern von Position und Größe berücksichtigen können: Die Entwurfsansicht von Tabellen oder Abfragen fällt weg, da wir diese nicht mit den Active…-Eigenschaften referenzieren können.

Die Eigenschaft ActiveDatasheet liefert tatsächlich nur einen Objektverweis zurück, wenn aktuell eine Tabelle oder Abfrage in der Datenblattansicht geöffnet ist. Aber auch das ist kein Problem, zumindest nicht gemessen an dem Wunsch des Lesers, die Position und Größe von in der Datenblattansicht geöffneten Elementen zu ermitteln und zu speichern.

Allerdings hilft uns Screen.ActiveDatasheet noch nicht weiter, wenn das Objekt, das wir untersuchen wollen, nicht den Fokus hat. Deshalb müssen wir, bevor wir auf eine geöffnete Tabelle in der Datenblattansicht zugreifen wollen, zunächst den Fokus auf diese Tabelle verschieben. Dass sie überhaupt geöffnet ist, können wir voraussetzen, denn wir wollen ja nur die Position und Größe von Tabellen ermitteln, die derzeit im Arbeitsbereich sichtbar sind.

Den Namen der zu untersuchenden Tabelle kennen wir über die Name-Eigenschaft auch. Also können wir die DoCmd.SelectObject-Methode nutzen, um die zu untersuchende Tabelle oder Abfrage in den Fokus zu setzen – beispielsweise so:

DoCmd.SelectObject acTable, objTable.Name

Tabelle zum Speichern der Objekteigenschaften

Als Nächstes erstellen wir die Tabelle, in der wir die Größe, Position und Ansicht der aktuell geöffneten Objekte speichern wollen.

Welche Informationen wir speichern wollen, haben wir bereits ausführlich besprochen, daher hier nur der Verweis auf den Entwurf der Tabelle tblObjects in Bild 5.

Tabelle zum Speichern der Objekteigenschaften

Bild 5: Tabelle zum Speichern der Objekteigenschaften

Außerdem noch die Information, dass wir den Typ des jeweiligen Objekts im Feld Objecttype als Zahlenwert speichern und dabei auf die folgenden Werte zurückgreifen:

  • 0: acTable (Tabelle)
  • 1: acQuery (Abfrage)
  • 2: acForm (Formular)
  • 3: acReport (Bericht)

Den Wert für das Feld ObjectView wählen wir wie von der Eigenschaft CurrentView geliefert.

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar