6.0 KiB
Anwesenheit PDF Generator
Liest Anwesenheitsdaten aus einer Excel-Datei (.xlsx) und erzeugt für jeden Teilnehmer eine ausgefüllte PDF-Datei (SAB-Formular).
Voraussetzungen
- Python 3.10 oder höher
- pip
Installation
# Abhängigkeiten installieren
pip install -r requirements.txt
Für Entwicklung inkl. Tests:
pip install -r requirements-dev.txt
Konfiguration
Vor dem ersten Start müssen zwei Werte in config.json eingetragen werden:
| Feld | Beschreibung |
|---|---|
antragsnummer |
SAB-Antragsnummer der Einrichtung |
ort |
Ort für die Unterschriftszeile im PDF |
Alle anderen Felder sind vorbelegt und müssen nur bei abweichender Excel-Struktur angepasst werden.
Verzeichnisstruktur
generate.py ← Einstiegspunkt
config.json ← Konfiguration
input/ ← Excel-Dateien ablegen
template/
sab.pdf ← PDF-Vorlage (muss vorhanden sein)
output/ ← Generierte PDFs (werden hier abgelegt)
Verwendung
Generierung starten
python generate.py generate --file "input/Anwesenheitsliste 2026.xlsx" --month Feb
Das Programm zeigt vor der Generierung eine Vorschau und fragt zur Bestätigung:
=== Vorschau der ermittelten Werte ===
Excel-Datei : Anwesenheitsliste 2026.xlsx
Jahr : 2026
Monat : Feb (02)
Antragsnummer : 12345
Ort : Leipzig
Erstelldatum : 27.03.2026
Teilnehmer : 49
Fehler : 0
Möchten Sie die PDF-Generierung starten? [j/N]
Nur bei Eingabe von j werden PDFs geschrieben.
Nur Validierung (keine PDFs erzeugen)
python generate.py validate --file "input/Anwesenheitsliste 2026.xlsx" --month Feb
Führt alle Prüfungen durch und zeigt die Vorschau — ohne Dateien zu schreiben.
PDF als Bild rendern
python generate.py render-image --pdf "output/(1) Mustermann, Max.pdf" --page 1 --out "preview.png"
Dieser Befehl rendert eine PDF-Seite als PNG-Bild. Er nutzt dieselbe Render-Funktion wie der Regressionstest, damit CLI-Vorschau und Testvergleich technisch identisch arbeiten.
Alle Seiten auf einmal rendern:
python generate.py render-image --pdf "output/(1) Mustermann, Max.pdf" --all-pages --out "render_out"
Optionen
generate
| Option | Pflicht | Beschreibung |
|---|---|---|
--file |
ja | Pfad zur Excel-Datei |
--month |
ja | Name des Monats-Sheets (z. B. Jan, Feb, Mrz, Apr …) |
--out |
nein | Ausgabeverzeichnis (Standard: output/ aus config.json) |
validate
| Option | Pflicht | Beschreibung |
|---|---|---|
--file |
ja | Pfad zur Excel-Datei |
--month |
ja | Name des Monats-Sheets |
render-image
| Option | Pflicht | Beschreibung |
|---|---|---|
--pdf |
ja | Pfad zur PDF-Datei |
--out |
nein | Zieldatei (Einzelseite) oder Zielordner (--all-pages) |
--dpi |
nein | Render-Auflösung in DPI (Standard: 150) |
--page |
nein | 1-basierte Seitennummer (Standard: 1) |
--all-pages |
nein | Rendert alle Seiten statt nur --page |
Sheet-Namen
Die deutschen Monatsabkürzungen entsprechen den Tabellenblatt-Namen in der Excel-Datei:
| Sheet | Monat |
|---|---|
Jan |
Januar |
Feb |
Februar |
Mrz |
März |
Apr |
April |
Mai |
Mai |
Jun |
Juni |
Jul |
Juli |
Aug |
August |
Sep |
September |
Okt |
Oktober |
Nov |
November |
Dez |
Dezember |
Ausgabe
Für jeden Teilnehmer wird eine PDF-Datei erstellt:
output/
(1) Mustermann, Max.pdf
(2) Beispiel, Anna.pdf
...
Die laufende Nummer entspricht der Nummerierung in Spalte A der Excel-Datei.
Tests ausführen
Alle Tests starten
pytest tests/ -v
Nur den Regression-Test. Der Test erwartet, dass im Ordner 2026_Feb die Excel-Datei und in reference/ die Ground-Truth-PDFs liegen. Er generiert PDFs in ein Temp-Verzeichnis und vergleicht sie pixelweise. Bei Abweichungen werden Diff-Bilder nach diff geschrieben.
python -m pytest tests/test_regression.py -v
Validierungsprüfungen
Das Programm prüft vor jeder Generierung:
config.jsonvorhanden und vollständig- Excel-Datei existiert und ist eine
.xlsx/.xlsm-Datei - Jahr aus Dateiname extrahierbar (z. B.
Anwesenheitsliste 2026.xlsx) - Sheet-Name bekannt (in
month_mappingderconfig.json) - Sheet existiert in der Arbeitsmappe
- Spalte A (lfd. Nummer) enthält Daten
- Headerzeile mit
Name, Vornamegefunden - Tagesspalten ab Spaltenindex 9 vorhanden
- PDF-Template unter
template/sab.pdferreichbar
Windows-Installer erstellen
Der Build-Prozess erzeugt neben dem Programm auch einen Windows-Installer (.exe), der vom SMB-Netzlaufwerk gestartet werden kann.
Voraussetzung: Inno Setup 6
Inno Setup 6 muss auf der Build-Maschine installiert sein. Installation über winget:
winget install --id JRSoftware.InnoSetup -e -s winget -i
Alternativ manueller Download: https://jrsoftware.org/isinfo.php
Installer bauen
build.bat
build.bat führt alle vier Schritte automatisch aus:
- Abhängigkeiten installieren (
pip install) - Version aktualisieren (
update_version.py) - Programm packen (
PyInstaller→dist\AnwesenheitPDF\) - Installer kompilieren (
ISCC.exe→dist\AnwesenheitPDF-Setup-x.y.z.exe)
Ist Inno Setup nicht installiert, wird Schritt 4 mit einer Warnung übersprungen — der PyInstaller-Output in dist\AnwesenheitPDF\ ist trotzdem nutzbar.
Installer verteilen
Die fertige Datei dist\AnwesenheitPDF-Setup-x.y.z.exe auf das SMB-Netzlaufwerk kopieren. Von dort kann sie direkt gestartet werden — ohne vorherige lokale Kopie.
Was der Installer macht
| Aktion | Details |
|---|---|
| Installationspfad | %ProgramFiles%\AnwesenheitPDF\ (Admin erforderlich) |
| Startmenü-Eintrag | AnwesenheitPDF |
| Desktop-Verknüpfung | Optional (Checkbox im Wizard, Standard: deaktiviert) |
| Uninstaller | Registriert unter Programme und Features |
| Windows-Version | Windows 10 oder höher |