fix: Fehlzeitenkalender Spaltenbreiten und unnötigen Seitenumbruch
CI / build-and-test (push) Waiting to run

Datum-Spalte in der Fehltage-Tabelle war für "dd.MM.yyyy" zu schmal
bemessen (an der kurzen Kopfzeile "Datum" orientiert) und wurde
abgeschnitten. RenderFlow erzwang außerdem zwischen den Ausschnitten
einer zu hohen Zeichenbox einen harten Seitenumbruch unabhängig vom
tatsächlich verbleibenden Platz auf der Seite - dadurch begann z.B.
der zweite Monat auf Seite 3, obwohl Seite 2 noch reichlich Platz
hatte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 22:42:29 +02:00
co-authored by Claude Sonnet 5
parent 861f2c76ca
commit 92e497b54f
2 changed files with 21 additions and 9 deletions
@@ -136,12 +136,18 @@ public static class StudentAbsenceDayListDrawingBuilder
commands.Add(new DrawStringEx(0, y, 10 * scale, contentWidth, studentName, commands.Add(new DrawStringEx(0, y, 10 * scale, contentWidth, studentName,
DrawingTextAlignment.AlignLeft, 8 * scale, Color: "#6B7280")); DrawingTextAlignment.AlignLeft, 8 * scale, Color: "#6B7280"));
y += 10 * scale + 2 * scale; y += 10 * scale + 2 * scale;
// Spaltenbreiten so gewählt, dass auch die Datenzeilen (nicht nur die kurzen Kopfzeilen-
// Labels) hineinpassen - "Datum" als Kopfzeile ist kürzer als "dd.MM.yyyy" und wurde bei
// 31 zu schmal bemessen, wodurch das Datum am rechten Rand abgeschnitten wurde.
const float dateColumnX = 2, dateColumnWidth = 38;
const float extentColumnX = 44, extentColumnWidth = 66;
const float statusColumnX = 114, statusColumnWidth = 54;
commands.Add(new DrawRectangle(0, y, contentWidth, rowHeight, "#CBD5E1", .4f, "#F3F4F6")); commands.Add(new DrawRectangle(0, y, contentWidth, rowHeight, "#CBD5E1", .4f, "#F3F4F6"));
commands.Add(new DrawStringEx(2, y + scale, rowHeight - scale, 31, "Datum", commands.Add(new DrawStringEx(dateColumnX, y + scale, rowHeight - scale, dateColumnWidth, "Datum",
DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true)); DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true));
commands.Add(new DrawStringEx(36, y + scale, rowHeight - scale, 75, "Umfang", commands.Add(new DrawStringEx(extentColumnX, y + scale, rowHeight - scale, extentColumnWidth, "Umfang",
DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true)); DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true));
commands.Add(new DrawStringEx(113, y + scale, rowHeight - scale, 55, "Status", commands.Add(new DrawStringEx(statusColumnX, y + scale, rowHeight - scale, statusColumnWidth, "Status",
DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true)); DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151", Bold: true));
y += rowHeight; y += rowHeight;
@@ -170,12 +176,12 @@ public static class StudentAbsenceDayListDrawingBuilder
: row.FriendlyStatusLabel; : row.FriendlyStatusLabel;
var statusColor = row.IsUnexcused ? "#C62828" : "#2E7D32"; var statusColor = row.IsUnexcused ? "#C62828" : "#2E7D32";
commands.Add(new DrawRectangle(0, y, contentWidth, rowHeight, "#E5E7EB", .3f, fill)); commands.Add(new DrawRectangle(0, y, contentWidth, rowHeight, "#E5E7EB", .3f, fill));
commands.Add(new DrawStringEx(2, y + scale, rowHeight - scale, 31, commands.Add(new DrawStringEx(dateColumnX, y + scale, rowHeight - scale, dateColumnWidth,
row.Date.ToString("dd.MM.yyyy"), DrawingTextAlignment.AlignLeft, 7.5f * scale, row.Date.ToString("dd.MM.yyyy"), DrawingTextAlignment.AlignLeft, 7.5f * scale,
Color: "#374151")); Color: "#374151"));
commands.Add(new DrawStringEx(36, y + scale, rowHeight - scale, 75, commands.Add(new DrawStringEx(extentColumnX, y + scale, rowHeight - scale, extentColumnWidth,
extent, DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151")); extent, DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: "#374151"));
commands.Add(new DrawStringEx(113, y + scale, rowHeight - scale, 55, commands.Add(new DrawStringEx(statusColumnX, y + scale, rowHeight - scale, statusColumnWidth,
status, DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: statusColor, status, DrawingTextAlignment.AlignLeft, 7.5f * scale, Color: statusColor,
Bold: row.IsUnexcused)); Bold: row.IsUnexcused));
y += rowHeight; y += rowHeight;
@@ -531,13 +531,19 @@ internal static class DrawingElementRenderer
}; };
container.Column(column => container.Column(column =>
{ {
for (var page = 0; page < pages.Count; page++) // Kein manueller PageBreak() zwischen den Ausschnitten: RenderFlow sitzt in einer
// ohnehin automatisch paginierenden Column (Flow-Dokument) bzw. füllt im Legacy-Modell
// fast die ganze Seite aus. Ein erzwungener Break hier sprang unabhängig vom
// tatsächlich verbleibenden Platz auf der aktuellen physischen Seite auf eine neue -
// z.B. begann der zweite Monat der Fehlzeitenliste auf Seite 3, obwohl auf Seite 2
// noch reichlich Platz war. QuestPDF schiebt einen Ausschnitt, der nicht mehr passt,
// ohnehin automatisch auf die nächste Seite.
foreach (var page in pages)
{ {
if (page > 0) column.Item().PageBreak();
// Koordinaten sind nach Slice()/RecordPages() bereits seitenlokal (bei 0 beginnend) - // Koordinaten sind nach Slice()/RecordPages() bereits seitenlokal (bei 0 beginnend) -
// kein zusätzlicher viewBox-Y-Offset nötig oder sinnvoll (siehe Slice()). // kein zusätzlicher viewBox-Y-Offset nötig oder sinnvoll (siehe Slice()).
column.Item().Height(UnitConverter.Points(pageHeight, unit)).Svg( column.Item().Height(UnitConverter.Points(pageHeight, unit)).Svg(
BuildSvg(pages[page], width, pageHeight, 0, unit)); BuildSvg(page, width, pageHeight, 0, unit));
} }
}); });
} }