wrote template for trainingsplan

This commit is contained in:
2026-03-20 13:13:29 +01:00
parent 4be223390c
commit 3a59c38ad6
3 changed files with 256 additions and 1 deletions

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@
.venv
*.txt
*temp/
*.xlsx
########################################################################################
# project specific gitignore entries

View File

@@ -0,0 +1,251 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 11,
"id": "efde98a5",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import datetime as dt\n",
"import openpyxl.styles"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "8e84cb92",
"metadata": {},
"outputs": [],
"source": [
"def get_week_boundary(target_date, boundary='first'):\n",
" \"\"\"\n",
" Returns the Monday (first) or Sunday (last) of the week for a given date.\n",
" \n",
" :param target_date: datetime object\n",
" :param boundary: 'first' or 'last'\n",
" :return: datetime object\n",
" \"\"\"\n",
" # .weekday() returns 0 for Monday, 6 for Sunday\n",
" days_since_monday = target_date.weekday()\n",
" \n",
" if boundary == 'first':\n",
" return target_date - dt.timedelta(days=days_since_monday)\n",
" elif boundary == 'last':\n",
" days_until_sunday = 6 - days_since_monday\n",
" return target_date + dt.timedelta(days=days_until_sunday)\n",
" else:\n",
" raise ValueError(\"Boundary must be 'first' or 'last'\")"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "7a9ce99f",
"metadata": {},
"outputs": [],
"source": [
"year = 2026\n",
"\n",
"date_index = pd.date_range(get_week_boundary(dt.datetime(year,1,1),'first'),get_week_boundary(dt.datetime(year,12,31),'last'),freq='1D')\n",
"\n",
"columns = ['KW','date','weekday','location','trainer','meetup_time','start_time','warmup','main','cooldown','post_workout','approx_end']\n",
"columns = columns + [f'padding_{i}' for i in range(5)]\n",
"header_names = ['KW','Datum','Tag','Ort','Trainer:in','Treffpunkt','Trainingsbeginn','Warm-Up','Programm','Cool-Down','Post-Workout','Trainingsende']\n",
"header_names = header_names + ['' for i in range(5)]\n",
"\n",
"\n",
"df = pd.DataFrame(index=date_index,columns=columns)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7be00de3",
"metadata": {},
"outputs": [],
"source": [
"weekday_dict_short = {0: 'Mo',\n",
" 1: 'Di',\n",
" 2: 'Mi',\n",
" 3: 'Do',\n",
" 4: 'Fr',\n",
" 5: 'Sa',\n",
" 6: 'So'}\n",
"\n",
"weekday_dict_long = {0: 'Montag',\n",
" 1: 'Dienstag',\n",
" 2: 'Mittwoch',\n",
" 3: 'Donnerstag',\n",
" 4: 'Freitag',\n",
" 5: 'Samstag',\n",
" 6: 'Sonntag'}"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "3f25dd5f",
"metadata": {},
"outputs": [],
"source": [
"df['KW'] = df.index.isocalendar().week\n",
"df['date'] = df.index.strftime('%d.%m.%Y')\n",
"df['weekday'] = df.index.weekday\n",
"df['weekday'] = df['weekday'].replace(weekday_dict_short)\n",
"df['location'] = 'RVV'"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "2b98908c",
"metadata": {},
"outputs": [],
"source": [
"def get_month_slice(df,month_number):\n",
"\n",
" week_numbers_of_month = df.loc[df.index.month==month_number,'KW'].unique()\n",
"\n",
" if month_number == 1:\n",
" week_numbers_of_month = [week_number if (week_number < 6) else None for week_number in week_numbers_of_month]\n",
" elif month_number == 12:\n",
" week_numbers_of_month = [week_number if (week_number > 40) else None for week_number in week_numbers_of_month]\n",
"\n",
" df_slice = df.loc[df['KW'].isin(week_numbers_of_month),:]\n",
" return df_slice"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "69339931",
"metadata": {},
"outputs": [],
"source": [
"def highlight_weekends(row):\n",
" # .weekday() > 4 means Saturday (5) or Sunday (6)\n",
" if row.name.weekday() > 4:\n",
" return ['background-color: #ffcccc'] * len(row) # Light red/pink\n",
" return [''] * len(row)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "379682df",
"metadata": {},
"outputs": [],
"source": [
"def format_rows(row):\n",
" # .weekday() > 4 means Saturday (5) or Sunday (6)\n",
" if row.name.weekday() == 0:\n",
" bg_style = 'background-color: #D1D1D1'\n",
" border_style = 'border-bottom: 1pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 1:\n",
" bg_style = ''\n",
" border_style = 'border-bottom: 1pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 2:\n",
" bg_style = 'background-color: #D1D1D1'\n",
" border_style = 'border-bottom: 1pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 3:\n",
" bg_style = ''\n",
" border_style = 'border-bottom: 1pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 4:\n",
" bg_style = 'background-color: #D1D1D1'\n",
" border_style = 'border-bottom: 2pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 5:\n",
" bg_style = 'background-color: ##C5D9F1'\n",
" border_style = 'border-bottom: 1pt solid black; border-left: 1pt solid black'\n",
" elif row.name.weekday() == 6:\n",
" bg_style = 'background-color: ##C5D9F1'\n",
" border_style = 'border-bottom: 3pt solid black; border-left: 1pt solid black'\n",
"\n",
" # Combine them (separated by semicolon)\n",
" combined = f\"{bg_style}; {border_style}\"\n",
" return [combined] * len(row)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "ae3bf250",
"metadata": {},
"outputs": [],
"source": [
"months = range(1,12+1,1)\n",
"file_name = f\"Trainingsplan_{year}.xlsx\"\n",
"\n",
"with pd.ExcelWriter(file_name, engine='openpyxl') as writer:\n",
" for month in months:\n",
" df_month = get_month_slice(df, month)\n",
" \n",
" # 1 format the cells\n",
" \n",
" # 1.1 format the rows (background color and borders)\n",
" styled_df = df_month.style.apply(format_rows, axis=1)\n",
" \n",
" # 1.2 center all cells\n",
" styled_df = styled_df.set_properties(**{'text-align': 'center'})\n",
" \n",
" # 2 Write to xlsx\n",
" styled_df.to_excel(writer, sheet_name=f\"{month}_{year}\",index=False,header=header_names)\n",
"\n",
" # 3 after writing, change other formats\n",
" # --- Access the openpyxl worksheet object ---\n",
" worksheet = writer.sheets[f\"{month}_{year}\"]\n",
"\n",
" # 3.1 set the widths\n",
" worksheet.column_dimensions['A'].width = 18*0.35\n",
" worksheet.column_dimensions['B'].width = 18*0.89\n",
" worksheet.column_dimensions['C'].width = 18*0.35\n",
" worksheet.column_dimensions['D'].width = 18*0.40\n",
" worksheet.column_dimensions['E'].width = 18*0.73\n",
" worksheet.column_dimensions['F'].width = 18*0.81\n",
" worksheet.column_dimensions['G'].width = 18*1.05\n",
" worksheet.column_dimensions['H'].width = 18*0.76\n",
" worksheet.column_dimensions['I'].width = 18*2.50\n",
" worksheet.column_dimensions['J'].width = 18*0.76\n",
" worksheet.column_dimensions['K'].width = 18*1.05\n",
" worksheet.column_dimensions['L'].width = 18*1.05\n",
"\n",
" # 3.2 format the header\n",
" # Define a bold, larger font\n",
" header_font = openpyxl.styles.Font(name='Arial', size=12, bold=True, color=\"000000\")\n",
" \n",
" # Iterate through the first row (Header)\n",
" # worksheet[1] returns all cells in the first row\n",
" for cell in worksheet[1]:\n",
" cell.font = header_font\n",
" cell.alignment = openpyxl.styles.Alignment(horizontal='center', vertical='center')\n",
" cell.border = openpyxl.styles.Border(bottom=openpyxl.styles.Side(border_style='medium', color='000000'))\n",
"\n",
" # 3.3 freeze the first row\n",
" worksheet.freeze_panes = 'A2' "
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -15,10 +15,13 @@ def get_list_of_packages_to_load():
packages.append('numpy')
packages.append('pandas')
packages.append('pyarrow')
packages.append('odfpy')
packages.append('fsspec')
packages.append('vobject')
packages.append('requests')
# packages.append('openpyxl')
packages.append('openpyxl')
packages.append('jinja2') # for styling
# packages.append('matplotlib')
# packages.append('pyqt5')
# packages.append('tirex-ts')