Einführung in Word-Makros III: Grundsätze des Makro-Programmierens

Dieser Beitrag ist Teil 3 von (bisher) 4 Teilen in der Beitragsserie Einführung in Word-Makros.

Im ersten Teil dieser Einführung in Word-Makros haben wir gelernt, wie man ein Makro aus Word heraus aufzeichnet. Im zweiten Teil haben wir uns der Bearbeitung des Makro-Codes gewidmet, das durch die Aufzeichnung erzeugt wurde. Mit diesem Hintergrundwissen möchten wir uns nun anschauen, wie man ohne Aufzeichnung aus Word heraus ein neues Makro erstellen, also programmieren, kann.

Hinzufügen eines Makros

Ohne vorherige Aufzeichnung können Sie ein neues Makro erstellen, indem Sie im Visual-Basic-Editor mit Sub Makroname() und End Sub ein neues Makro definieren. Sobald Sie die Zeile mit Sub geschrieben haben und die Enter-Taste drücken, fügt der Visual-Basic-Editor automatisch das End Sub an und trennt dieses neue Makro optisch mit einer Linie vom vorherigen Makro ab (sog. Autocomplete):

Zur besseren Übersichtlichkeit empfiehlt es sich, die einzelnen Zeilen eines Makros einzurücken. Befehle innerhalb eines logischen Blocks (etwa einer Wenn-Dann-Anweisung oder einer wiederholten Ausführung von Befehlen in einer Schleife) sollten Sie eine Stufe weiter einrücken, um so die logische Struktur des Makros auch optisch abbilden zu können. Dies erleichtert zudem das Auffinden etwaiger Fehler, zum Beispiel nicht-geschlossener Tags/Anweisungen. Zum Ein- oder Ausrücken einer Zeile drücken Sie am Zeilenanfang die Taste Tab oder die Tasten Shift + Tab. Alternativ können Sie Ein- und Ausrückungen für die Zeile, in der sich der Cursor gerade befindet, sowie für mehrere markierte Zeilen auch in der Symbolleiste des Visual-Basic-Editors über die beiden Schaltflächen „Einzug vergrößern“ 1 und „Einzug verkleinern“ 2 vornehmen:

Der hier verwendete Befehl MsgBox öffnet übrigens ein Word-Dialogfenster, das mit „OK“ bestätigt werden muss. Als Argument in runden Klammern ist der Text anzugeben, der in dem Dialogfenster angezeigt werden soll. Time gibt die aktuelle Uhrzeit in Stunden, Minuten und Sekunden aus. Etwas schöner ist die Ausgabe, wenn die Zeile anstelle von MsgBox (Time) ausführlicher MsgBox ("Es ist jetzt " & Time & " Uhr.") lautet. Das &-Zeichen ist dabei erforderlich, um zwei Zeichenketten („Strings“) miteinander zu verbinden. Wenn Sie diese ausführlichere Variante als einzigen Befehl in dem Testmakro2 verwenden und dieses mit dem Play-Button ausführen, erscheint das folgende Fenster:

Arbeiten mit Variablen

Spannende und hilfreiche Makros beruhen regelmäßig auf der Verwendung von Variablen. Variablen sind Platzhalter, die verschiedene Werte annehmen können. Bei der Vergabe von Variablennamen sind Sie recht frei. Nicht enthalten sein dürfen Leerzeichen, Punkte und Trennstriche. Auch wenn Groß- und Kleinschreibung keinen Unterschied macht, sollten Sie einheitlich bleiben, also entweder var1 oder Var1 verwenden. Bei Variablen mit längerem Namen bietet sich sog. CamelCase an, also das Großschreiben neuer Wortbestandteile ohne Leerzeichen, beispielsweise als varAlt.

Deklarieren von Variablen

Es empfiehlt sich, die Variablen für ein Makro an dessen Anfang mit dem Befehl Dim aufzulisten, sie also zu deklarieren. Sinnvoll ist, dabei mit As nach dem Variablennamen auch gleich die Art der Variable anzugeben. Relevant sind insbesondere die folgenden Typen:

  • String: normaler Text
  • Integer: eine ganze Zahl
  • Single: eine Zahl mit Stellen nach dem Komma
  • Date: ein Datum
  • Boolean: wahr oder falsch
  • Variant: ein Auffangdatentyp, der sich immer am aktuellen Wert der Variable orientiert

Um also etwa die Variable Ausgangswert als ganze Zahl zu deklarieren, verwenden Sie Dim Ausgangswert as Integer. Die Variable AuszugebenderText können sie mit Dim AuszugebenderText as String als eine Textvariable deklarieren.

Zuweisen eines Werts zu einer Variablen

Um einer Variablen einen Wert zuzuweisen, verwenden Sie schlicht das Zeichen =. Die Zeile Ausgangswert = 1 etwa setzt den Wert der Variable Ausgangswert auf die Zahl 1. Mit AuszugebenderText = "Danke für die Nutzung dieses Makros." wird der Variablen AuszugebenderText der Text „Danke für die Nutzung dieses Makros.“ zugewiesen. Ein zuzuweisender Text hat immer zwischen zwei (doppelten) Anführungszeichen zu stehen.

Operationen mit Variablen

Für Zahlvariablen können Sie die von Taschenrechnern bekannten arithmetischen Operatoren verwenden (also insbesondere +, -, *, / und ^). Haben Sie etwa die beiden Variablen Ausgangswert und Ergebnis als Integer-Variablen definiert und der Variablen Ausgangswert den Wert 1 zugewiesen, so können Sie mit Ergebnis = Ausgangswert + Ausgangswert die Variable Ergebnis auf 2 setzen.

Für Textvariablen ist vor allem die Verkettung mit dem Operator & von Interesse. Wenn Sie die drei String-Variablen Text1, Text2 und AuszugebenderText definiert haben und Text1 den Wert „Dies ist der“ sowie Text2 den Wert „auszugebende Text.“ zugewiesen haben, können Sie mit AuszugebenderText = Text1 & Text2 die Variable AuszugebenderText mit dem vollständigen Text belegen. Sie können den &-Operator auch verwenden, um einen Text (eine String-Variable) und eine Zahl (Integer-Variable) zu kombinieren.

Als Vergleichs-Operatoren stehen =, <, >, <=, >= und <> zur Verfügung, die jeweils „True“ oder „False“ zurückgeben. Vergleichen Sie etwa im obigen Beispiel Ausgangswert <= Ergebnis, so wird dies „True“ liefern, da 1 kleiner oder gleich 2 ist. AuszugebenderText <> Text1 wird ebenfalls „True“ zurückgeben, da sich der Inhalt der beiden String-Variablen ja unterscheidet.

Bedingungen

Zur Prüfung von Bedingungen stehen die Befehle If, Then, End If, Else und ElseIf zur Verfügung.

If prüft, ob der darauffolgende Ausdruck wahr ist. Zur besseren Übersichtlichkeit bietet es sich an, den Ausdruck in runden Klammern zu fassen. [Expertentipp: Es können auch mehrere Ausdrücke mit And, Or oder Xor kombiniert werden. Mit dem Operator Not kann der darauffolgende Ausdruck in sein Gegenteil verkehrt werden.] Ist der Ausdruck wahr, dann wird der nach dem Then stehende Befehl ausgeführt. Folgen auf das Then mehrere Befehle, so ist dieser Block mit End If abzuschließen. Um die logische Struktur optisch erfassen zu können, sollte dabei mit Einrückungen gearbeitet werden. Ein IfThenEnd If-Block sollte also wie folgt aussehen:

If (Ausdruck) Then
    Befehl1
    Befehl2
End If

Folgt auf ein If ein Else, dann werden die nach dem Else stehenden Befehle nur ausgeführt, wenn der mit If geprüfte Ausdruck nicht wahr ist. Möchte man den Else-Teil nur bei Zutreffen einer weiteren Bedingung ausführen, so ist ElseIf zu verwenden.

Ein kleines Beispiel gefällig? So wie Time (dazu bereits oben) die aktuelle Uhrzeit zurückgibt, liefert Date das aktuelle Datum. Weekday(Datum) liefert den Wochentag des übergebenen Datums als Zahl, wobei Sonntag die 1 ist und Samstag die 7 ist. Wollen wir also mit einem einfachen Makro in einem Dialog anzeigen, ob heute Wochenende ist, könnte das wie folgt aussehen:

Sub Testmakro2()
    If (Weekday(Date) = 7) Then        ' Samstag
        MsgBox ("Heute ist Samstag und daher Wochenende!")
    ElseIf (Weekday(Date) = 1) Then    ' Sonntag 
        MsgBox ("Heute ist Sonntag und daher Wochenende!")
    Else                               ' weder Samstag noch Sonntag
        MsgBox ("Heute ist leider kein Wochenende.") 
    End If
End Sub

Zur Erinnerung: Der Text nach einem ' (einfachen Anführungszeichen, Hochkomma)  stellt einen Kommentar dar, der bei der Ausführung des Makros ignoriert wird und lediglich die Lesbarkeit des Codes fördern soll.

Praxisbeispiel: Bestimmung der Berufungsfrist

Als Beispiel wollen wir ein Makro programmieren, das zu einem einzugebenden Zustellungsdatum den Ablauf der zivilrechtlichen Berufungs(einlegungs)frist ausgibt. Nach § 517 ZPO beträgt die Berufungsfrist grundsätzlich einen Monat und beginnt mit der Zustellung des in vollständiger Form abgefassten Urteils. Nach § 222 Abs. 2 ZPO verschiebt sich das Fristende bei Ablauf an einem Wochenendtag oder einem allgemeinen Feiertag auf den darauffolgenden Werktag. Da die allgemeinen Feiertag entweder einzeln eingegeben werden oder aus einer Datenquelle ausgelesen werden müssten, wollen wir in unserem Beispielsmakro den Fristablauf an einem allgemeinen Feiertag unberücksichtigt lassen.

Die Eingabe in einem Dialogfeld realisieren wir mit dem Befehl InputBox(), dem als Argument in der Klammer der im Dialogfeld anzuzeigende Text (in Form eines Strings) übergeben wird. Wenn wir zunächst die Variable Ausgangsdatum als Variable des Typs Date definiert haben, können wir dieser dann das eingegebene Datum wie folgt zuweisen:

    Dim Ausgangsdatum As Date
    Ausgangsdatum = InputBox("Geben Sie das Zustellungsdatum ein:")

Die Funktion DateAdd() fügt einem Datum eine bestimmte Zeitspanne zurück. Als erstes Argument in der Klammer erwartet sie als String das hinzuzufügende Zeitintervall. Wir verwenden "m" für „month“. Mit "d" hingegen könnten wir eine in Tagen („days“) bemessene Zeitspanne hinzufügen. Existiert der betreffende Monatstag im folgenden Monat nicht, so gibt DateAdd() automatisch den ersten Tag des übernächsten Monats zurück; das Hinzufügen eines Monats zum 30. Januar führt also zum 1. März.

Als zweites Argument ist in Form einer Zahl anzugeben, wie oft dieses Zeitintervall hinzugefügt werden soll. Gemäß § 517 ZPO verwenden wir hier 1.

Schließlich ist als drittes Argument in der Klammer das Datum zu übergeben, dem die Zeitspanne hinzugefügt werden soll. In unserem Fall ist das die Date-Variable Ausgangsdatum. Das neue Datum wollen wir der zunächst mit dem Typ Date definierten Variable EnddatumVorKorrektur zuweisen:

Dim EnddatumVorKorrektur As Date
EnddatumVorKorrektur = DateAdd("m", 1, Ausgangsdatum)

Sodann ist in Umsetzung des § 222 Abs. 2 ZPO zu schauen, ob das berechnete Enddatum auf einen Samstag oder einen Sonntag fällt. Dazu verwenden wir die im obigen Kurzbeispiel zu den Bedingungen bereits beschriebene Funktion Weekday(). Wenn wir zuvor die Integer-Variable Wochentag definiert haben, können wir dieser die Zahl des Wochentages zuweisen:

Dim Wochentag As Integer
Wochentag = Weekday(EnddatumVorKorrektur)

Wie bereits im obigen Kurzbeispiel zu den Bedingungen gehandhabt, schauen wir dann, ob es sich bei dem Wochentag um einen Samstag (7), einen Sonntag (1) oder einen anderen Wochentag handelt. Im ersteren Fall haben wir dem vorläufigen Enddatum zwei Wochentage hinzuzufügen, um auf den Montag zu kommen. In zweiten Fall eines Sonntags ist nur ein Tag zu addieren. Handelt es sich bereits um einen Werktag, kann dies so bleiben. Das gegebenenfalls korrigierte Enddatum weisen wir der Date-Variablen EnddatumNachKorrektur zu:

Wochentag = Weekday(EnddatumVorKorrektur)
If (Wochentag = 7) Then     'Samstag 
    EnddatumNachKorrektur = DateAdd("d", 2, EnddatumVorKorrektur) 
ElseIf (Wochentag = 1) Then 'Sonntag
    EnddatumNachKorrektur = DateAdd("d", 1, EnddatumVorKorrektur)
Else                        'kein Wochenendtag 
    EnddatumNachKorrektur = EnddatumVorKorrektur
End If

Jetzt müssen wir nur noch den Text für die Ausgabe im Dialogfeld festlegen. Hierfür verwenden wir die Variable Ausgabetext vom Typ String. Um ein Datum in der Form „1. Januar 2021“ ausgeben wollen, können wir hierzu den Befehl Format() nutzen. Als erstes Argument übergeben wir dabei das zu formatierende Datum und als zweites den Formatierungsstring, in unserem Fall "D. MMMM YYYY".

Wir hatten ja bereits gesehen, dass wir mehrere Strings mit & aneinanderreihen können. Wenn eine Zeile im VBA-Editor lange wird und daher horizontales Scrollen erfordern würde, können wir auf eine neue Zeile umbrechen, indem wir die Zeile mit einem Leerzeichen und einem Unterstrich  _ beenden und sie sodann in der nächsten Zeile – am besten eingerückt – fortsetzen. Mit MgsBox() können wir schließlich ein Dialogfeld mit dem Ausgabetext anzeigen, den wir dem Befehl als String übergeben. Wollen Sie den Ausgabetext nicht in einem Dialogfeld anzeigen, sondern direkt in ihrem aktuellen Word-Dokument an der momentanen Cursor-Position schreiben, so können Sie anstelle von MsgBox() den Befehl Selection.TypeText() verwenden.

Ausgabetext = "Bei Zustellung am " _
    & Format(Ausgangsdatum, "D. MMMM YYYY") _
    & " endet die Berufungseinlegungsfrist am " _
    & Format(EnddatumNachKorrektur, "D. MMMM YYYY") _ 
    & ", sofern dies kein allgemeiner Feiertag ist."
MsgBox Ausgabetext

Insgesamt schaut der Code unseres Beispielmakros damit wie folgt aus:

Sub Berufungseinlegungsfrist()

    Dim Ausgangsdatum As Date 
    Dim EnddatumVorKorrektur As Date 
    Dim EnddatumNachKorrektur As Date 
    Dim Wochentag As Integer
    Dim Ausgabetext As String

    Ausgangsdatum = InputBox("Geben Sie das Zustellungsdatum ein:")
    EnddatumVorKorrektur = DateAdd("m", 1, Ausgangsdatum)

    Wochentag = Weekday(EnddatumVorKorrektur) 
    If (Wochentag = 7) Then        'Samstag
        EnddatumNachKorrektur = DateAdd("d", 2, EnddatumVorKorrektur)
    ElseIf (Wochentag = 1) Then    'Sonntag
        EnddatumNachKorrektur = DateAdd("d", 1, EnddatumVorKorrektur)
    Else                           'kein Wochenendtag
        EnddatumNachKorrektur = EnddatumVorKorrektur
    End If

    Ausgabetext = "Bei Zustellung am " _
        & Format(Ausgangsdatum, "D. MMMM YYYY") _
        & " endet die Berufungseinlegungsfrist am " _
        & Format(EnddatumNachKorrektur, "D. MMMM YYYY") _
        & ", sofern dies kein allgemeiner Feiertag ist."
    MsgBox Ausgabetext

End Sub

Ausgeführt schaut das Makro folgendermaßen aus:

Herzlichen Glückwunsch zu Ihrem ersten selbstprogrammierten Word-Makro! Sollten Sie dabei Fragen oder Probleme aufgetreten sein, zögern Sie nicht, uns über kontakt(at)legal-automation-blog.de zu kontaktieren oder einen Kommentar zu diesem Beitrag zu hinterlassen.

Im folgenden Beitrag dieser Serie soll es darum gehen, wie Sie Ihre Makros verwalten und diese auch Kolleginnen und Kollegen zur Verfügung stellen können.

 

Seriennavigation← Einführung Word-Makros II: Bearbeiten des Codes eines MakrosEinführung in Word-Makros IV: Speichern, Organisieren und Weitergeben von Makros →