This commit is contained in:
2025-09-23 06:11:50 +02:00
parent 721787e46b
commit 3e55a36cb9
3 changed files with 279 additions and 0 deletions

136
10 Očkování chřipka.py Normal file
View File

@@ -0,0 +1,136 @@
#!/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
# ================== 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 ==================
# Pozn.: CAST(ockzaz.datum AS DATE) pro přesné párování na lecd.datose (DATE).
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",
/* --- VŠECHNY KÓDY Z TABULKY LECD PRO TOHO PACIENTA A TENTÝŽ DEN --- */
(
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)"
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 nazev containing 'chřipka'
and EXTRACT(YEAR FROM ockzaz.datum)=2025
ORDER BY ockzaz.datum DESC
"""
# ================== Načtení do DataFrame ==================
df = pd.read_sql(sql, con)
con.close()
# Textové sloupce jako string
for col in ["Kód MZ", "Šarže", "Rodné číslo", "Látka", "Název", "Příjmení", "Jméno", "LECD kódy (ten den)"]:
if col in df.columns:
df[col] = df[col].astype("string")
# Převod dat na datetime
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 ==================
with pd.ExcelWriter(xlsx_path, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="Očkování")
# ================== 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
# Hlavička vzhled
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")
# Freeze top row
ws.freeze_panes = "A2"
# Tabulka jen pokud jsou data
if max_row < 2:
autosize_columns(ws)
return
ref = f"A1:{get_column_letter(max_col)}{max_row}"
tbl = Table(displayName=table_name, 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"
ws_main = wb["Očkování"]
style_table(ws_main, "Ockovani")
format_dates(ws_main, ["Datum očkování", "Expirace"])
wb.save(xlsx_path)
print(f"Hotovo. Uloženo do: {xlsx_path}")

71
20 Medicus all tables.py Normal file
View File

@@ -0,0 +1,71 @@
import fdb
con = fdb.connect(
host='192.168.1.4',
database=r'z:\MEDICUS 3\data\medicus.FDB',
user='sysdba',
password='masterkey',
charset='WIN1250'
)
cur = con.cursor()
# Query all user tables and their columns
cur.execute("""
SELECT
rf.rdb$relation_name AS table_name,
rf.rdb$field_name AS column_name,
f.rdb$field_type AS field_type,
f.rdb$field_sub_type AS field_subtype,
f.rdb$field_length AS field_length,
f.rdb$field_precision AS field_precision,
f.rdb$field_scale AS field_scale,
f.rdb$null_flag AS not_null
FROM rdb$relation_fields rf
JOIN rdb$fields f ON rf.rdb$field_source = f.rdb$field_name
JOIN rdb$relations r ON rf.rdb$relation_name = r.rdb$relation_name
WHERE r.rdb$system_flag = 0 -- only user tables
ORDER BY rf.rdb$relation_name, rf.rdb$field_position
""")
# helper to translate Firebird numeric codes to SQL types
fb_types = {
7: "SMALLINT",
8: "INTEGER",
10: "FLOAT",
12: "DATE",
13: "TIME",
14: "CHAR",
16: "BIGINT/NUMERIC",
27: "DOUBLE",
35: "TIMESTAMP",
37: "VARCHAR",
261:"BLOB"
}
schema = {}
for row in cur.fetchall():
table = row[0].strip()
column = row[1].strip()
ftype = fb_types.get(row[2], f"TYPE{row[2]}")
subtype = row[3]
length = row[4]
precision = row[5]
scale = row[6]
not_null = bool(row[7])
# Build human-readable type
if ftype in ("CHAR","VARCHAR"):
dtype = f"{ftype}({length})"
elif ftype == "BIGINT/NUMERIC" and precision:
dtype = f"NUMERIC({precision},{-scale})"
else:
dtype = ftype
coldef = f"{column} {dtype}{' NOT NULL' if not_null else ''}"
schema.setdefault(table, []).append(coldef)
# Pretty print
for t, cols in schema.items():
print(f"\nTable: {t}")
for c in cols:
print(" ", c)

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import fdb
CODE = "0255910"
con = fdb.connect(
host='192.168.1.4',
database=r'z:\MEDICUS 3\data\medicus.FDB',
user='sysdba',
password='masterkey',
charset='WIN1250'
)
cur = con.cursor()
# --- find every user-table column defined as CHAR(7) ---
cur.execute("""
SELECT
TRIM(rf.rdb$relation_name) AS table_name,
TRIM(rf.rdb$field_name) AS column_name
FROM rdb$relation_fields rf
JOIN rdb$fields f
ON rf.rdb$field_source = f.rdb$field_name
JOIN rdb$relations r
ON rf.rdb$relation_name = r.rdb$relation_name
WHERE
r.rdb$system_flag = 0 -- only user tables
AND r.rdb$view_blr IS NULL -- exclude views
AND f.rdb$field_type = 14 -- CHAR
AND f.rdb$field_length = 7 -- exactly CHAR(7)
ORDER BY rf.rdb$relation_name, rf.rdb$field_position
""")
columns = cur.fetchall()
matches = []
# --- check each CHAR(7) column for exact match ---
for table_name, column_name in columns:
sql_count = f'''
SELECT COUNT(*)
FROM "{table_name}"
WHERE "{column_name}" = ?
'''
try:
cur.execute(sql_count, (CODE,))
cnt = cur.fetchone()[0]
except Exception as e:
print(f"Skipped {table_name}.{column_name}: {e}")
continue
if cnt > 0:
sql_sample = f'''
SELECT FIRST 5 "{column_name}"
FROM "{table_name}"
WHERE "{column_name}" = ?
'''
cur.execute(sql_sample, (CODE,))
samples = [s.strip() if s else "" for (s,) in cur.fetchall()]
matches.append((table_name, column_name, int(cnt), samples))
# --- report ---
if not matches:
print(f'No exact matches for "{CODE}" in any CHAR(7) column.')
else:
print(f'Exact matches for "{CODE}" in CHAR(7) columns:')
for t, c, cnt, samples in matches:
print(f' - {t}.{c}: {cnt} row(s)')
for s in samples:
print(f' sample: {s}')
con.close()