Lektionen/Formulare & Berichte

Endlosformulare & bedingte Formatierung

Fortgeschritten9 Min. Lesezeit

Endlosformulare sind praktisch: Sie zeigen viele Datensätze untereinander in derselben Struktur. Doch sobald du versuchst, eine einzelne Zeile per VBA einzufärben — etwa einen überfälligen Auftrag rot —, stolperst du über eine Eigenheit, die viele Anfänger zur Verzweiflung bringt: Plötzlich sind alle Zeilen rot.

Diese Lektion erklärt, warum das so ist, und zeigt dir die richtige Lösung: die bedingte Formatierung über das FormatConditions-Objekt.

Warum ein Steuerelement für alle Zeilen gilt

Ein Endlosformular sieht aus wie eine Tabelle mit vielen Zeilen — technisch ist es aber nur ein Satz Steuerelemente im Detailbereich, der für jeden Datensatz neu gezeichnet wird. Das Textfeld txtStatus existiert also nur einmal, nicht pro Zeile.

Wenn du im Code schreibst:

Me.txtStatus.BackColor = vbRed

dann setzt du die Hintergrundfarbe dieses einen Steuerelements — und da es für jede Zeile dasselbe ist, werden alle Zeilen rot. Das direkte Setzen von BackColor, ForeColor oder FontBold funktioniert deshalb nur in Einzelformularen sinnvoll, nicht in Endlosformularen.

Merke: In Endlosformularen ist jede optische Eigenschaft, die du per VBA direkt setzt, eine Eigenschaft für alle sichtbaren Zeilen zugleich. Für zeilenabhängige Farben brauchst du die bedingte Formatierung.

Die Lösung: FormatConditions

Access hat für genau diesen Fall die bedingte Formatierung eingebaut. Sie bewertet für jede Zeile einzeln einen Ausdruck und färbt nur die Zeilen, auf die er zutrifft. Genau das siehst du auch im Menüband unter Format → Bedingte Formatierung — und du kannst es komplett per VBA steuern.

Jedes Steuerelement hat eine Auflistung FormatConditions. Mit Add fügst du eine Regel hinzu, mit Delete löschst du alle bestehenden.

Private Sub Form_Load()
    Dim fc As FormatCondition

    ' Alte Regeln entfernen, sonst sammeln sie sich an
    Me.txtStatus.FormatConditions.Delete

    ' Neue Regel: Wenn Feld "Status" = "offen", dann rot hinterlegen
    Set fc = Me.txtStatus.FormatConditions.Add( _
        acFieldValue, acEqual, "'offen'")
    fc.BackColor = RGB(255, 199, 206)   ' helles Rot
    fc.ForeColor = RGB(156, 0, 6)       ' dunkles Rot für Text
    fc.FontBold = True
End Sub

Der wichtige Punkt: FormatConditions.Add wird einmalig beim Laden aufgerufen, nicht pro Zeile. Access wendet die Regel danach automatisch auf jede Zeile einzeln an.

Die Parameter von Add

FormatConditions.Add erwartet je nach Regeltyp unterschiedliche Argumente:

ArgumentBedeutungBeispielwerte
TypeWas wird geprüftacFieldValue, acExpression, acFieldHasFocus
OperatorVergleichacEqual, acBetween, acGreaterThan, acLessThan
Expression1Vergleichswert / Ausdruck"100", "'offen'", "1000"
Expression2zweiter Wert (nur bei acBetween)"5000"

Für Textvergleiche gehört der Wert in einfache Anführungszeichen innerhalb des Strings: "'offen'". Bei Zahlen reicht "100".

Ampel-Status: Farbe abhängig vom Wert

Ein häufiger Wunsch ist eine „Ampel": Ein Feld Bestand soll rot werden, wenn er kritisch niedrig ist, gelb bei Warnung und grün, wenn alles in Ordnung ist. Dafür legst du mehrere Regeln übereinander. Access prüft sie in der Reihenfolge des Hinzufügens und nimmt die erste zutreffende.

Private Sub Form_Load()
    Dim fc As FormatCondition

    Me.txtBestand.FormatConditions.Delete

    ' Rot: Bestand unter 10
    Set fc = Me.txtBestand.FormatConditions.Add( _
        acFieldValue, acLessThan, "10")
    fc.BackColor = RGB(255, 92, 92)
    fc.ForeColor = vbWhite

    ' Gelb: Bestand zwischen 10 und 50
    Set fc = Me.txtBestand.FormatConditions.Add( _
        acFieldValue, acBetween, "10", "50")
    fc.BackColor = RGB(255, 214, 102)

    ' Grün: Bestand über 50
    Set fc = Me.txtBestand.FormatConditions.Add( _
        acFieldValue, acGreaterThan, "50")
    fc.BackColor = RGB(146, 208, 80)
End Sub

Regel über einen Ausdruck (andere Spalte prüfen)

Manchmal soll die Farbe eines Feldes von einem anderen Feld abhängen — zum Beispiel den Kundennamen rot einfärben, wenn das Lieferdatum überschritten ist. Dafür nutzt du acExpression und schreibst einen Ausdruck, der die Feldnamen des Formulars referenziert:

Private Sub Form_Load()
    Dim fc As FormatCondition

    Me.txtKunde.FormatConditions.Delete

    ' Ausdruck bewertet pro Zeile das Feld "Lieferdatum"
    Set fc = Me.txtKunde.FormatConditions.Add( _
        acExpression, , "[Lieferdatum] < Date() And [Erledigt] = False")
    fc.BackColor = RGB(255, 199, 206)
    fc.ForeColor = RGB(156, 0, 6)
    fc.FontBold = True
End Sub

Beim Typ acExpression bleibt das Operator-Argument leer (das Komma bleibt stehen), und der ganze Vergleich steht in Expression1. Die eckigen Klammern verweisen auf die Felder der zugrunde liegenden Datenherkunft.

Achtung: Ein Steuerelement erlaubt maximal vier bedingte Formatierungsregeln plus das Standardformat. Brauchst du mehr Abstufungen, musst du auf einen Bericht oder eigene Logik im Format-Ereignis ausweichen.

Bedingte Formatierung vs. Bericht

Beide Techniken färben zeilenabhängig — aber sie haben unterschiedliche Stärken:

Endlosformular + FormatConditionsBericht + Format-Ereignis
Interaktiv (scrollen, bearbeiten)janein (nur Anzeige/Druck)
Anzahl Regelnmax. 4 pro Feldunbegrenzt (per Code)
Direktes BackColor je Zeileneinja, im Detail_Format
Für den Druck gedachteher nichtja

Im Bericht wird der Detailbereich für jede Zeile einzeln gerendert und das Format-Ereignis pro Datensatz ausgelöst — dort funktioniert direktes BackColor sehr wohl:

Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
    If Me.Bestand < 10 Then
        Me.txtBestand.BackColor = RGB(255, 92, 92)
    Else
        Me.txtBestand.BackColor = vbWhite
    End If
End Sub

Der Else-Zweig ist wichtig: Da der Bereich wiederverwendet wird, musst du die Farbe für nicht zutreffende Zeilen aktiv zurücksetzen — sonst „klebt" die Farbe der vorherigen Zeile.

Zusammengefasst

  • In Endlosformularen gibt es jedes Steuerelement nur einmal — direktes BackColor färbt darum immer alle Zeilen.
  • Für zeilenabhängige Farben nutzt du FormatConditions.Add, das Access pro Datensatz einzeln auswertet.
  • acFieldValue prüft den Feldwert, acExpression erlaubt Regeln über andere Spalten; maximal vier Regeln pro Steuerelement.
  • Rufe die Regeln einmal in Form_Load auf und lösche vorher mit FormatConditions.Delete die alten.
  • Für Druck oder mehr als vier Abstufungen nimm einen Bericht und färbe im Detail_Format-Ereignis direkt — dort inklusive Else-Zurücksetzen.
Nächste Lektion
E-Mails mit Outlook versenden