use static font size over all document texts
This commit is contained in:
1 parent
23cb3c35b3
commit
2247c42e81
6 files changed
+16
-36
No files matched your search
@@ -289,6 +289,7 @@ if generate_clicked:
|
||||
mapping=app_config.output_mapping,
|
||||
output_dir=output_dir,
|
||||
filename_pattern=app_config.filename_pattern,
|
||||
fontsize=app_config.fontsize,
|
||||
)
|
||||
st.session_state.generated_files = generated
|
||||
except Exception as e:
|
||||
|
||||
@@ -113,6 +113,7 @@ def main():
|
||||
mapping=config.output_mapping,
|
||||
output_dir=output_dir,
|
||||
filename_pattern=config.filename_pattern,
|
||||
fontsize=config.fontsize,
|
||||
)
|
||||
|
||||
output_file = generated[0]
|
||||
|
||||
@@ -6,6 +6,10 @@ output_dir = output
|
||||
[output]
|
||||
filename_pattern = {last_name}_{first_name}_Tätigkeitsnachweis.pdf
|
||||
|
||||
[font]
|
||||
# Statische Schriftgröße (in Punkt) für alle Felder im PDF
|
||||
fontsize = 9
|
||||
|
||||
[parsing]
|
||||
# Sheets whose names match these patterns are treated as monthly data sheets
|
||||
# Use * as wildcard. Sheets not matching are ignored (e.g. "Alle Rollen").
|
||||
|
||||
@@ -21,6 +21,7 @@ def load_settings(config_dir: Path, project_root: Path) -> AppConfig:
|
||||
paths = parser["paths"] if "paths" in parser else {}
|
||||
output = parser["output"] if "output" in parser else {}
|
||||
parsing = parser["parsing"] if "parsing" in parser else {}
|
||||
font = parser["font"] if "font" in parser else {}
|
||||
|
||||
return AppConfig(
|
||||
input_dir=str(project_root / paths.get("input_dir", "input")),
|
||||
@@ -30,6 +31,7 @@ def load_settings(config_dir: Path, project_root: Path) -> AppConfig:
|
||||
month_sheet_pattern=parsing.get("month_sheet_pattern", "* 20??"),
|
||||
skip_empty_name=parsing.getboolean("skip_empty_name", True),
|
||||
skip_empty_antragsnummer=parsing.getboolean("skip_empty_antragsnummer", True),
|
||||
fontsize=font.getfloat("fontsize", 11.0),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ class AppConfig:
|
||||
month_sheet_pattern: str = "* 20??"
|
||||
skip_empty_name: bool = True
|
||||
skip_empty_antragsnummer: bool = True
|
||||
fontsize: float = 11.0
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
+7
-36
@@ -101,6 +101,7 @@ def _get_field_value(record: EmployeeRecord, employee_name: str, source_field: s
|
||||
def _scan_template_fields(
|
||||
template_path: Path,
|
||||
mapping: list[OutputMapping],
|
||||
fontsize: float,
|
||||
) -> dict[str, dict]:
|
||||
"""
|
||||
Scannt ALLE Seiten des PDF-Templates nach _Field-Platzhaltern.
|
||||
@@ -117,7 +118,7 @@ def _scan_template_fields(
|
||||
|
||||
field_info: dict[str, dict] = {}
|
||||
|
||||
# 1. Per search_for die Rechtecke aller PDF-Feld-Marker finden (alle Seiten)
|
||||
# Per search_for die Rechtecke aller PDF-Feld-Marker finden (alle Seiten)
|
||||
for pdf_field, source_field in pdf_to_source.items():
|
||||
found_any = False
|
||||
for page_num in range(doc.page_count):
|
||||
@@ -128,7 +129,7 @@ def _scan_template_fields(
|
||||
"source_field": source_field,
|
||||
"page_num": page_num,
|
||||
"rect": found[0],
|
||||
"fontsize": 11, # Fallback
|
||||
"fontsize": fontsize,
|
||||
"fontname": "helv",
|
||||
}
|
||||
found_any = True
|
||||
@@ -136,23 +137,6 @@ def _scan_template_fields(
|
||||
if not found_any:
|
||||
field_info[pdf_field] = None # nicht gefunden
|
||||
|
||||
# 2. Schriftgrößen aus den Text-Details extrahieren (alle Seiten)
|
||||
for page_num in range(doc.page_count):
|
||||
page = doc[page_num]
|
||||
text_dict = page.get_text("dict")
|
||||
for block in text_dict.get("blocks", []):
|
||||
if "lines" not in block:
|
||||
continue
|
||||
for line in block["lines"]:
|
||||
for span in line["spans"]:
|
||||
text = span["text"].strip()
|
||||
if text.endswith("_Field") and text in field_info:
|
||||
info = field_info[text]
|
||||
if info is not None:
|
||||
info["fontsize"] = span["size"]
|
||||
info["fontname"] = span.get("font", "helv")
|
||||
info["rect"] = fitz.Rect(span["bbox"])
|
||||
|
||||
doc.close()
|
||||
return field_info
|
||||
|
||||
@@ -167,17 +151,13 @@ def _fill_pdf_pages(
|
||||
employee_name: str,
|
||||
mapping: list[OutputMapping],
|
||||
field_info: dict[str, dict],
|
||||
fontsize: float,
|
||||
) -> None:
|
||||
"""Befüllt alle Template-Seiten: redacted _Field-Platzhalter und fügt echte Daten ein."""
|
||||
# Mehrzeilige Felder, die als Textbox (mit Zeilenumbruch) behandelt werden
|
||||
MULTILINE_FIELDS = {"Tätigkeiten_Field", "Dienstreisen_Field"}
|
||||
TEXTBOX_WIDTH_PT = 400 # Breite der Textbox in Punkt
|
||||
|
||||
# Felder mit automatischer Schriftgrößen-Anpassung bei langem Text
|
||||
AUTOSCALE_FIELDS = {"Qualifikation_Field", "Funktion_Field"}
|
||||
AUTOSCALE_MAX_CHARS = 35 # ab dieser Länge wird verkleinert
|
||||
AUTOSCALE_MIN_FACTOR = 0.75 # minimale Schriftgröße relativ zum Original
|
||||
|
||||
for m in mapping:
|
||||
if m.pdf_field is None:
|
||||
continue
|
||||
@@ -192,7 +172,6 @@ def _fill_pdf_pages(
|
||||
|
||||
page = pages[page_num]
|
||||
rect = info["rect"]
|
||||
fontsize = info.get("fontsize", 11)
|
||||
|
||||
value = _get_field_value(record, employee_name, m.source_field)
|
||||
formatted = _format_value(value, m.format)
|
||||
@@ -204,15 +183,6 @@ def _fill_pdf_pages(
|
||||
if not formatted:
|
||||
continue
|
||||
|
||||
# Automatische Schriftgrößen-Anpassung für lange Texte
|
||||
if m.pdf_field in AUTOSCALE_FIELDS and len(formatted) > AUTOSCALE_MAX_CHARS:
|
||||
text_width = fitz.get_text_length(formatted, fontname="helv", fontsize=fontsize)
|
||||
available_width = rect.width
|
||||
if text_width > available_width:
|
||||
factor = available_width / text_width
|
||||
factor = max(factor, AUTOSCALE_MIN_FACTOR)
|
||||
fontsize = fontsize * factor
|
||||
|
||||
# Mehrzeilige Felder: Zeilenweise per insert_text schreiben
|
||||
if m.pdf_field in MULTILINE_FIELDS:
|
||||
# Doppelte Leerzeilen entfernen
|
||||
@@ -269,6 +239,7 @@ def generate_activity_reports(
|
||||
mapping: list[OutputMapping],
|
||||
output_dir: Path,
|
||||
filename_pattern: str,
|
||||
fontsize: float = 11.0,
|
||||
) -> list[Path]:
|
||||
"""
|
||||
Erzeugt für jeden Mitarbeiter ein PDF.
|
||||
@@ -278,7 +249,7 @@ def generate_activity_reports(
|
||||
generated_files: list[Path] = []
|
||||
|
||||
# Pre-Scan: Feld-Positionen auf allen Template-Seiten ermitteln
|
||||
field_info = _scan_template_fields(template_path, mapping)
|
||||
field_info = _scan_template_fields(template_path, mapping, fontsize)
|
||||
|
||||
for employee_name, records in employee_records.items():
|
||||
if not records:
|
||||
@@ -301,7 +272,7 @@ def generate_activity_reports(
|
||||
temp_doc = fitz.open(template_path)
|
||||
pages = [temp_doc[i] for i in range(temp_doc.page_count)]
|
||||
|
||||
_fill_pdf_pages(pages, record, employee_name, mapping, field_info)
|
||||
_fill_pdf_pages(pages, record, employee_name, mapping, field_info, fontsize)
|
||||
|
||||
# Alle modifizierten Seiten ins Ergebnis-PDF einfügen
|
||||
result_doc.insert_pdf(temp_doc)
|
||||
|
||||
Reference in new issue
Block a user