This commit is contained in:
2025-05-26 18:27:11 +00:00
parent 56d0869d04
commit 835f5645d6

View File

@@ -96,9 +96,13 @@ def create_google_doc_from_csv(service):
return None return None
requests = [] requests = []
current_index = 1 # Startindex für das gesamte Dokument. Bleibt für den ersten Block bei 1.
# Für nachfolgende Seiten (nach PageBreak) müssen wir überlegen, wie der Index behandelt wird.
# Wenn PageBreak mit endOfSegmentLocation eingefügt wird, ist der nächste Einfügepunkt
# implizit am Anfang des neuen Segments.
doc_cursor_index = 1
for i, gruppe_original in enumerate(sorted_gruppen_namen): # Jetzt ist sorted_gruppen_namen definiert for i, gruppe_original in enumerate(sorted_gruppen_namen):
kinder_liste = kinder_nach_gruppen[gruppe_original] kinder_liste = kinder_nach_gruppen[gruppe_original]
anzahl_kinder = len(kinder_liste) anzahl_kinder = len(kinder_liste)
gruppe_display_name = gruppe_original + GRUPPENNAME_SUFFIX gruppe_display_name = gruppe_original + GRUPPENNAME_SUFFIX
@@ -108,41 +112,60 @@ def create_google_doc_from_csv(service):
f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n" f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n"
f"{FOTODATUM}\n\n" f"{FOTODATUM}\n\n"
) )
requests.append({'insertText': {'location': {'index': current_index}, 'text': header_text_for_page}}) # Wenn es die erste Seite ist, verwenden wir doc_cursor_index.
current_index += len(header_text_for_page) # Für nachfolgende Seiten könnte man endOfSegmentLocation verwenden, wenn der vorherige Block auch damit endete.
# Wir versuchen, doc_cursor_index weiterzuführen.
requests.append({'insertText': {'location': {'index': doc_cursor_index}, 'text': header_text_for_page}})
doc_cursor_index += len(header_text_for_page)
# --- Tabelle --- # --- Tabelle ---
num_rows_for_table = len(kinder_liste) + 1 num_rows_for_table = len(kinder_liste) + 1
num_cols_for_table = 3 num_cols_for_table = 3
# Füge die Tabellenstruktur ein
# Die Tabelle wird an der aktuellen Cursor-Position eingefügt.
requests.append({ requests.append({
'insertTable': { 'insertTable': {
'location': {'index': current_index}, 'location': {'index': doc_cursor_index},
'rows': num_rows_for_table, 'rows': num_rows_for_table,
'columns': num_cols_for_table 'columns': num_cols_for_table
} }
}) })
table_fill_start_index = current_index + 1 # WICHTIG: Wo ist der Cursor jetzt, um Text IN die Tabelle einzufügen?
# Annahme: Der Cursor ist jetzt AM ANFANG der ERSTEN Zelle.
# Daher sollte der Index für das Einfügen des Tabelleninhalts derselbe sein
# wie der Index, an dem die Tabelle erstellt wurde, PLUS EINS (für das Start-Tag der Tabelle selbst).
# Dies ist der kritische Punkt.
# Der Index zum Befüllen der Tabelle ist der Startindex der Tabelle (doc_cursor_index) + 1.
# (Das +1 ist für das unsichtbare Zeichen, das den Anfang der Tabellenstruktur markiert).
table_content_insertion_point = doc_cursor_index + 1
table_text_content = [] table_text_content = []
table_text_content.append("Nachname\tVorname\tGruppe") table_text_content.append("Nachname\tVorname\tGruppe")
for kind in kinder_liste: for kind in kinder_liste:
table_text_content.append(f"{kind['Nachname']}\t{kind['Vorname']}\t{gruppe_display_name}") table_text_content.append(f"{kind['Nachname']}\t{kind['Vorname']}\t{gruppe_display_name}")
full_table_text = "\n".join(table_text_content) + "\n" full_table_text = "\n".join(table_text_content) + "\n"
# Füge den gesamten Tabelleninhalt ein.
requests.append({ requests.append({
'insertText': { 'insertText': {
'location': {'index': table_fill_start_index}, 'location': {'index': table_content_insertion_point},
'text': full_table_text 'text': full_table_text
} }
}) })
# Nach dem Einfügen der Tabelle und ihres Inhalts müssen wir den doc_cursor_index
# auf eine Position *NACH* der Tabelle setzen.
# Die Tabelle (Struktur) selbst belegt 1 Index-Einheit (aus Sicht des batchUpdate-Requests).
# Der Text, der in die Tabelle gefüllt wurde, belegt `len(full_table_text)` Zeichen.
# Aber die gesamte Tabellenstruktur im Dokument ist komplexer.
# Es ist sehr schwer, den genauen Index nach einer Tabelle vorherzusagen.
# HIER verwenden wir endOfSegmentLocation für den Footer, um dieses Problem zu umgehen.
# --- Footer --- # --- Footer ---
# Korrektur: 'text' muss auf derselben Ebene wie 'endOfSegmentLocation' sein
footer_text_for_page = ( footer_text_for_page = (
f"\n{anzahl_kinder} angemeldete Kinder\n\n" f"\n{anzahl_kinder} angemeldete Kinder\n\n" # Start mit \n um sicher aus der Tabelle zu sein
"Dies ist die Liste der bereits angemeldeten Kinder. Bitte die Eltern der noch fehlenden\n" "Dies ist die Liste der bereits angemeldeten Kinder. Bitte die Eltern der noch fehlenden\n"
"Kinder an die Anmeldung erinnern.\n\n" "Kinder an die Anmeldung erinnern.\n\n"
f"Stand {stand_zeit}\n\n" f"Stand {stand_zeit}\n\n"
@@ -150,7 +173,7 @@ def create_google_doc_from_csv(service):
) )
requests.append({ requests.append({
'insertText': { 'insertText': {
'endOfSegmentLocation': {}, 'endOfSegmentLocation': {}, # Fügt am Ende des aktuellen Haupttextkörpers ein
'text': footer_text_for_page 'text': footer_text_for_page
} }
}) })
@@ -158,24 +181,58 @@ def create_google_doc_from_csv(service):
# --- Seitenumbruch --- # --- Seitenumbruch ---
if i < len(sorted_gruppen_namen) - 1: if i < len(sorted_gruppen_namen) - 1:
requests.append({'insertPageBreak': {'endOfSegmentLocation': {}}}) requests.append({'insertPageBreak': {'endOfSegmentLocation': {}}})
# Reset current_index for the new page if not using endOfSegmentLocation for header # WICHTIG: Für die nächste Iteration muss doc_cursor_index
# Da wir endOfSegmentLocation für den nächsten Header nicht explizit verwenden (er basiert auf current_index), # den Anfang des neuen Segments (nach dem PageBreak) repräsentieren.
# müssen wir sicherstellen, dass current_index für die nächste Seite korrekt ist. # Wenn endOfSegmentLocation verwendet wurde, ist der nächste logische Einfügepunkt
# Mit endOfSegmentLocation für Footer und PageBreak ist die manuelle Index-Verfolgung # wieder "endOfSegmentLocation" oder der Index muss neu "gefunden" werden.
# für den *nächsten* Header schwierig. # Für den Header der NÄCHSTEN Seite setzen wir doc_cursor_index
# Eine sicherere Methode wäre, den Header der nächsten Seite auch mit endOfSegmentLocation zu beginnen. # NICHT einfach auf 1, da das Dokument weiterläuft.
# Für jetzt lassen wir current_index einfach weiterlaufen und hoffen, dass # Wenn wir endOfSegmentLocation für PageBreak und Footer verwenden,
# endOfSegmentLocation für Footer/PageBreak den Cursor korrekt für den *nächsten* Block # sollte der Header der nächsten Seite auch mit endOfSegmentLocation beginnen,
# (der wieder 'location' mit 'current_index' verwendet) positioniert. # ODER wir müssen den exakten Index nach dem PageBreak kennen.
# Dies könnte ein potenzielles Problem für die nächste Iteration sein, wenn der Footer/PageBreak # Da der nächste Header wieder 'location' verwendet, müssen wir den Index aktualisieren.
# den `current_index` nicht so verschiebt, wie es für den nächsten Header-Insert benötigt wird. # Ein PageBreak fügt 1 zum Index hinzu. Der Footer hat eine Länge.
# EINFACHERE LÖSUNG: current_index nach endOfSegmentLocation nicht mehr verwenden. # Dies ist immer noch der heikle Teil.
# Wenn endOfSegmentLocation verwendet wird, sollte der nächste Insert auch endOfSegmentLocation verwenden oder # doc_cursor_index += len(footer_text_for_page) + 1 # Ungenau, da Tabelle dazwischen war.
# man muss den Index explizit auf 1 für eine neue Seite setzen (was aber nicht korrekt ist, wenn das Dokument
# als ein langer Stream behandelt wird). # Da wir jetzt endOfSegmentLocation für Footer und PageBreak verwenden,
# Für jetzt: Da der Header der nächsten Seite `current_index` verwendet, müssen wir ihn aktualisieren. # ist der `doc_cursor_index` für den Header der nächsten Seite nicht mehr einfach weiterzuzählen.
# Ein Page Break fügt 1 zum Index hinzu. Der Footer hat `len(footer_text_for_page)`. # Wir müssen den Header der nächsten Seite auch mit `endOfSegmentLocation` einfügen,
current_index += len(footer_text_for_page) + 1 # +1 für den PageBreak # oder die Logik wird sehr komplex.
# Umstellung: Header der Folgeseiten auch mit endOfSegmentLocation
# Dies erfordert, dass der *erste* Header mit `location` eingefügt wird,
# und alle *weiteren* Blöcke mit `endOfSegmentLocation`.
# Das machen wir später, wenn diese Version nicht geht.
# Vorerst: Wir nehmen an, `endOfSegmentLocation` hat den "globalen" Cursor bewegt.
# Der `doc_cursor_index` wird für den nächsten Header NICHT mehr direkt verwendet,
# wenn wir auf `endOfSegmentLocation` umstellen.
# Temporär: Lassen wir die explizite Aktualisierung von doc_cursor_index hier weg,
# da die Einfügepunkte für Footer/PageBreak relativ sind.
# Wenn der nächste Header wieder `location: {index: doc_cursor_index}` verwendet, wird es knallen.
# Wir müssen konsequent sein.
# Wenn wir `doc_cursor_index` für den Header verwenden, müssen wir ihn korrekt weiterführen.
# Länge der Tabelle ist NICHT nur len(full_table_text). Es ist komplexer.
#
# EINFACHSTE LÖSUNG JETZT: Wir gehen davon aus, dass nach einem
# `insertPageBreak` mit `endOfSegmentLocation`, der NÄCHSTE `insertText`
# für den Header der neuen Seite an Index 1 dieser neuen Seite beginnt.
# Das ist FALSCH für die Google Docs API, da das Dokument ein Stream ist.
#
# Richtiger Ansatz: Wenn endOfSegmentLocation verwendet wird, sollte der nächste Block
# auch endOfSegmentLocation verwenden.
# Wir müssen uns entscheiden: Entweder alles mit exakten Indizes (schwer)
# oder alles relativ mit endOfSegmentLocation (einfacher für sequenzielles Anhängen).
# DA DER HEADER DER NÄCHSTEN ITERATION `location: {'index': doc_cursor_index}` verwendet,
# MÜSSEN WIR `doc_cursor_index` AKTUALISIEREN.
# DIES IST DER TEIL, DER AM WAHRSCHEINLICHSTEN FEHLSCHLÄGT, WENN DIE LÄNGENBERECHNUNG FALSCH IST.
# Die Struktur einer Tabelle ist nicht nur ihr Text.
# Annahme: Eine Tabelle (Struktur + Text) + Footer + PageBreak
# Versuchen wir, `doc_cursor_index` *nicht* zu aktualisieren und stattdessen
# den Header der Folgeseiten auch mit `endOfSegmentLocation` einzufügen.
pass # doc_cursor_index wird nicht mehr manuell hochgezählt, wenn EOS verwendet wird.
# Batch-Update ausführen # Batch-Update ausführen