reporter
This commit is contained in:
169
#10 Download reports/31 Report ordinace expenses.py
Normal file
169
#10 Download reports/31 Report ordinace expenses.py
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Expenses Ordinace – Report Generator (2025)
|
||||
------------------------------------------
|
||||
Reads JSON with tab definitions + SQL queries.
|
||||
Creates one Excel workbook with multiple sheets.
|
||||
Uniform formatting for all tabs.
|
||||
Deletes old reports before saving the new one.
|
||||
"""
|
||||
|
||||
import json
|
||||
import pandas as pd
|
||||
import pymysql
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
|
||||
from openpyxl.utils.dataframe import dataframe_to_rows
|
||||
|
||||
|
||||
# ==============================
|
||||
# CONFIG
|
||||
# ==============================
|
||||
|
||||
JSON_TABS = r"expenses_tabs.json"
|
||||
|
||||
MYSQL = {
|
||||
"host": "192.168.1.76",
|
||||
"port": 3307,
|
||||
"user": "root",
|
||||
"password": "Vlado9674+",
|
||||
"database": "fio",
|
||||
"charset": "utf8mb4"
|
||||
}
|
||||
|
||||
EXPORT_DIR = Path(r"z:\Dropbox\Ordinace\Reporty")
|
||||
EXPORT_DIR.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
# ==============================
|
||||
# DELETE OLD REPORTS (OPTION C)
|
||||
# ==============================
|
||||
|
||||
def delete_all_old_reports(directory: Path):
|
||||
"""Deletes all previously generated ordinace expense reports."""
|
||||
pattern = "*fio ordinace expenses.xlsx"
|
||||
deleted = 0
|
||||
|
||||
for f in directory.glob(pattern):
|
||||
try:
|
||||
f.unlink()
|
||||
deleted += 1
|
||||
print(f"🗑 Deleted old report: {f.name}")
|
||||
except Exception as e:
|
||||
print(f"❌ Could not delete {f.name}: {e}")
|
||||
|
||||
if deleted == 0:
|
||||
print("ℹ No old reports to delete.")
|
||||
else:
|
||||
print(f"✓ Deleted {deleted} old reports.")
|
||||
|
||||
|
||||
# ==============================
|
||||
# FORMATTING HELPERS
|
||||
# ==============================
|
||||
|
||||
def format_sheet(ws):
|
||||
"""Apply column widths, header styling, borders, autofilter."""
|
||||
|
||||
# Yellow header (Option A)
|
||||
header_fill = PatternFill("solid", fgColor="FFF200")
|
||||
bold_font = Font(bold=True, color="000000")
|
||||
center_align = Alignment(horizontal="center", vertical="center")
|
||||
|
||||
thin = Side(border_style="thin", color="000000")
|
||||
border = Border(left=thin, right=thin, top=thin, bottom=thin)
|
||||
|
||||
# Autofilter
|
||||
if ws.max_row > 1:
|
||||
ws.auto_filter.ref = ws.dimensions
|
||||
|
||||
# Auto column widths
|
||||
for col in ws.columns:
|
||||
max_len = 0
|
||||
letter = col[0].column_letter
|
||||
for cell in col:
|
||||
try:
|
||||
max_len = max(max_len, len(str(cell.value)))
|
||||
except Exception:
|
||||
pass
|
||||
ws.column_dimensions[letter].width = min(max_len + 2, 50)
|
||||
|
||||
# Style header row
|
||||
for cell in ws[1]:
|
||||
cell.font = bold_font
|
||||
cell.fill = header_fill
|
||||
cell.alignment = center_align
|
||||
cell.border = border
|
||||
|
||||
# Border for all body cells
|
||||
for row in ws.iter_rows(min_row=2):
|
||||
for cell in row:
|
||||
cell.border = border
|
||||
|
||||
|
||||
# ==============================
|
||||
# MAIN
|
||||
# ==============================
|
||||
|
||||
def main():
|
||||
print("=== Expenses Ordinace Report (with cleanup) ===")
|
||||
|
||||
# Load JSON tabs
|
||||
with open(JSON_TABS, "r", encoding="utf-8") as f:
|
||||
config = json.load(f)
|
||||
|
||||
tabs = config.get("tabs", [])
|
||||
print(f"Loaded {len(tabs)} tab definitions.")
|
||||
|
||||
# Connect DB
|
||||
conn = pymysql.connect(**MYSQL)
|
||||
|
||||
# Prepare workbook
|
||||
wb = Workbook()
|
||||
wb.remove(wb.active)
|
||||
|
||||
# Process each tab
|
||||
for tab in tabs:
|
||||
name = tab["name"]
|
||||
sql = tab["sql"]
|
||||
|
||||
print(f"→ Running tab: {name}")
|
||||
|
||||
df = pd.read_sql(sql, conn)
|
||||
df = df.fillna("")
|
||||
|
||||
# Swap columns N (index 13) and O (index 14)
|
||||
cols = df.columns.tolist()
|
||||
if len(cols) >= 15:
|
||||
cols[13], cols[14] = cols[14], cols[13]
|
||||
df = df[cols]
|
||||
|
||||
# Create sheet
|
||||
sheet_name = name[:31]
|
||||
ws = wb.create_sheet(sheet_name)
|
||||
|
||||
# Write DataFrame
|
||||
for row in dataframe_to_rows(df, index=False, header=True):
|
||||
ws.append(row)
|
||||
|
||||
# Apply formatting
|
||||
format_sheet(ws)
|
||||
|
||||
conn.close()
|
||||
|
||||
# Delete older reports
|
||||
delete_all_old_reports(EXPORT_DIR)
|
||||
|
||||
# Save new report
|
||||
OUTFILE = EXPORT_DIR / f"{datetime.now():%Y-%m-%d %H-%M-%S} FIO ordinace expenses.xlsx"
|
||||
wb.save(OUTFILE)
|
||||
|
||||
print(f"\n✔ Report generated:\n{OUTFILE}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user