#!/usr/bin/env python3 import cgi import cgitb import pandas as pd from openpyxl import Workbook from openpyxl.styles import Alignment, Border, Font, PatternFill, Side from openpyxl.utils import get_column_letter from datetime import datetime from io import StringIO import os import shutil cgitb.enable() print("Content-Type: text/html") print() form = cgi.FieldStorage() title = form.getvalue('title') detail = form.getvalue('detail') csv_content = form.getvalue('csv_content') program_descriptions = { "C": form.getvalue('desc_C', "Program naplnujici cile"), "S": form.getvalue('desc_S', "Program pro podporu skupinove dynamiky"), "K": form.getvalue('desc_K', "Kreativni program"), "P": form.getvalue('desc_P', "Provozni blok"), "O": form.getvalue('desc_O', "Vyplnove a ostatni programy"), } program_colors = { "C": 'FF' + form.getvalue('color_C', "ADD8E6").lstrip('#'), "S": 'FF' + form.getvalue('color_S', "90EE90").lstrip('#'), "K": 'FF' + form.getvalue('color_K', "FFFF00").lstrip('#'), "P": 'FF' + form.getvalue('color_P', "D3D3D3").lstrip('#'), "O": 'FF' + form.getvalue('color_O', "FFB6C1").lstrip('#'), } def read_csv_from_string(csv_string): return pd.read_csv(StringIO(csv_string), sep=";", header=None, names=["Datum", "Zacatek", "Konec", "Program", "Typ", "Garant", "Poznamka"]) def calculate_row_height(cell_value, column_width): if not cell_value: return 15 max_line_length = column_width * 1.2 lines = cell_value.split('\n') line_count = 0 for line in lines: line_count += len(line) // max_line_length + 1 return line_count * 15 def create_timetable(data, title, detail, program_descriptions, program_colors): wb = Workbook() ws = wb.active thick_border = Border(left=Side(style='thick', color='000000'), right=Side(style='thick', color='000000'), top=Side(style='thick', color='000000'), bottom=Side(style='thick', color='000000')) ws['A1'] = title ws['A1'].alignment = Alignment(horizontal="center", vertical="center") ws['A1'].font = Font(size=24, bold=True) ws['A1'].border = thick_border ws['A2'] = detail ws['A2'].alignment = Alignment(horizontal="center", vertical="center") ws['A2'].font = Font(size=16, italic=True) ws['A2'].border = thick_border # Nastavení výšky řádků pro nadpis a podnadpis title_row_height = calculate_row_height(title, ws.column_dimensions[get_column_letter(1)].width) detail_row_height = calculate_row_height(detail, ws.column_dimensions[get_column_letter(1)].width) ws.row_dimensions[1].height = title_row_height ws.row_dimensions[2].height = detail_row_height data["Datum"] = pd.to_datetime(data["Datum"], format="%d.%m.%Y") data = data.sort_values(by=["Datum", "Zacatek"]) start_times = data["Zacatek"].apply(lambda x: datetime.strptime(str(x), '%H%M')) end_times = data["Konec"].apply(lambda x: datetime.strptime(str(x), '%H%M')) min_time = start_times.min() max_time = end_times.max() time_slots = pd.date_range(min_time, max_time, freq='15min').time total_columns = len(time_slots) + 1 ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=total_columns) ws.merge_cells(start_row=2, start_column=1, end_row=2, end_column=total_columns) row_offset = 3 col_offset = 1 cell = ws.cell(row=row_offset, column=col_offset, value="Datum") cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3", fill_type="solid") cell.alignment = Alignment(horizontal="center", vertical="center") cell.font = Font(bold=True) cell.border = thick_border for i, time_slot in enumerate(time_slots, start=col_offset + 1): cell = ws.cell(row=row_offset, column=i, value=time_slot.strftime("%H:%M")) cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3", fill_type="solid") cell.alignment = Alignment(horizontal="center", vertical="center") cell.font = Font(bold=True) cell.border = thick_border current_row = row_offset + 1 grouped_data = data.groupby(data['Datum']) for date, group in grouped_data: day_name = date.strftime("%A") date_str = date.strftime(f"%d.%m {day_name}") cell = ws.cell(row=current_row, column=col_offset, value=date_str) cell.alignment = Alignment(horizontal="center", vertical="center") cell.fill = PatternFill(start_color="D3D3D3", end_color="D3D3D3", fill_type="solid") cell.font = Font(bold=True, size=14) cell.border = thick_border for _, row in group.iterrows(): start_time = datetime.strptime(str(row["Zacatek"]), '%H%M').time() end_time = datetime.strptime(str(row["Konec"]), '%H%M').time() start_index = list(time_slots).index(start_time) + col_offset + 1 end_index = list(time_slots).index(end_time) + col_offset + 1 cell_value = f"{row['Program']}" if pd.notna(row['Garant']): cell_value += f"\n{row['Garant']}" if pd.notna(row['Poznamka']): cell_value += f"\n\n{row['Poznamka']}" ws.merge_cells(start_row=current_row, start_column=start_index, end_row=current_row, end_column=end_index - 1) cell = ws.cell(row=current_row, column=start_index) cell.value = cell_value cell.alignment = Alignment(wrap_text=True, horizontal="center", vertical="center") lines = cell_value.split("\n") for idx, line in enumerate(lines): if idx == 0: cell.font = Font(bold=True) elif idx == 1: cell.font = Font(bold=False) elif idx > 1 and pd.notna(row['Poznamka']): cell.font = Font(italic=True) cell.fill = PatternFill(start_color=program_colors[row["Typ"]], end_color=program_colors[row["Typ"]], fill_type="solid") cell.border = thick_border current_row += 1 legend_row = current_row + 2 legend_max_length = 0 ws.cell(row=legend_row, column=1, value="Legenda:").font = Font(bold=True) legend_row += 1 for typ, desc in program_descriptions.items(): legend_text = f"{desc} ({typ})" legend_cell = ws.cell(row=legend_row, column=1, value=legend_text) legend_cell.fill = PatternFill(start_color=program_colors[typ], fill_type="solid") legend_max_length = max(legend_max_length, calculate_column_width(legend_text)) legend_row += 1 ws.column_dimensions[get_column_letter(col_offset)].width = legend_max_length for col in range(2, total_columns + 1): ws.column_dimensions[get_column_letter(col)].width = 15 for row in ws.iter_rows(min_row=1, max_row=current_row - 1, min_col=1, max_col=total_columns): for cell in row: cell.alignment = Alignment(wrap_text=True, horizontal="center", vertical="center") cell.border = thick_border for row in ws.iter_rows(min_row=1, max_row=current_row - 1): max_height = 0 for cell in row: if cell.value: height = calculate_row_height(cell.value, ws.column_dimensions[get_column_letter(cell.column)].width) if height > max_height: max_height = height ws.row_dimensions[row[0].row].height = max_height return wb def calculate_column_width(text): max_length = max(len(line) for line in text.split('\n')) return max_length * 1.2 data = read_csv_from_string(csv_content) wb = create_timetable(data, title, detail, program_descriptions, program_colors) filename = f"{title}.xlsx" file_path = f"/var/www/htdocs/{filename}" wb.save(file_path) print(f'Stahnout scenar pro {title} ZDE')