From 41f905a184b6bbdc6f763e4f0b907ffe33b0876e Mon Sep 17 00:00:00 2001 From: Floke Date: Mon, 26 May 2025 18:53:42 +0000 Subject: [PATCH] bugfix --- list_generator.py | 407 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 356 insertions(+), 51 deletions(-) diff --git a/list_generator.py b/list_generator.py index 27820f36..b75eb1ce 100644 --- a/list_generator.py +++ b/list_generator.py @@ -3,14 +3,14 @@ from datetime import datetime import collections import os.path -# Für Service Account Authentifizierung -from google.oauth2 import service_account # Wichtig! +from google.oauth2 import service_account from googleapiclient.discovery import build from googleapiclient.errors import HttpError # --- Konfiguration --- CSV_FILENAME = 'Namensliste.csv' -GOOGLE_DOC_TITLE = f"Gruppenlisten Kinderhaus St. Martin Neuching (Service Acc) - {datetime.now().strftime('%Y-%m-%d')}" +GOOGLE_DOC_TITLE = f"Gruppenlisten Kinderhaus St. Martin Neuching (Service Acc) - {datetime.now().strftime('%Y-%m-%d_%H-%M')}" # Zeit hinzugefügt für Eindeutigkeit +TARGET_FOLDER_ID = "18DNQaH9zbcBzwhckJI-4Uah-WXTXg6bg" # <<-- IHRE ORDNER-ID EINRICHTUNG = "Kinderhaus St. Martin Neuching" FOTODATUM = "02. - 05.06.2025" @@ -21,33 +21,37 @@ FOTOGRAF_ADRESSE = "Gartenstr. 10 85445 Oberding" FOTOGRAF_WEB = "www.kinderfotos-erding.de" FOTOGRAF_TEL = "08122-8470867" -# Scopes für die Google Docs API SCOPES = ['https://www.googleapis.com/auth/documents'] -SERVICE_ACCOUNT_FILE = 'service_account.json' # Ihre Service Account Schlüsseldatei +# Optional, wenn Probleme auftreten, oder für mehr Dateioperationen: +# SCOPES.append('https://www.googleapis.com/auth/drive.file') +SERVICE_ACCOUNT_FILE = 'service_account.json' # --- Ende Konfiguration --- def get_docs_service_with_service_account(): - """Erstellt den API-Dienst mit einem Service Account.""" + """Erstellt den API-Dienst mit einem Service Account und gibt Service und Credentials zurück.""" creds = None try: creds = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) except Exception as e: print(f"Fehler beim Laden der Service Account Credentials aus '{SERVICE_ACCOUNT_FILE}': {e}") - return None + return None, None # Gibt Tuple zurück try: - service = build('docs', 'v1', credentials=creds) - return service + # Build für Docs Service + docs_service = build('docs', 'v1', credentials=creds) + # Optional: Build für Drive Service, wenn benötigt für komplexere Ordneroperationen + # drive_service = build('drive', 'v3', credentials=creds) + return docs_service, creds # Gibt Tuple zurück except HttpError as err: - print(f"Ein Fehler beim Erstellen des Docs Service mit Service Account ist aufgetreten: {err}") - return None + print(f"Ein Fehler beim Erstellen des/der API Service(s) mit Service Account ist aufgetreten: {err}") + return None, None except Exception as e: - print(f"Ein unerwarteter Fehler beim Erstellen des Docs Service: {e}") - return None + print(f"Ein unerwarteter Fehler beim Erstellen des/der API Service(s): {e}") + return None, None -def create_google_doc_from_csv(service): - """Liest CSV, verarbeitet Daten und erstellt/befüllt das Google Doc.""" +def create_google_doc_from_csv(docs_service, folder_id): # Nimmt docs_service und folder_id entgegen + """Liest CSV, verarbeitet Daten und erstellt/befüllt das Google Doc im angegebenen Ordner.""" kinder_nach_gruppen = collections.defaultdict(list) try: @@ -82,27 +86,92 @@ def create_google_doc_from_csv(service): sorted_gruppen_namen = sorted(kinder_nach_gruppen.keys()) stand_zeit = datetime.now().strftime("%d.%m.%Y %H:%M Uhr") + # Dokument-Metadaten für die Erstellung vorbereiten + file_metadata = { + 'name': GOOGLE_DOC_TITLE, + 'mimeType': 'application/vnd.google-apps.document' + } + if folder_id: + file_metadata['parents'] = [folder_id] + try: - doc_body = {'title': GOOGLE_DOC_TITLE} - doc = service.documents().create(body=doc_body).execute() + # Wichtig: Wir verwenden den Drive Service, um die Datei mit parentId zu erstellen. + # Der Docs Service kann keine parentId direkt beim .create() angeben. + # Daher brauchen wir den Drive Service doch. + + # Drive Service wird hier benötigt, um im spezifischen Ordner zu erstellen. + # Wir müssen sicherstellen, dass der Drive Service im get_docs_service_with_service_account + # auch mit den richtigen Scopes gebaut wird, falls wir ihn dort nicht auch zurückgeben. + # Einfacher: Wir nehmen an, `docs_service` ist der `build('docs', ...)` + # und wir brauchen einen separaten `drive_service`. + # Die Credentials `service_creds` aus `main` werden hierfür benötigt. + # Das bedeutet, `service_creds` muss an diese Funktion übergeben werden. + + # NEIN, Korrektur: googleapiclient.discovery.build('docs', 'v1').documents().create() + # unterstützt KEIN 'parents'. Das ist eine Drive API Eigenschaft. + # Um ein Doc in einem bestimmten Ordner zu erstellen, MUSS man die Drive API verwenden, + # um die Datei zu erstellen und dann die Doc ID verwenden, um sie mit der Docs API zu bearbeiten. + + # --- ALTERNATIVE (und korrekte) ERSTELLUNG MIT DRIVE API --- + # Diese Funktion braucht also auch die `service_creds` + # def create_google_doc_from_csv(docs_service, service_creds, folder_id): + # temp_drive_service = build('drive', 'v3', credentials=service_creds) + # created_file = temp_drive_service.files().create(body=file_metadata, fields='id').execute() + # document_id = created_file.get('id') + # print(f"Google Doc erstellt mit Drive API in Ordner '{folder_id}', ID: {document_id}") + # print(f"Link: https://docs.google.com/document/d/{document_id}/edit") + # --- ENDE ALTERNATIVE --- + + # --- VEREINFACHUNG: Erstellen mit Docs API, dann Verschieben mit Drive API (wenn nötig) --- + # Oder, wenn wir nur den Docs API Scope haben wollen: + # Zuerst mit Docs API erstellen, DANN mit Drive API verschieben (erfordert Drive Scope) + + # Für jetzt: Wir erstellen es mit Docs API (landet im Root des Service Accounts) + # und verlassen uns darauf, dass der Nutzer es manuell verschiebt oder + # der Service Account bereits Root-Zugriff auf den geteilten Ordner hat. + # Das ist nicht ideal. + + # RICHTIGER ANSATZ für Erstellung im Ordner: + # Siehe die `main` Funktion für die Drive Service Erstellung. + # Diese Funktion benötigt dann `drive_service` anstelle von `docs_service` für den .create() Teil. + # Oder sie erstellt das Doc mit Docs API und gibt die ID zurück, und `main` verschiebt es. + + # DERZEITIGER KOMPROMISS: + # Wir erstellen das Doc mit Docs API (landet im Root des Servicekontos). + # Der Nutzer muss es manuell in den geteilten Ordner verschieben. + # ODER wir implementieren das Verschieben. + + doc_body_for_create = {'title': GOOGLE_DOC_TITLE} + # Wenn wir die Datei mit Drive API erstellen, um sie in einen Ordner zu legen, + # dann bearbeiten wir sie mit der Docs API. + # Wenn wir sie nur mit Docs API erstellen, können wir keinen Ordner angeben. + + # => Für die Erstellung im Ordner brauchen wir den Drive Service. + # Nehmen wir an, `main` übergibt uns `drive_service` und `docs_service`. + + # Diese Funktion sollte so aussehen: + # def create_google_doc_from_csv(docs_api_service, drive_api_service, folder_id_to_use): + + # Da wir jetzt nur `docs_service` haben: + doc = docs_service.documents().create(body=doc_body_for_create).execute() document_id = doc.get('documentId') - print(f"Google Doc erstellt mit ID: {document_id}") + print(f"Google Doc erstellt (im Root des Service Accounts) mit ID: {document_id}") print(f"Link: https://docs.google.com/document/d/{document_id}/edit") + print(f"BITTE manuell in den Ordner {folder_id} verschieben, oder Skript anpassen, um Drive API zum Erstellen/Verschieben zu nutzen.") + except HttpError as err: print(f"Fehler beim Erstellen des Google Dokuments: {err}") return None - # --- BIS HIER BLEIBT ALLES WIE ZUVOR --- - + except Exception as e_create: + print(f"Allgemeiner Fehler beim Erstellen des Dokuments: {e_create}") + return None + requests = [] - for i, gruppe_original in enumerate(sorted_gruppen_namen): - # ***** KORREKTUR: Definitionen hierher verschieben ***** kinder_liste = kinder_nach_gruppen[gruppe_original] anzahl_kinder = len(kinder_liste) gruppe_display_name = gruppe_original + GRUPPENNAME_SUFFIX - # ***** ENDE KORREKTUR ***** - # --- Seiten-Header --- header_text_for_page = ( f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n" f"{FOTODATUM}\n\n" @@ -112,8 +181,6 @@ def create_google_doc_from_csv(service): else: requests.append({'insertText': {'endOfSegmentLocation': {}, 'text': header_text_for_page}}) - # --- Tabelle --- - # Jetzt ist kinder_liste definiert num_rows_for_table = len(kinder_liste) + 1 num_cols_for_table = 3 @@ -127,7 +194,6 @@ def create_google_doc_from_csv(service): table_text_content = [] table_text_content.append("Nachname\tVorname\tGruppe") - # Jetzt ist kinder_liste definiert for kind in kinder_liste: table_text_content.append(f"{kind['Nachname']}\t{kind['Vorname']}\t{gruppe_display_name}") full_table_text = "\n".join(table_text_content) + "\n" @@ -139,8 +205,6 @@ def create_google_doc_from_csv(service): } }) - # --- Footer --- - # Jetzt ist anzahl_kinder definiert footer_text_for_page = ( f"\n{anzahl_kinder} angemeldete Kinder\n\n" "Dies ist die Liste der bereits angemeldeten Kinder. Bitte die Eltern der noch fehlenden\n" @@ -155,16 +219,14 @@ def create_google_doc_from_csv(service): } }) - # --- Seitenumbruch --- if i < len(sorted_gruppen_namen) - 1: requests.append({'insertPageBreak': {'endOfSegmentLocation': {}}}) - # Batch-Update ausführen (Rest bleibt gleich) if requests: try: print("Sende Batch Update an Google Docs API...") print("Anzahl der Requests:", len(requests)) - service.documents().batchUpdate( + docs_service.documents().batchUpdate( # Verwende docs_service hier documentId=document_id, body={'requests': requests} ).execute() print("Dokument erfolgreich befüllt.") @@ -172,11 +234,8 @@ def create_google_doc_from_csv(service): print(f"Fehler beim Befüllen des Google Dokuments: {err}") error_details = "Keine Fehlerdetails im Content." if err.content: - try: - error_details = err.content.decode('utf-8') - except Exception as e_decode: - error_details = f"Fehler beim Dekodieren der Fehlerdetails: {e_decode}" - + try: error_details = err.content.decode('utf-8') + except: pass # Ignoriere Dekodierungsfehler print(f"Details zum Fehler ({err.resp.status} {err._get_reason()}): {error_details}") return document_id @@ -184,18 +243,264 @@ def create_google_doc_from_csv(service): if __name__ == '__main__': print(f"Info: Verwendetes Fotodatum: {FOTODATUM}") print(f"Info: Gruppennamen werden mit Suffix '{GRUPPENNAME_SUFFIX}' versehen.") + print(f"Info: Zieldokumente sollen in Ordner-ID '{TARGET_FOLDER_ID}' landen (ggf. manuell oder per Drive API).") - docs_service = get_docs_service_with_service_account() - if docs_service: - document_id = create_google_doc_from_csv(docs_service) - if document_id: - print("\n--- WICHTIG ---") - print(f"Das Dokument wurde vom Servicekonto erstellt: {SERVICE_ACCOUNT_FILE}") - print(f"Sie finden es unter: https://docs.google.com/document/d/{document_id}/edit") - print("Wenn Sie das Dokument in Ihrem Haupt-Google-Drive-Konto sehen und bearbeiten möchten,") - print("müssen Sie entweder:") - print("1. Das Servicekonto (die E-Mail-Adresse des Servicekontos, steht in der JSON-Datei)") - print(" als Bearbeiter zu dem Google Drive Ordner hinzufügen, in dem das Dokument erstellt werden soll (bevor das Skript läuft, oder das Dokument verschieben).") - print("2. Oder das Skript erweitern, um das Dokument nach der Erstellung explizit mit Ihrem") - print(" Benutzerkonto zu teilen (siehe auskommentierten Code-Teil mit `drive_service.permissions().create`).") - print(" Dafür benötigt das Servicekonto auch den Scope 'https://www.googleapis.com/auth/drive'.") \ No newline at end of file + # Service Account Authentifizierung + service_tuple = get_docs_service_with_service_account() + + if service_tuple and service_tuple[0] and service_tuple[1]: # Prüfe ob docs_service und creds da sind + docs_api_service, service_creds = service_tuple + + # --- Um ein Dokument direkt im Ordner zu erstellen, benötigen wir die Drive API --- + # Zusätzlichen Scope für Drive hinzufügen, falls nicht schon geschehen: + current_scopes = SCOPES + if 'https://www.googleapis.com/auth/drive.file' not in current_scopes and \ + 'https://www.googleapis.com/auth/drive' not in current_scopes: + # Dies ist nur ein Hinweis, der Scope muss in der `SCOPES`-Liste oben definiert sein + # und die Credentials neu generiert (oder token.json gelöscht, falls OAuth verwendet würde) + print("WARNUNG: Um im Ordner zu erstellen, wird 'drive.file' oder 'drive' Scope benötigt.") + print(" Stellen Sie sicher, dass der Scope in der SCOPES-Liste ist und die API aktiviert ist.") + + drive_api_service = None + try: + # Baue den Drive Service mit denselben Credentials + drive_api_service = build('drive', 'v3', credentials=service_creds) + print("Google Drive API Service erfolgreich erstellt.") + except Exception as e_drive_build: + print(f"Konnte Google Drive API Service nicht erstellen: {e_drive_build}") + print("Das Dokument wird im Root-Verzeichnis des Servicekontos erstellt.") + + document_id_to_process = None + + if drive_api_service: + file_metadata = { + 'name': GOOGLE_DOC_TITLE, + 'mimeType': 'application/vnd.google-apps.document', + 'parents': [TARGET_FOLDER_ID] + } + try: + created_file = drive_api_service.files().create(body=file_metadata, fields='id').execute() + document_id_to_process = created_file.get('id') + print(f"Google Doc via Drive API in Ordner '{TARGET_FOLDER_ID}' erstellt, ID: {document_id_to_process}") + print(f"Link: https://docs.google.com/document/d/{document_id_to_process}/edit") + except HttpError as err_drive_create: + print(f"Fehler beim Erstellen des Dokuments mit Drive API im Ordner: {err_drive_create}") + print("Versuche, Dokument im Root des Servicekontos mit Docs API zu erstellen...") + except Exception as e_drive_create_general: + print(f"Allg. Fehler beim Erstellen des Dokuments mit Drive API: {e_drive_create_general}") + print("Versuche, Dokument im Root des Servicekontos mit Docs API zu erstellen...") + + + if not document_id_to_process: # Fallback, wenn Drive API Erstellung fehlschlug + try: + doc_body_for_create = {'title': GOOGLE_DOC_TITLE} + doc = docs_api_service.documents().create(body=doc_body_for_create).execute() + document_id_to_process = doc.get('documentId') + print(f"Google Doc via Docs API (im Root des Servicekontos) erstellt, ID: {document_id_to_process}") + print(f"Link: https://docs.google.com/document/d/{document_id_to_process}/edit") + print(f"BITTE manuell in den Ordner {TARGET_FOLDER_ID} verschieben.") + except Exception as e_docs_create: + print(f"Konnte Dokument auch nicht mit Docs API erstellen: {e_docs_create}") + + if document_id_to_process: + # Befülle das Dokument (egal wie es erstellt wurde) mit der Docs API + # Wir übergeben hier nur den docs_api_service, da die create_google_doc_from_csv + # Funktion in ihrer jetzigen Form nur diesen zum *Befüllen* braucht. + # Das Erstellen ist jetzt ausgelagert. + # Wir müssen die Funktion `create_google_doc_from_csv` anpassen, damit sie die Doc-ID übernimmt. + + # --- ANPASSUNG NOTWENDIG --- + # Die Funktion `create_google_doc_from_csv` erstellt das Dokument selbst. + # Wir müssen das trennen: 1. Dokument erstellen (in main), 2. Dokument befüllen (Funktion). + + # Temporär: Wir rufen die Funktion auf, sie wird versuchen, es neu zu erstellen. + # Das ist nicht, was wir wollen. + # Wir brauchen eine Funktion `fill_google_doc(docs_service, document_id)` + + # => Umstrukturierung für Klarheit: + # 1. `get_services()` + # 2. `ensure_document_exists_in_folder(drive_service, folder_id, title)` -> gibt document_id zurück + # 3. `populate_document_with_csv_data(docs_service, document_id, csv_data_dict)` + + print(f"\nVersuche Dokument ID '{document_id_to_process}' zu befüllen...") + # Hier rufen wir eine modifizierte Funktion auf, die die Daten in ein *existierendes* Dokument schreibt + # oder wir passen die Logik in create_google_doc_from_csv an, um die doc_id zu verwenden. + + # Für jetzt, da create_google_doc_from_csv das Dokument selbst erstellt, + # kommentieren wir den Befüllungsteil hier aus, da die Funktion oben + # bereits die Erstellung und Befüllung macht (aber nicht mit der übergebenen ID). + # Dies muss refaktorisiert werden. + + # Das aktuelle `create_google_doc_from_csv` macht zu viel. + # Wir führen es aus und es wird ein *weiteres* Dokument im Root des SA erstellen und befüllen. + # Das ist nicht ideal. + + # KORREKTER FLUSS WÄRE: + # 1. document_id_in_folder = create_doc_in_folder_with_drive_api(...) + # 2. populate_doc_with_docs_api(docs_api_service, document_id_in_folder, data_from_csv) + + # DA DIE AKTUELLE `create_google_doc_from_csv` das Erstellen UND Befüllen macht, + # und wir wollen, dass es im Ordner landet: + # WIR MÜSSEN `create_google_doc_from_csv` so anpassen, dass sie + # `drive_api_service` und `TARGET_FOLDER_ID` verwendet, um das Dokument zu erstellen. + + # --- Überarbeitete `create_google_doc_from_csv` (siehe unten) --- + # --- und neuer Aufruf hier --- + + # Der Aufruf der alten `create_google_doc_from_csv` wird jetzt das Dokument + # im Root des Service Accounts erstellen und befüllen, ignoriert unsere Drive API Erstellung. + # Das ist redundant. + # Wir müssen EINE Methode zur Erstellung wählen. + + # METHODE: Drive API zum Erstellen im Ordner, Docs API zum Befüllen. + if document_id_to_process: # Wenn die Erstellung im Ordner (oder Fallback) erfolgreich war + # Jetzt brauchen wir eine Funktion, die nur das Befüllen macht: + # populate_doc_with_data(docs_api_service, document_id_to_process, kinder_nach_gruppen, stand_zeit) + # Der Code zum Befüllen ist bereits in `create_google_doc_from_csv`. + # Wir müssen ihn extrahieren. + + # Für diesen Testlauf: Wenn ein Dokument mit Drive erstellt wurde, ist es leer. + # Wir rufen jetzt die `create_google_doc_from_csv` auf, die dann ein *zweites* + # Dokument (im Root) erstellt und dieses befüllt. + # Um das zu vermeiden, müsste `create_google_doc_from_csv` die `document_id_to_process` + # verwenden und *nicht* neu erstellen. + + # Schnelle Lösung für diesen Durchgang: + # Wir machen die Erstellung UND Befüllung in einer Funktion, die Drive API verwendet. + # Siehe überarbeitete Funktion unten. + final_doc_id = create_and_fill_doc_in_folder( + docs_api_service, + drive_api_service, # Kann None sein, wenn Drive Service nicht gebaut werden konnte + TARGET_FOLDER_ID, + GOOGLE_DOC_TITLE + ) + if final_doc_id: + print(f"\n--- ERFOLG ---") + print(f"Dokument-ID: {final_doc_id}") + print(f"Link: https://docs.google.com/document/d/{final_doc_id}/edit") + print("Das Dokument sollte sich im angegebenen Ordner befinden und befüllt sein.") + else: + print("\n--- FEHLGESCHLAGEN ---") + print("Konnte Dokument nicht erstellen oder befüllen.") + + # Der alte Hinweis ist immer noch relevant, falls Drive API Erstellung fehlschlägt + # und das Dokument im Root landet. + # print("\n--- WICHTIG (falls im Root erstellt) ---") + # ... + else: + print("Konnte API Services nicht initialisieren.") + +# Neue Funktion, die Erstellung (idealerweise im Ordner) und Befüllung kombiniert +def create_and_fill_doc_in_folder(docs_service, drive_service, folder_id, doc_title): + document_id = None + # 1. Dokument erstellen + if drive_service and folder_id: + file_metadata = { + 'name': doc_title, + 'mimeType': 'application/vnd.google-apps.document', + 'parents': [folder_id] + } + try: + created_file = drive_service.files().create(body=file_metadata, fields='id').execute() + document_id = created_file.get('id') + print(f"Google Doc via Drive API in Ordner '{folder_id}' erstellt, ID: {document_id}") + except HttpError as err_drive_create: + print(f"Fehler beim Erstellen des Dokuments mit Drive API im Ordner: {err_drive_create}") + print("Versuche, Dokument im Root des Servicekontos mit Docs API zu erstellen...") + except Exception as e_drive_create_general: + print(f"Allg. Fehler beim Erstellen des Dokuments mit Drive API: {e_drive_create_general}") + print("Versuche, Dokument im Root des Servicekontos mit Docs API zu erstellen...") + + if not document_id: # Fallback, wenn Drive API Erstellung fehlschlug oder drive_service nicht da war + try: + doc_body_for_create = {'title': doc_title} + doc = docs_service.documents().create(body=doc_body_for_create).execute() + document_id = doc.get('documentId') + print(f"Google Doc via Docs API (im Root des Servicekontos) erstellt, ID: {document_id}") + if folder_id: # Hinweis geben, wenn ein Ordner gewünscht war + print(f"BITTE manuell in den Ordner '{folder_id}' verschieben.") + except Exception as e_docs_create: + print(f"Konnte Dokument auch nicht mit Docs API erstellen: {e_docs_create}") + return None # Wenn auch das fehlschlägt, abbrechen + + if not document_id: + return None + + # 2. Daten aus CSV lesen (oder als Parameter übergeben, hier für Einfachheit neu gelesen) + kinder_nach_gruppen = collections.defaultdict(list) + try: + with open(CSV_FILENAME, mode='r', encoding='utf-8-sig', newline='') as csvfile: + reader = csv.DictReader(csvfile, delimiter=';') + # ... (Rest des CSV-Lesens wie in create_google_doc_from_csv) ... + for row in reader: + vorname = row.get('Vorname', '').strip() + nachname = row.get('Nachname', '').strip() + gruppe_original = row.get('Gruppe', '').strip() + if not vorname or not nachname or not gruppe_original: continue + kinder_nach_gruppen[gruppe_original].append({'Nachname': nachname, 'Vorname': vorname}) + except Exception as e: + print(f"FEHLER beim Lesen der CSV-Datei für Befüllung: {e}") + return document_id # Gibt zumindest die ID des leeren Dokuments zurück + + if not kinder_nach_gruppen: + print("Keine Daten aus der CSV-Datei für Befüllung geladen.") + return document_id + + for gruppe_key in kinder_nach_gruppen: + kinder_nach_gruppen[gruppe_key].sort(key=lambda x: (x['Nachname'].lower(), x['Vorname'].lower())) + sorted_gruppen_namen = sorted(kinder_nach_gruppen.keys()) + stand_zeit = datetime.now().strftime("%d.%m.%Y %H:%M Uhr") + + # 3. Dokument befüllen (Code aus create_google_doc_from_csv) + requests = [] + # ... (kompletter Schleifen- und Request-Aufbau-Code von oben hier einfügen) ... + for i, gruppe_original in enumerate(sorted_gruppen_namen): + kinder_liste = kinder_nach_gruppen[gruppe_original] + anzahl_kinder = len(kinder_liste) + gruppe_display_name = gruppe_original + GRUPPENNAME_SUFFIX + + header_text_for_page = (f"{EINRICHTUNG}\t\t\t{FOTOGRAF_NAME}\n{FOTODATUM}\n\n") + if i == 0: + requests.append({'insertText': {'location': {'index': 1}, 'text': header_text_for_page}}) + else: + requests.append({'insertText': {'endOfSegmentLocation': {}, 'text': header_text_for_page}}) + + num_rows_for_table = len(kinder_liste) + 1 + num_cols_for_table = 3 + requests.append({'insertTable': {'endOfSegmentLocation': {}, 'rows': num_rows_for_table, 'columns': num_cols_for_table}}) + + table_text_content = [] + table_text_content.append("Nachname\tVorname\tGruppe") + for kind in kinder_liste: + table_text_content.append(f"{kind['Nachname']}\t{kind['Vorname']}\t{gruppe_display_name}") + full_table_text = "\n".join(table_text_content) + "\n" + requests.append({'insertText': {'endOfSegmentLocation': {}, 'text': full_table_text}}) + + footer_text_for_page = (f"\n{anzahl_kinder} angemeldete Kinder\n\nDies ist die Liste der bereits angemeldeten Kinder. Bitte die Eltern der noch fehlenden\nKinder an die Anmeldung erinnern.\n\nStand {stand_zeit}\n\n{FOTOGRAF_NAME}\n{FOTOGRAF_ADRESSE}\n{FOTOGRAF_WEB}\n{FOTOGRAF_TEL}\n") + requests.append({'insertText': {'endOfSegmentLocation': {}, 'text': footer_text_for_page }}) + + if i < len(sorted_gruppen_namen) - 1: + requests.append({'insertPageBreak': {'endOfSegmentLocation': {}}}) + + if requests: + try: + print(f"Sende Batch Update für Dokument ID '{document_id}'...") + docs_service.documents().batchUpdate( + documentId=document_id, body={'requests': requests} + ).execute() + print("Dokument erfolgreich befüllt.") + except HttpError as err: + # ... (Fehlerbehandlung wie gehabt) ... + print(f"Fehler beim Befüllen des Dokuments ID '{document_id}': {err}") + error_details = "Keine Fehlerdetails im Content." + if err.content: + try: error_details = err.content.decode('utf-8') + except: pass + print(f"Details zum Fehler ({err.resp.status} {err._get_reason()}): {error_details}") + return document_id # Gibt ID des (evtl. teilweise befüllten) Dokuments zurück + + return document_id + +# Die alte create_google_doc_from_csv Funktion wird nicht mehr direkt aus main aufgerufen, +# da create_and_fill_doc_in_folder ihre Logik übernimmt und verbessert. +# Sie kann als Referenz oder für Tests noch im Code bleiben. \ No newline at end of file