# -*- coding: utf-8 -*- # ============================================================================= # Nazev: report_77242113UCO2001_v1.2.py # Verze: 1.2 # Datum: 2026-06-19 # Popis: Generator Excel reportu z Mongo feasibility.investigators. # v1.2 - pridan PRVNI list "Prehled KROK": A=KROK, B=pocet, # C=seznam jmen zkousejicich (oddeleno strednikem) v jedne bunce. # List Investigators nasleduje jako druhy. # v1.1 - sloupec KROK hned pred STATUS + barevne odliseni dle KROK. # Projekt: 77242113UCO2001 (DAWN / spravny kod 77242113UCO3002) # Vystup: u:\Dropbox\!!!Days\Downloads Z230\ (verzovany nazev s timestampem) # ============================================================================= import os from datetime import datetime from pymongo import MongoClient import openpyxl from openpyxl.styles import Font, PatternFill, Alignment, Border, Side from openpyxl.utils import get_column_letter # --- Připojení k MongoDB --- MONGO_URI = os.environ.get("MONGO_URI", "mongodb://192.168.1.76:27017") client = MongoClient(MONGO_URI) db = client["feasibility"] col = db["investigators"] # --- Načtení dat --- docs = list(col.find({})) print(f"Načteno {len(docs)} záznamů.") # --- Cílová složka --- OUTPUT_DIR = r"u:\Dropbox\!!!Days\Downloads Z230" os.makedirs(OUTPUT_DIR, exist_ok=True) datum = datetime.now().strftime("%Y%m%d_%H%M") filename = f"77242113UCO2001_investigators_{datum}.xlsx" filepath = os.path.join(OUTPUT_DIR, filename) # --- Definice sloupců --- # Pořadí: jméno, email, KROK, STATUS, kriticka_poznamka, pak ostatní # KROK je ZÁMĚRNĚ hned PŘED STATUS. FIXED_COLS = [ ("prijmeni", "Příjmení"), ("jmeno", "Jméno"), ("email", "Email"), ("KROK", "KROK"), ("STATUS", "STATUS"), ("kriticka_poznamka", "Kritická poznámka"), ("zeme", "Země"), ("pracoviste", "Pracoviště"), ("internet_summary","Internet summary"), ] # Klíče, které přeskočíme (složité nested objekty) SKIP_KEYS = {"_id", "excel", "sites_illuminator", "maf", "zdroje", "studie", "Viper_Performance", "Viper_Contacts", "cda", "history", "zpracovane_emaily", "sipiq"} # Ostatní skalární pole fixed_keys = {c[0] for c in FIXED_COLS} extra_keys = set() for doc in docs: for k in doc.keys(): if k not in fixed_keys and k not in SKIP_KEYS: extra_keys.add(k) extra_keys = sorted(extra_keys) ALL_COLS = FIXED_COLS + [(k, k) for k in extra_keys] # --- Barvy podle KROK --- def krok_color(krok): if not krok: return None k = krok.strip() if k.startswith("5") or k.startswith("6") or k.startswith("7"): return "FFC6EFCE" # zelená - CDA podepsáno / SIPIQ if k.startswith("4"): return "FFB7E1CD" # tmavší zelená - CDA vyžádáno if k.startswith("3.1"): return "FFDDEBF7" # světle modrá - zájem if k.startswith("3.2"): return "FFFFC7CE" # červená - nezájem if k.startswith("2"): return "FFFFF2CC" # světle žlutá - připomenuto if k.startswith("1"): return "FFDCE6F1" # modrá - nabídka odeslána if k.startswith("0"): return "FFD9D9D9" # šedá - mimo return None # --- Pomocná funkce: setřídění KROK dle čísla prefixu --- def krok_sort_key(krok): k = (krok or "").strip() num = "" for ch in k: if ch.isdigit() or ch == ".": num += ch else: break try: return (0, float(num)) if num else (1, 0.0) except ValueError: return (1, 0.0) # --- Agregace pro přehledový list --- def cele_jmeno(doc): p = (doc.get("prijmeni") or "").strip() j = (doc.get("jmeno") or "").strip() return (p + " " + j).strip() or "(bez jména)" skupiny = {} # krok -> list jmen for doc in docs: krok = str(doc.get("KROK", "") or "").strip() or "(nezařazeno)" skupiny.setdefault(krok, []).append(cele_jmeno(doc)) prehled_rows = [] for krok in sorted(skupiny, key=krok_sort_key): jmena = sorted(skupiny[krok]) prehled_rows.append((krok, len(jmena), "; ".join(jmena))) # --- Styly --- header_font = Font(bold=True, color="FFFFFFFF") header_fill = PatternFill("solid", fgColor="FF1F4E79") header_align = Alignment(horizontal="center", vertical="center", wrap_text=True) cell_align = Alignment(vertical="top", wrap_text=True) thin = Side(style="thin", color="FFB0B0B0") border = Border(left=thin, right=thin, top=thin, bottom=thin) # --- Vytvoření workbooku --- wb = openpyxl.Workbook() # === LIST 1: Přehled KROK === ws_p = wb.active ws_p.title = "Přehled KROK" PREHLED_COLS = [("KROK", 30), ("Počet", 10), ("Zkoušející (jména)", 120)] for col_idx, (label, w) in enumerate(PREHLED_COLS, 1): c = ws_p.cell(row=1, column=col_idx, value=label) c.font = header_font c.fill = header_fill c.alignment = header_align c.border = border ws_p.column_dimensions[get_column_letter(col_idx)].width = w ws_p.row_dimensions[1].height = 26 for r, (krok, pocet, jmena) in enumerate(prehled_rows, 2): bg = krok_color(krok) vals = [krok, pocet, jmena] for col_idx, val in enumerate(vals, 1): c = ws_p.cell(row=r, column=col_idx, value=val) c.alignment = cell_align c.border = border if bg: c.fill = PatternFill("solid", fgColor=bg) if col_idx == 1: c.font = Font(bold=True) if col_idx == 2: c.alignment = Alignment(horizontal="center", vertical="top") # Řádek CELKEM tot_r = len(prehled_rows) + 2 ws_p.cell(row=tot_r, column=1, value="CELKEM").font = Font(bold=True) tc = ws_p.cell(row=tot_r, column=2, value=sum(p for _, p, _ in prehled_rows)) tc.font = Font(bold=True) tc.alignment = Alignment(horizontal="center") for col_idx in range(1, 4): ws_p.cell(row=tot_r, column=col_idx).border = border ws_p.freeze_panes = "A2" ws_p.auto_filter.ref = f"A1:C{len(prehled_rows) + 1}" # === LIST 2: Investigators === ws = wb.create_sheet("Investigators") # Záhlaví for col_idx, (key, label) in enumerate(ALL_COLS, 1): cell = ws.cell(row=1, column=col_idx, value=label) cell.font = header_font cell.fill = header_fill cell.alignment = header_align cell.border = border ws.row_dimensions[1].height = 30 # Data for row_idx, doc in enumerate(docs, 2): krok_val = str(doc.get("KROK", "") or "") bg = krok_color(krok_val) for col_idx, (key, label) in enumerate(ALL_COLS, 1): val = doc.get(key, "") if isinstance(val, list): val = ", ".join(str(v) for v in val) elif isinstance(val, dict): val = str(val) elif val is None: val = "" else: val = str(val) cell = ws.cell(row=row_idx, column=col_idx, value=val) cell.alignment = cell_align cell.border = border if bg: cell.fill = PatternFill("solid", fgColor=bg) if key == "KROK": cell.font = Font(bold=True) # Šířky sloupců col_widths = { "prijmeni": 18, "jmeno": 15, "email": 35, "KROK": 26, "STATUS": 45, "kriticka_poznamka": 60, "zeme": 12, "pracoviste": 35, "internet_summary": 60, } for col_idx, (key, label) in enumerate(ALL_COLS, 1): w = col_widths.get(key, 20) ws.column_dimensions[get_column_letter(col_idx)].width = w ws.freeze_panes = "A2" ws.auto_filter.ref = ws.dimensions # --- Uložení --- wb.save(filepath) print(f"Ulozeno: {filepath}") print(f"List 1 'Přehled KROK': {len(prehled_rows)} kroků, celkem {sum(p for _,p,_ in prehled_rows)} zkoušejících.") print("List 2 'Investigators':", len(docs), "radku.")