Einer für drei: Der Befehl SysCmd

15.02.2006 von Lorenz  Hölscher
Nüchtern betrachtet hat es den Anschein, als hätte man den SysCmd-Befehl in Access kurz vor Fertigstellung angeflickt, um noch rasch drei völlig unterschiedliche Funktionen unterzubringen. Warum er trotzdem sehr mächtig ist und nicht unterschätzt werden sollte, erfahren Sie in diesem Beitrag.

Zuallererst ist er in der Lage, bestimmte System- Informationen zu liefern, zum Beispiel um welche Access-Version es sich handelt oder ob Access als Runtime gestartet wurde. Listing 1 zeigt, welche Daten abgefragt werden können.

Sub ShowInfo()
Dim strVersion As String
Dim strPfad As String
Dim strSysDatei As String
Dim strProfil As String
Dim strIniDatei As String
Dim booRuntime As Boolean
strVersion = Application.SysCmd(acSysCmdAccessVer)
strPfad = Application.SysCmd(acSysCmdAccessDir)
strSysDatei = Application.SysCmd( _
acSysCmdGetWorkgroupFile)
strProfil = Application.SysCmd(acSysCmdProfile) & ""
strIniDatei = Application.SysCmd(acSysCmdIniFile)
booRuntime = Application.SysCmd(acSysCmdRuntime)
MsgBox "Version: " & strVersion & vbCrLf & _
"Access.exe-Pfad: " & strPfad & vbCrLf & _
"System-Datei: " & strSysDatei & vbCrLf & _
"Profil: " & strProfil & vbCrLf & _
"INI-Datei: " & strIniDatei & vbCrLf & _
"Runtime: " & booRuntime
End Sub

Gegebenenfalls müssen Sie darauf achten, dass die Rückgabewerte auch leer sein können wie beim Profil. Dabei handelt es sich um den Parameter, der beim Access-Start per Kommandozeile hinter "/profile" steht. Damit es keinen Fehler mit Nullwerten gibt, steht direkt dahinter die Verkettung mit einem leeren Text.

Bei der Angabe, ob Access nur als Runtime im Gegensatz zur Vollversion gestartet wurde, handelt es sich als einzigem Wert um eine boolesche Variable, also einen Ja/Nein-Wert.

Fortschrittsbalken

Beim Ausführen längerer Abfragen zeigt Access automatisch einen blauen Fortschrittsbalken links unten in der Statuszeile an. Diesen Fortschrittsbalken können Sie mit SysCmd selber erzeugen. Dazu benötigen Sie drei Aufrufe, nämlich den Start, das Weiterzählen und die Entfernung am Ende. Damit der Aufruf übersichtlich bleibt, werden diese Teilaufgaben wie in Listing 2 in Prozeduren gekapselt.

Sub FortschrittStarten(strMeldung As String, _
lngGesamt As Long)
Application.SysCmd acSysCmdInitMeter, _
strMeldung, lngGesamt
End Sub
Sub FortschrittWeiter(lngTeilwert)
Application.SysCmd acSysCmdUpdateMeter, lngTeilwert
End Sub
Sub FortschrittEnde()
Application.SysCmd acSysCmdRemoveMeter
End Sub

In Listing 3 ist mit einer einfachen Schleife zu sehen, wie ein Fortschrittsbalken erzeugt wird. Die Gesamtlänge des Balkens und sein Text müssen bereits beim Start mit angegeben werden. Das bedeutet, dass er für Do-Loop-Schleifen mit ihrer nicht vorhersehbaren Anzahl an Durchläufen ungeeignet ist.

Sub TesteFortschritt()
Dim L As Long
Const conGesamt = 100000
FortschrittStarten "Los gehts!", conGesamt
For L = 1 To conGesamt
FortschrittWeiter L
Next
FortschrittEnde
End Sub

Der angezeigte Text lässt sich außerdem während des Fortschritts nicht mehr ändern, um beispielsweise zugehörige Prozentwerte einzublenden. Es gibt zwar einen Aufruf acSysCmd- SetStatus, der einen Textwechsel ermöglicht (Listing 4), dafür schaltet er aber den blauen Balken aus und flackert ordentlich. Zudem lässt er sich nicht mit den drei anderen Prozeduren kombinieren, sondern setzt diese wieder zurück auf den Anfang. Daher ist es auf jeden Fall sinnvoller, DoCmd.Echo einzusetzen, wenn Sie einen Text in der Statuszeile benötigen.

Sub FortschrittAendern(strMeldung As String)
'eigentlich:
'Application.SysCmd acSysCmdSetStatus, strMeldung
'aber flackerfreier:
DoCmd.Echo True, strMeldung
End Sub
Sub TesteFortschritt2()
Dim L As Long
Const conGesamt = 1000
For L = 1 To conGesamt
FortschrittAendern "Prozent: " & _
Format(L / conGesamt, "0.0%")
Next
End Sub

Status ermitteln

Die dritte Funktionalität von SysCmd besteht darin, den Status von Objekten der Datenbank zu ermitteln. So können Sie prüfen, ob ein Formular ganz neu, geöffnet oder noch ungespeichert ist. Auch diese Funktionalität sollten Sie wegen der enthaltenen Binärcodierung kapseln, wie in Listing 5 demonstriert wird.

Function IstFormularOffen(strFormularName As String) As Boolean
Dim intStatus As Long
intStatus = Application.SysCmd(acSysCmdGetObjectState, acForm, strFormularName)
IstFormularOffen = ((intStatus Or 1) = intStatus)
End Function
Function IstFormularUngespeichert(strFormularName As String) As Boolean
Dim intStatus As Long
intStatus = Application.SysCmd(acSysCmdGetObjectState, acForm, strFormularName)
IstFormularUngespeichert = ((intStatus Or 2) = intStatus)
End Function
Function IstFormularNeu(strFormularName As String) As Boolean
Dim intStatus As Long
intStatus = Application.SysCmd(acSysCmdGetObjectState, acForm, strFormularName)
IstFormularNeu = ((intStatus Or 4) = intStatus)
End Function

Die Stati geöffnet, ungespeichert und neu werden mit den Zahlen 1, 2 und 4 angegeben und können natürlich auch gleichzeitig vorhanden sein. Ob ein Gesamtstatus vorhanden ist, lässt sich prüfen, indem Sie mit einer OR-Verknüpfung vergleichen, ob das Ergebnis mit dem Gesamtstatus identisch ist. Dann war der jeweilige Status bereits darin enthalten.

In Listing 6 sehen Sie, wie sich für ein Formular seine verschiedenen Stati ermitteln und als Meldung anzeigen lassen.

Sub TestFormulare()
Dim strMeldung As String
Const conName = "Formular1"
If IstFormularOffen(conName) Then
strMeldung = "offen"
Else
strMeldung = "geschlossen"
End If
If IstFormularNeu(conName) Then
strMeldung = strMeldung & " und neu"
Else
strMeldung = strMeldung & " und alt"
End If
If IstFormularUngespeichert(conName) Then
strMeldung = strMeldung & " und ungespeichert"
Else
strMeldung = strMeldung & " und schon gespeichert"
End If
MsgBox "'" & conName & "' ist " & strMeldung
End Sub