This commit is contained in:
2025-10-17 14:25:39 +02:00
parent 53c5584852
commit f3e94ef49d
2 changed files with 308 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
import time
import fdb
import pandas as pd
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils import get_column_letter
# ================== Výstupní cesta ==================
BASE_DIR = Path(r"..") # uprav dle potřeby
timestamp = time.strftime("%Y-%m-%d %H-%M-%S")
xlsx_name = f"Pacienti očkování {timestamp}.xlsx"
xlsx_path = BASE_DIR / xlsx_name
# ================== Definice skupin vakcín ==================
SHEETS = {
"COVID-19": ["commirnaty", "spikevax", "nuvaxovid"],
"Chřipka": ["vaxigrip", "influvac", "fluarix", "afluria"],
"Klíšťová encefalitida": ["fsme", "encepur"],
"Tetanus": ["tetavax", "boostrix", "adacel"],
"HepA": ["avaxim", "havrix"],
"HepB": ["engerix"],
"HepA+B": ["twinrix"]
}
# ================== Připojení k DB ==================
con = fdb.connect(
host='192.168.1.4',
database=r'z:\\MEDICUS 3\\data\\medicus.FDB',
user='sysdba',
password='masterkey',
charset='WIN1250'
)
# ================== SQL dotaz ==================
sql = """
SELECT
kar.rodcis AS "Rodné číslo",
kar.prijmeni AS "Příjmení",
kar.jmeno AS "Jméno",
ockzaz.datum AS "Datum očkování",
ockzaz.kodmz AS "Kód MZ",
ockzaz.poznamka AS "Šarže",
ockzaz.latka AS "Látka",
ockzaz.nazev AS "Název",
ockzaz.expire AS "Expirace",
(
SELECT LIST(l.kod, ', ')
FROM lecd l
WHERE l.rodcis = kar.rodcis
AND l.datose = CAST(ockzaz.datum AS DATE)
) AS "LECD kódy (ten den)",
(
SELECT LIST(d.kod, ', ')
FROM dokladd d
WHERE d.rodcis = kar.rodcis
AND d.datose = CAST(ockzaz.datum AS DATE)
) AS "Výkony (ten den)"
FROM registr
JOIN kar ON registr.idpac = kar.idpac
JOIN ockzaz ON registr.idpac = ockzaz.idpac
WHERE
registr.datum_zruseni IS NULL
AND kar.vyrazen <> 'A'
AND kar.rodcis IS NOT NULL
AND idicp <> 0
AND EXTRACT(YEAR FROM ockzaz.datum) = 2025
ORDER BY ockzaz.datum DESC
"""
# ================== Načtení do DataFrame ==================
df = pd.read_sql(sql, con)
con.close()
# ================== Datové typy ==================
for col in ["Kód MZ", "Šarže", "Rodné číslo", "Látka", "Název", "Příjmení", "Jméno", "LECD kódy","Výkony"]:
if col in df.columns:
df[col] = df[col].astype("string")
for dcol in ["Datum očkování", "Expirace"]:
if dcol in df.columns:
df[dcol] = pd.to_datetime(df[dcol], errors="coerce")
# ================== Uložení do Excelu více listů ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
for sheet_name, vakciny in SHEETS.items():
print(sheet_name,vakciny)
mask = df["Látka"].str.contains('|'.join(vakciny), case=False, na=False)
df_filtered = df[mask]
if not df_filtered.empty:
df_filtered.to_excel(writer, index=False, sheet_name=sheet_name)
# navíc celkový přehled všech očkování
df.to_excel(writer, index=False, sheet_name="Vše")
# ================== Formátování ==================
wb = load_workbook(xlsx_path)
def autosize_columns(ws):
for col_idx in range(1, ws.max_column + 1):
col_letter = get_column_letter(col_idx)
max_len = 0
for cell in ws[col_letter]:
val = "" if cell.value is None else str(cell.value)
if len(val) > max_len:
max_len = len(val)
ws.column_dimensions[col_letter].width = min(max(12, max_len + 2), 60)
def style_table(ws, table_name: str):
max_row = ws.max_row
max_col = ws.max_column
if max_col == 0:
return
header_fill = PatternFill("solid", fgColor="D9E1F2")
for cell in ws[1]:
cell.font = Font(bold=True)
cell.fill = header_fill
cell.alignment = Alignment(vertical="center")
ws.freeze_panes = "A2"
if max_row < 2:
autosize_columns(ws)
return
ref = f"A1:{get_column_letter(max_col)}{max_row}"
tbl = Table(displayName=table_name.replace(" ", "_"), ref=ref)
tbl.tableStyleInfo = TableStyleInfo(
name="TableStyleMedium9", showRowStripes=True, showColumnStripes=False
)
ws.add_table(tbl)
autosize_columns(ws)
def format_dates(ws, columns_names):
header = [c.value for c in ws[1]]
date_cols = [header.index(name) + 1 for name in columns_names if name in header]
for col_idx in date_cols:
for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx, max_row=ws.max_row):
row[0].number_format = "DD.MM.YYYY"
for ws in wb.worksheets:
style_table(ws, ws.title)
format_dates(ws, ["Datum očkování", "Expirace"])
wb.save(xlsx_path)
print(f"✅ Hotovo. Uloženo do: {xlsx_path.resolve()}")

View File

@@ -0,0 +1,157 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
import time
import fdb
import pandas as pd
import re
from openpyxl import load_workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.styles import Font, PatternFill, Alignment
from openpyxl.utils import get_column_letter
# ================== Výstupní cesta ==================
BASE_DIR = Path(r"..") # uprav dle potřeby
timestamp = time.strftime("%Y-%m-%d %H-%M-%S")
xlsx_name = f"Pacienti očkování {timestamp}.xlsx"
xlsx_path = BASE_DIR / xlsx_name
# ================== Definice skupin vakcín ==================
SHEETS = {
"COVID-19": ["commirnaty", "spikevax", "nuvaxovid"],
"Chřipka": ["vaxigrip", "influvac", "fluarix", "afluria"],
"Klíšťová encefalitida": ["fsme", "encepur"],
"Tetanus": ["tetavax", "boostrix", "adacel"],
"HepA": ["avaxim", "havrix"],
"HepB": ["engerix"],
"HepA+B": ["twinrix"],
}
# ================== Připojení k DB ==================
con = fdb.connect(
host='192.168.1.4',
database=r'z:\\MEDICUS 3\\data\\medicus.FDB',
user='sysdba',
password='masterkey',
charset='WIN1250'
)
# ================== SQL dotaz ==================
sql = """
SELECT
kar.rodcis AS "Rodné číslo",
kar.prijmeni AS "Příjmení",
kar.jmeno AS "Jméno",
ockzaz.datum AS "Datum očkování",
ockzaz.kodmz AS "Kód MZ",
ockzaz.poznamka AS "Šarže",
ockzaz.latka AS "Látka",
ockzaz.nazev AS "Název",
ockzaz.expire AS "Expirace",
(
SELECT LIST(l.kod, ', ')
FROM lecd l
WHERE l.rodcis = kar.rodcis
AND l.datose = CAST(ockzaz.datum AS DATE)
) AS "LECD kódy (ten den)",
(
SELECT LIST(d.kod, ', ')
FROM dokladd d
WHERE d.rodcis = kar.rodcis
AND d.datose = CAST(ockzaz.datum AS DATE)
) AS "Výkony (ten den)"
FROM registr
JOIN kar ON registr.idpac = kar.idpac
JOIN ockzaz ON registr.idpac = ockzaz.idpac
WHERE
registr.datum_zruseni IS NULL
AND kar.vyrazen <> 'A'
AND kar.rodcis IS NOT NULL
AND idicp <> 0
AND EXTRACT(YEAR FROM ockzaz.datum) = 2025
ORDER BY ockzaz.datum DESC
"""
# ================== Načtení do DataFrame ==================
df = pd.read_sql(sql, con)
con.close()
# ================== Datové typy ==================
for col in ["Kód MZ", "Šarže", "Rodné číslo", "Látka", "Název", "Příjmení", "Jméno", "LECD kódy", "Výkony"]:
if col in df.columns:
df[col] = df[col].astype("string")
for dcol in ["Datum očkování", "Expirace"]:
if dcol in df.columns:
df[dcol] = pd.to_datetime(df[dcol], errors="coerce")
# ================== Uložení do Excelu více listů ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
for sheet_name, vakciny in SHEETS.items():
pattern = "|".join(re.escape(v) for v in vakciny if v)
mask = df["Látka"].astype(str).str.contains(pattern, case=False, na=False)
df_filtered = df[mask]
if not df_filtered.empty:
df_filtered.to_excel(writer, index=False, sheet_name=sheet_name)
# navíc celkový přehled všech očkování
df.to_excel(writer, index=False, sheet_name="Vše")
# ================== Formátování ==================
wb = load_workbook(xlsx_path)
def autosize_columns(ws):
for col_idx in range(1, ws.max_column + 1):
col_letter = get_column_letter(col_idx)
max_len = 0
for cell in ws[col_letter]:
val = "" if cell.value is None else str(cell.value)
if len(val) > max_len:
max_len = len(val)
ws.column_dimensions[col_letter].width = min(max(12, max_len + 2), 60)
def safe_table_name(sheet_name):
"""Return an Excel-safe, unique table name."""
name = re.sub(r"[^0-9A-Za-z_]", "_", sheet_name)
return f"tbl_{name[:25]}"
def style_table(ws):
max_row = ws.max_row
max_col = ws.max_column
if max_col == 0:
return
header_fill = PatternFill("solid", fgColor="D9E1F2")
for cell in ws[1]:
cell.font = Font(bold=True)
cell.fill = header_fill
cell.alignment = Alignment(vertical="center")
ws.freeze_panes = "A2"
if max_row < 2:
autosize_columns(ws)
return
ref = f"A1:{get_column_letter(max_col)}{max_row}"
tbl = Table(displayName=safe_table_name(ws.title), ref=ref)
tbl.tableStyleInfo = TableStyleInfo(
name="TableStyleMedium9", showRowStripes=True, showColumnStripes=False
)
ws.add_table(tbl)
autosize_columns(ws)
def format_dates(ws, columns_names):
header = [c.value for c in ws[1]]
date_cols = [header.index(name) + 1 for name in columns_names if name in header]
for col_idx in date_cols:
for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx, max_row=ws.max_row):
row[0].number_format = "DD.MM.YYYY"
for ws in wb.worksheets:
style_table(ws)
format_dates(ws, ["Datum očkování", "Expirace"])
wb.save(xlsx_path)
print(f"✅ Hotovo. Uloženo do: {xlsx_path.resolve()}")