This commit is contained in:
2025-05-26 18:28:43 +00:00
parent 507a6bd865
commit 14b2657cd8

View File

@@ -96,52 +96,34 @@ def create_google_doc_from_csv(service):
return None return None
requests = [] requests = []
# 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): for i, gruppe_original in enumerate(sorted_gruppen_namen):
kinder_liste = kinder_nach_gruppen[gruppe_original] # ... (kinder_liste, anzahl_kinder, gruppe_display_name) ...
anzahl_kinder = len(kinder_liste)
gruppe_display_name = gruppe_original + GRUPPENNAME_SUFFIX
# --- Seiten-Header --- # --- Seiten-Header ---
header_text_for_page = ( header_text_for_page = (
f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n" f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n"
f"{FOTODATUM}\n\n" f"{FOTODATUM}\n\n"
) )
# Wenn es die erste Seite ist, verwenden wir doc_cursor_index. if i == 0: # Nur für die allererste Seite einen expliziten Index
# Für nachfolgende Seiten könnte man endOfSegmentLocation verwenden, wenn der vorherige Block auch damit endete. requests.append({'insertText': {'location': {'index': 1}, 'text': header_text_for_page}})
# Wir versuchen, doc_cursor_index weiterzuführen. else: # Für Folgeseiten nach einem PageBreak
requests.append({'insertText': {'location': {'index': doc_cursor_index}, 'text': header_text_for_page}}) requests.append({'insertText': {'endOfSegmentLocation': {}, '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 # Tabelle wird nach dem Header eingefügt.
# Die Tabelle wird an der aktuellen Cursor-Position eingefügt. # Wenn Header mit EOS eingefügt wurde, wird Tabelle auch mit EOS eingefügt.
requests.append({ requests.append({
'insertTable': { 'insertTable': {
'location': {'index': doc_cursor_index}, 'endOfSegmentLocation': {}, # Fügt Tabelle am aktuellen Ende an
'rows': num_rows_for_table, 'rows': num_rows_for_table,
'columns': num_cols_for_table 'columns': num_cols_for_table
} }
}) })
# 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:
@@ -149,23 +131,17 @@ def create_google_doc_from_csv(service):
full_table_text = "\n".join(table_text_content) + "\n" full_table_text = "\n".join(table_text_content) + "\n"
# Füge den gesamten Tabelleninhalt ein. # Füge den gesamten Tabelleninhalt ein.
# Dies sollte in die zuletzt mit EOS erstellte Tabelle gehen.
requests.append({ requests.append({
'insertText': { 'insertText': {
'location': {'index': table_content_insertion_point}, 'endOfSegmentLocation': {},
'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 ---
footer_text_for_page = ( footer_text_for_page = (
f"\n{anzahl_kinder} angemeldete Kinder\n\n" # Start mit \n um sicher aus der Tabelle zu sein f"\n{anzahl_kinder} angemeldete Kinder\n\n"
"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"
@@ -173,7 +149,7 @@ def create_google_doc_from_csv(service):
) )
requests.append({ requests.append({
'insertText': { 'insertText': {
'endOfSegmentLocation': {}, # Fügt am Ende des aktuellen Haupttextkörpers ein 'endOfSegmentLocation': {},
'text': footer_text_for_page 'text': footer_text_for_page
} }
}) })
@@ -181,65 +157,16 @@ 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': {}}})
# WICHTIG: Für die nächste Iteration muss doc_cursor_index
# den Anfang des neuen Segments (nach dem PageBreak) repräsentieren.
# Wenn endOfSegmentLocation verwendet wurde, ist der nächste logische Einfügepunkt
# wieder "endOfSegmentLocation" oder der Index muss neu "gefunden" werden.
# Für den Header der NÄCHSTEN Seite setzen wir doc_cursor_index
# NICHT einfach auf 1, da das Dokument weiterläuft.
# Wenn wir endOfSegmentLocation für PageBreak und Footer verwenden,
# sollte der Header der nächsten Seite auch mit endOfSegmentLocation beginnen,
# ODER wir müssen den exakten Index nach dem PageBreak kennen.
# Da der nächste Header wieder 'location' verwendet, müssen wir den Index aktualisieren.
# Ein PageBreak fügt 1 zum Index hinzu. Der Footer hat eine Länge.
# Dies ist immer noch der heikle Teil.
# doc_cursor_index += len(footer_text_for_page) + 1 # Ungenau, da Tabelle dazwischen war.
# Da wir jetzt endOfSegmentLocation für Footer und PageBreak verwenden,
# ist der `doc_cursor_index` für den Header der nächsten Seite nicht mehr einfach weiterzuzählen.
# Wir müssen den Header der nächsten Seite auch mit `endOfSegmentLocation` einfügen,
# 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
if requests: if requests:
try: try:
print("Sende Batch Update an Google Docs API...") print("Sende Batch Update an Google Docs API...")
print("Anzahl der Requests:", len(requests)) print("Anzahl der Requests:", len(requests))
# Debug: Gib die ersten paar Requests aus, um zu sehen, ob sie logisch aussehen
# for req_idx, req_content in enumerate(requests[:6]):
# print(f"Request [{req_idx}]: {req_content}")
service.documents().batchUpdate( service.documents().batchUpdate(
documentId=document_id, body={'requests': requests} documentId=document_id, body={'requests': requests}
).execute() ).execute()
@@ -254,6 +181,10 @@ def create_google_doc_from_csv(service):
error_details = f"Fehler beim Dekodieren der Fehlerdetails: {e_decode}" error_details = f"Fehler beim Dekodieren der Fehlerdetails: {e_decode}"
print(f"Details zum Fehler ({err.resp.status} {err._get_reason()}): {error_details}") print(f"Details zum Fehler ({err.resp.status} {err._get_reason()}): {error_details}")
# Wenn es immer noch schiefgeht, alle Requests ausgeben:
# print("Alle gesendeten Requests:")
# for req_idx, req_content in enumerate(requests):
# print(f"Request [{req_idx}]: {req_content}")
return document_id return document_id