Wie kann mit VBA festgestellt werden, ob ein Formular/Report einen gewissen Bereich (z.B. Formularkopf) enthält?
Bei der Programmierung innerhalb eines Formulars, stellt sich nicht wirklich die Frage, den es ist ja bekannt was im aktuellen Formular an Bereichen eingerichtet ist und was nicht.
Bei der Programmierung einer allgemeinen Formularübergreifenden Prozedur, ist der Prozedur dies jedoch nicht bekannt, und da stellt sich sehr wohl die Frage, ob eine gewisse Section (Bereich) vorhanden ist oder nicht.
Dazu müssten wir eigentlich nur die VBA Auflistung Section befragen.
Doch Leider gibt es nicht solch eine Auflistung für dieses Objekt :-(
Also schreiben wir uns einfach eine Globale-Funktion die diesen Job für uns erledigt:
Public Function SectionExists(FormReportOBJ As Object, SectionIndex As AcSection _
, Optional ByRef SectionOBJ As Section) As Boolean
On Error Resume Next
Set SectionOBJ = FormReportOBJ.Section(SectionIndex)
SectionExists = (Err.Number = 0)
End Function
Hinweis: Das Objekt Section stellt uns leider nicht die Information zur Verfügung, wie viel Sections vorhanden sind. Somit bleibt uns nichts anderes übrig, als dies mit der Fehlerabfangmethode zu lösen. Nicht elegant, aber es funktioniert ;-)
Andere Fehler haben wir nicht zu erwarten, so dass hier keine weitere Fehlerbehandlung benötigt wird.
Und so kann jetzt unsere Funktion angewandt werden:
Private Sub Form_Load()
Dim SectionOBJ As Section
If SectionExists(Me, acHeader, SectionOBJ) Then
SectionOBJ.BackColor = RGB(255, 0, 0) 'Farbe Rot
End If
End Sub
Erläuterung: Bei Laden des Formulars wird geprüft ob das aktuelle Formular (ME) einen Formularkopf enthält. Wenn dies der Fall ist, liefert unsere Prüf-Funktion SectionExists() den Wert True zurück und die abgefragte Section wird mit der Hintergrundfarbe Rot versehen. Die Variable SectionOBJ ist übrigens per Referenz-Übergabe in der Funktionsprozedur SectionExists() gesetzt worden.
Wenn wir schon dabei sind, mit der gleichen Technik schreiben wir uns noch eine Funktion, die uns die Anzahl der vorhandenen Sections zurück liefert:
Public Function SectionsCount(FormReportOBJ As Object) As Byte
Dim i As Byte, SectionOBJ As Section
On Error Resume Next
For i = 0 To 255
Set SectionOBJ = FormReportOBJ.Section(i)
If Not Err.Number = 0 Then Exit For
Next
SectionsCount = i
End Function
Dies kann z.B. interessant sein, wenn per VBA alle Sections im Formular mit einer Farbe versehen werden soll. Und so geht's:
Private Sub Form_Load()
Dim i As Byte
For i = 0 To SectionsCount(Me)-1
me.Section(i).BackColor = RGB(255, 0, 0) 'Farbe Rot
Next
End Function
Das ganze funktioniert auch mit Berichten. Gerade diese haben durchaus noch weitere Bereiche wie acGroupLevel1Footer, acGroupLevel2Footer usw...
Tipps und Tricks für Microsoft® Office insbesondere Access und Excel VBA-Programmierung und Funktionen
Translate
Montag, 19. Dezember 2016
Freitag, 21. Oktober 2016
WORD Add-In: Funktionalitäten automatisch ausführen sobald ein beliebiges Dokument geöffnet wird
Kürzlich kam die Anforderung auf, das jedes Dokument was geöffnet wird,
standardmäßig immer auf 160% automatisch gezoomt werden soll.
Nun ich habe leider keine Einstelloption in Word gefunden, daher habe
ich mir kurzerhand ein Add-in geschrieben, welches genau diese (oder auch
andere) Aufgabe übernimmt.
Mein erstelltes Add-in kann hier heruntergeladen werden.
Die Datei DefaultFunctions.dotm
muss nun einfach in den AutoStart-Ordner
von Word gespeichert werden. Dieser müsste standardmäßig der folgende sein:
C:\Users\username\AppData\Roaming\Microsoft\Word\STARTUP
C:\Users\username\AppData\Roaming\Microsoft\Word\STARTUP
Alternativ kann dieser in Word in den Optionen nachgeschaut werden:
Datei/Optionen/Erweitert/Dateispeicherorte…/AutoStart/Ändern
Datei/Optionen/Erweitert/Dateispeicherorte…/AutoStart/Ändern
Jetzt noch Word einmal schließen und neu Starten und schon sollte die
Funktionalität aktiv sein.
Die Technik dahinter:
Die Datei DefaultFunctions.dotm
wird automatisch geöffnet, sobald Word gestartet wurde, da sie sich ja im AutoStart-Ordner befindet.
In dieser Datei befindet sich eine AutoExec-Prozedur, die (wie der
Name es schon ausdrückt) automatisch ausgeführt wird, sobald die Datei geöffnet
wurde.
In dieser Prozedur wird eine Klasse instanziiert, welche die Aufgabe
hat, die Ereignisse von Word abzufangen und dann dort was zu machen. Uns
interessiert hier das Ereignis DocumentOpen,
welches ausgelöst wird, sobald eine Datei in Word geöffnet wurde.
Hier der Code dazu:
Option ExplicitConst ZoomPercentage As Long = 160
Private cWatcher As clsWatchWD 'Hier wird die Klasse im Speicher gehalten
Public Sub AutoExec()
'Diese Prozedur wird automatisch nach dem Öffnen ausgeführt
Set cWatcher = New clsWatchWD 'Die Klasse wird instanziiert, somit werden die Ereignisse der aktuellen Word-Instanz in dieser abgefangen (siehe Klasse)
cWatcher.SetZoomPercentage = ZoomPercentage 'des Wertes für den Zoomfaktor
End Sub
Hier der Code von unserer Klasse clsWatchWD, die den
eigentlich Job macht:
Option ExplicitPrivate WithEvents cWD As Word.Application 'Durch WithEvents erhalten wir eine ereignisfähige Objektvariable
Dim cZoomPercentage As
Long
Public Property Let SetZoomPercentage(T As Long)
cZoomPercentage = T
'Übergabe des Wertes für den ZoomfaktorEnd Property
Private Sub Class_Initialize()
'Beim instanziieren der Klasse, wird diese Prozedur automatisch
ausgeführtSet cWD = Application 'Die aktuelle Word-instanz wird in der Ereignisfähigen Objektvariable cWD gespeichert
End Sub
Private Sub cWD_DocumentOpen(ByVal Doc As Document)
'Diese Ereignis-Prozedur wird automatisch ausgeführt, nach dem
ein Dokument geöffnet wurde'Die Variable Doc verweis auf das gerade geöffnete Dokument
'Diese Prozedur kann mit weiteren gewünschten Befehlen erweitert werden...
With Doc
'Dieser Abschnitt stellt die Ansicht auf Seitenlayout um, falls dies nicht der Fall sein sollte
If .ActiveWindow.View.SplitSpecial = wdPaneNone Then
.ActiveWindow.ActivePane.View.Type = wdPrintView
Else
.ActiveWindow.View.Type = wdPrintView
End If
'Hier wird das aktuelle Fenster auf den gewünschten Wert gezoomt
.ActiveWindow.ActivePane.View.Zoom.Percentage = cZoomPercentage
End With
End Sub
Der Code kann in der Datei eingesehen und angepasst werden, dazu die Datei nicht
direkt öffnen, sondern aus dem Windows Explorer mit rechter maustaste und
Befehle Öffnen laden.
Mit der bekannten Tastenkombi ALT+F11 wird in den VBA-Editor gewechselt und der Code kann eingesehen und geändert werden.
In der Klasse können noch weitere Ereignis-Prozeduren angelegt werden,
je nach Wunsch. z.B. Newdocument,
wenn nach dem Erstellen eines neuen Dokumentes was passieren soll.
Oder DocumentBeforeClose,
wenn beim Schließen eines Dokumentes was passieren soll, usw...
Dienstag, 14. Juli 2015
Mit Klasse die Access-Gültigkeitsmeldung bei erforderlichen Felder verbessern
Aufgabe 1: Umgang mit erforderlichen Feldern
Enthält eine Tabelle erforderlichen Felder, werden diese erst beim speichern des Datensatzes mit folgender Access-System-Meldung angefordert:
Diese Standard-Meldung ist bescheiden und lässt sich nicht beeinflussen.
Des Weiteren kommt jeweils eine Meldung für jedes einzelne erforderliche Feld, was nicht sehr Anwenderfreundlich ist.
Abhilfe Schaft hier ein VBA-Code, der über das Form-Event BeforeUpdate diesen Fall abfängt, um eine selbstdefinierte Meldung erscheinen zu lassen.
Selbstverständlich möchten wir nun diesen Anwenderfreundliche "Service" in sämtlichen Formularen zur Verfügung stellen.
Es liegt nah den VBA-Code unter BeforeUpdate in die anderen Formularen zu kopieren, mit Anpassung der erforderlichen Felder. Programm-Code der letztendlich dasselbe macht x-mal zu kopieren zeugte schon immer von schlechter Codierung. Hinzu kommt das in gewissen Formularen, die Event Prozedur BeforeUpdate bereits VBA-Code für andere Anforderungen enthält. Also können wir in diesen Fällen den Code nicht einfach 1:1 übertragen.
Daher ist die Idee entstanden den VBA-Code inkl. dem Form-Event BeforeUpdate in einer Klasse auszulagern. Somit muss in den Formularen lediglich die Klasse instanziiert werden, mit Übergabe der gewünschten erforderlichen Felder. Der VBA-Code selbst, der die Funktionalität umsetzt, steht somit nur einmalig in einem Klassenmodul.
Aufgabe 2: Formulare sollen mit den Schaltflächen
OK/Abbrechen/Übernehmen versehen werden
Die Schaltfläche 'OK' soll den aktuellen Datensatz speichern und das Formular schliessen.
Die Schaltfläche 'Abbrechen' soll den aktuellen Datensatz verwerfen (mit Rückfrage, falls erforderlich) und das Formular schließen.
Die Schaltfläche 'Übernehmen' soll den aktuellen Datensatz speichern und dabei nur aktiv sein, wenn der Datensatz sich im Änderungsmodus befindet.
Auch hier sollte der VBA-Code und die diversen Event-Prozeduren die dazu nötig sind nicht in den Formularen vervielfältigt werden.
Diese passen Thematisch sehr gut in unsere Klasse mit der Gültigkeitsprüfung, also lagern wir den VBA-Code mit den Form-/Button-Events auch in dieser Klasse aus.
Die Schaltfläche 'Abbrechen' soll den aktuellen Datensatz verwerfen (mit Rückfrage, falls erforderlich) und das Formular schließen.
Die Schaltfläche 'Übernehmen' soll den aktuellen Datensatz speichern und dabei nur aktiv sein, wenn der Datensatz sich im Änderungsmodus befindet.
Auch hier sollte der VBA-Code und die diversen Event-Prozeduren die dazu nötig sind nicht in den Formularen vervielfältigt werden.
Diese passen Thematisch sehr gut in unsere Klasse mit der Gültigkeitsprüfung, also lagern wir den VBA-Code mit den Form-/Button-Events auch in dieser Klasse aus.
Option Compare Database
Option Explicit
Dim cRV As
clsFormRecordValidation
Private Sub Form_Load()
Set cRV = New
clsFormRecordValidation
cRV.AddRequiredField
Me.TitleOfCourtesy
cRV.AddRequiredField Me.LastName
cRV.AddRequiredField Me.Country
cRV.AddRequiredField Me.ReportsTo
cRV.ButtonOK =
Me.cmdOK
cRV.ButtonApply =
Me.cmdApply
cRV.ButtonCancel =
Me.cmdCancel
End Sub
Private Sub Form_Close()
Set cRV = Nothing
End Sub
Die fertige Klasse integriert in einer Kleinem Beispiel kann hier heruntergeladen werden. Der VBA-Code ist kommentiert, in der Hoffnung, dass das Konzept verständlich wird. Ansonsten einfach Fragen stellen über die Kommentar-Funktion. Kritik (Positiv/Negativ) wie auch Anregungen sind erwünscht.
End Sub
Die fertige Klasse integriert in einer Kleinem Beispiel kann hier heruntergeladen werden. Der VBA-Code ist kommentiert, in der Hoffnung, dass das Konzept verständlich wird. Ansonsten einfach Fragen stellen über die Kommentar-Funktion. Kritik (Positiv/Negativ) wie auch Anregungen sind erwünscht.
Ich wünsche weiterhin viel Erfolg mit nicht nur guten VBA-Code, sondern zukünftig auch mit Klasse.
Abonnieren
Posts (Atom)
