{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "152c4ce0", "metadata": {}, "outputs": [], "source": [ "import requests\n", "import pandas as pd\n", "import datetime as dt\n", "import openpyxl.styles" ] }, { "cell_type": "code", "execution_count": null, "id": "041b0ab6", "metadata": {}, "outputs": [], "source": [ "# --- Configuration ---\n", "NEXTCLOUD_URL = \"https://nextcloud.karnelegger.eu\"\n", "USERNAME = \"Georg Brantegger\"\n", "with open('app_pw.txt','r') as f:\n", " APP_PASSWORD = f.readline()\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b4c04efb", "metadata": {}, "outputs": [], "source": [ "import requests\n", "import vobject\n", "\n", "\n", "# This is the \"URL slug\" of your address book. \n", "# Usually, if you name it \"Athletes\", the slug is \"athletes\" (lowercase).\n", "# You can find the exact name by going to Contacts -> Settings (bottom left) -> \n", "# Click the 3 dots next to your address book -> \"Copy link\". \n", "# The link will end with /addressbooks/users/username/THIS_PART/\n", "ADDRESSBOOK_NAME = \"rv-villach-athletinnen\" \n", "\n", "\n", "# The ?export parameter tells Nextcloud to dump the whole address book at once\n", "CARDDAV_URL = f\"{NEXTCLOUD_URL}/remote.php/dav/addressbooks/users/{USERNAME}/{ADDRESSBOOK_NAME}/?export\"\n", "\n", "def get_athlete_data():\n", " print(f\"Fetching contacts from the '{ADDRESSBOOK_NAME}' address book...\")\n", " response = requests.get(CARDDAV_URL, auth=(USERNAME, APP_PASSWORD))\n", " \n", " if response.status_code != 200:\n", " print(f\"❌ Error {response.status_code}: Could not fetch address book.\")\n", " print(\"Check your URL, credentials, and make sure the ADDRESSBOOK_NAME is exactly right.\")\n", " return []\n", "\n", " vcf_data = response.text\n", " first_names = []\n", " last_names = []\n", " genders = []\n", " years_of_birth = []\n", "\n", " # Parse the multi-contact VCF data\n", " for vcard in vobject.readComponents(vcf_data):\n", " # The 'n' property in a vCard holds the structured Name (First, Last, etc.)\n", " if hasattr(vcard, 'n'):\n", " first_name = vcard.n.value.given\n", " last_name = vcard.n.value.family\n", " \n", " first_names.append(first_name)\n", " last_names.append(last_name)\n", " else: print(vcard.fn.value)\n", " \n", " if hasattr(vcard, 'note'):\n", " [_,year_of_birth,gender] = vcard.note.value.split(' ')\n", " \n", " genders.append(gender)\n", " years_of_birth.append(int(year_of_birth))\n", " \n", " return last_names,first_names,genders,years_of_birth" ] }, { "cell_type": "code", "execution_count": null, "id": "3efe3bb1", "metadata": {}, "outputs": [], "source": [ "a,b,c,d = get_athlete_data()\n", "data_dict = {'Nachname':a,'Vorname':b,'Gender':c,'Jahrgang':d}\n", "\n", "df = pd.DataFrame(data_dict)" ] }, { "cell_type": "code", "execution_count": null, "id": "a65d7693", "metadata": {}, "outputs": [], "source": [ "def evaluate_class(row):\n", " gender = row['Gender']\n", " yob = row['Jahrgang']\n", " age = dt.datetime.now().year - yob\n", " \n", " if age <= 12:\n", " c1 = 'Sch'\n", " c2 = 'B'\n", " elif 12 < age <= 14:\n", " c1 = 'Sch'\n", " c2 = 'A'\n", " elif 14 < age <= 16:\n", " c1 = 'Jun'\n", " c2 = 'B'\n", " elif 16 < age <= 18:\n", " c1 = 'Jun'\n", " c2 = 'A'\n", " elif 18 < age <= 23:\n", " c1 = 'Sen'\n", " c2 = 'B'\n", " elif 23 < age <= 30:\n", " c1 = 'Sen'\n", " c2 = 'A'\n", " \n", " return f'{c1}-{gender}-{c2}'\n" ] }, { "cell_type": "code", "execution_count": null, "id": "529f37c2", "metadata": {}, "outputs": [], "source": [ "df['Klasse'] = df.apply(evaluate_class,axis=1)\n", "df[f'Ruderpass {dt.datetime.now().year}'] = 0" ] }, { "cell_type": "code", "execution_count": null, "id": "7ff6f41c", "metadata": {}, "outputs": [], "source": [ "file_name = 'temp.xlsx'\n", "\n", "with pd.ExcelWriter(file_name, engine='openpyxl') as writer:\n", " \n", " df_styled = df.style.set_properties(**{'text-align': 'center'})\n", " # 2 Write to xlsx\n", " df_styled.to_excel(writer, sheet_name=\"Athlet_innen\",index=False)\n", "\n", " # 3 after writing, change other formats\n", " # --- Access the openpyxl worksheet object ---\n", " worksheet = writer.sheets[\"Athlet_innen\"]\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", " worksheet.column_dimensions['A'].width = 18*1.63\n", " worksheet.column_dimensions['B'].width = 18*0.86\n", " worksheet.column_dimensions['C'].width = 18*0.72\n", " worksheet.column_dimensions['D'].width = 18*0.91\n", " worksheet.column_dimensions['E'].width = 18*0.72\n", " worksheet.column_dimensions['F'].width = 18*1.45\n", "\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 }