Seria: automatyzacja obecności / część 2
Jak ułożyć arkusz obecności, żeby dało się go automatyzować
Zanim pojawił się większy skrypt, trzeba było uporządkować sam arkusz: zawodników, daty treningów, zakładki, podsumowania i zasady wpisywania danych.
Automatyzacja zaczyna się wcześniej niż kod
W pierwszym wpisie tej serii opisałem problem: prowadzenie obecności w klubie pływackim szybko przestało być zwykłym wpisywaniem zer i jedynek. Gdy dochodzą różne grupy, różni trenerzy, papierowy dziennik, Librus, zawodnicy spoza szkoły i potrzeba późniejszego podsumowania danych, prosty arkusz zaczyna robić się coraz mniej prosty.
Drugi krok nie polegał jeszcze na pisaniu dużego skryptu. Najpierw trzeba było ułożyć sam arkusz tak, żeby dało się z nim później sensownie pracować.
To jest coś, co łatwo pominąć. Wydaje się, że automatyzacja zaczyna się od kodu, ale w praktyce bardzo często zaczyna się od struktury danych. Jeśli arkusz jest chaotyczny, każdy tydzień nazywa się inaczej, daty są wpisywane w różnych miejscach, a trenerzy używają różnych wartości, to późniejszy skrypt nie rozwiązuje problemu. On tylko dziedziczy bałagan.
Pierwsza wersja: działało, ale było manualne
Pierwsza wersja była prosta. Każda grupa miała swój arkusz, a w środku była tabela obecności.
W wierszach byli zawodnicy. W kolumnach były treningi. W komórkach wpisywałem obecność — na początku głównie jako 0 albo 1.
To wystarczało, żeby szybko zobaczyć, kto był na treningu, a kogo nie było. Dało się też policzyć frekwencję funkcjami arkuszowymi. Problem w tym, że całość była mocno manualna.
Zakładki były wtedy robione miesięcznie albo tygodniowo, ale bez stałego standardu nazewnictwa. Każdy trener mógł nazwać je trochę inaczej. To nie przeszkadzało, dopóki człowiek sam otwierał arkusz i patrzył na dane. Zaczynało przeszkadzać wtedy, gdy chciałem później te dane zliczać albo automatycznie wyszukiwać konkretne tygodnie i miesiące.
Jeśli raz zakładka nazywa się po prostu „Kwiecień”, innym razem jest zakresem dat, a jeszcze innym razem ktoś dopisze coś po swojemu, to dla człowieka nadal jest to zrozumiałe. Dla skryptu już niekoniecznie.
Wiersz to zawodnik
Najprostsza decyzja była taka: jeden zawodnik to jeden wiersz.
W kolumnie A znajdowały się imiona i nazwiska. Nie było tam dodatkowych informacji, bo na tym etapie arkusz miał jeden cel: prowadzić obecność. Nie był jeszcze pełnym systemem treningowym, bazą zawodników ani analizą obciążeń.
Taki układ był czytelny dla trenerów. Otwierasz arkusz, znajdujesz zawodnika i wpisujesz wartość przy danym treningu. Nie trzeba szukać danych w kilku miejscach.
To też później bardzo ułatwiało liczenie. Skoro jeden wiersz oznaczał jednego zawodnika, to podsumowanie obecności zawodnika można było liczyć wprost z wartości wpisanych w tym wierszu.
Kolumny to treningi
Druga ważna decyzja dotyczyła kolumn.
Kolumny treningowe zawierały daty. To okazało się dużo ważniejsze, niż na początku wyglądało.
Na pierwszy rzut oka można by wpisać po prostu: poniedziałek, wtorek, środa. Dla trenera prowadzącego zajęcia w danym tygodniu to wystarczy. Problem pojawia się przy raportach.
Jeśli w kolumnach są konkretne daty, to później można skryptem sprawdzić, które treningi należą do danego tygodnia albo miesiąca. Można policzyć frekwencję za wybrany okres. Można zrobić raport miesięczny bez ręcznego wybierania zakresów.
Dlatego w nowszej wersji arkusza daty w kolumnach stały się jednym z najważniejszych elementów struktury. Nie były tylko opisem dla człowieka. Były też informacją, z której później korzystał skrypt.
Co było po prawej stronie tabeli
Za ostatnią kolumną z treningiem pojawiało się podsumowanie.
Jednym z najprostszych, ale bardzo przydatnych podsumowań było pokazanie, ile treningów zawodnik faktycznie zaliczył względem liczby treningów wpisanych w arkuszu. W praktyce wyglądało to jak zapis w stylu 7/10.
Taka wartość od razu mówi trenerowi więcej niż sam procent. Widać nie tylko wynik końcowy, ale też skalę: czy mówimy o trzech treningach, czy o dziesięciu.
Do takiego podsumowania używałem funkcji arkuszowej, która liczyła niepuste komórki i odejmowała wpisy oznaczające brak obecności. Jedna z wersji wyglądała mniej więcej tak:
=TEXTJOIN(""; PRAWDA; (ILE.NIEPUSTYCH(B2:K2)-LICZ.JEŻELI(B2:K2;0)); "/"; ILE.NIEPUSTYCH(B2:K2))
Nie chodzi tutaj o samą formułę, tylko o pomysł. Arkusz miał szybko pokazać, ile treningów faktycznie zostało zaliczonych i z ilu możliwych wpisów to wynikało.
Obok można było też liczyć procent frekwencji. To było wygodne przy szybkiej ocenie grupy, ale samo 7/10 często było bardziej czytelne w codziennej pracy.
Brak wpisu też ma znaczenie
Na początku brak wpisu potrafił być problemem. Jeśli grupa miała stałe dni treningowe, a któregoś dnia trening się nie odbył, łatwo było potraktować pustą komórkę jak błąd albo brak danych.
Z czasem podejście się zmieniło.
Brak wpisu zaczął oznaczać: ten trening nie liczy się do obecności. To było ważne, bo nie każdy pusty dzień oznaczał nieobecność zawodnika. Czasem treningu po prostu nie było, czasem dana grupa nie pływała, a czasem arkusz obejmował dni, których nie należało uwzględniać w podsumowaniu.
Dlatego logika obecności zaczęła wyglądać tak:
- brak wpisu — trening nie liczy się do obecności,
0— zawodnik był nieobecny,- wartość między
0a1— obecność częściowa, 1— pełna obecność.
Ten ostatni element, czyli wartości częściowe, był szczególnie przydatny. Zwykłe spóźnienie w dzienniku nie pokazuje, ile treningu zawodnik realnie opuścił. Podobnie wcześniejsze wyjście. Wpisanie wartości pośredniej pozwalało przynajmniej w prosty sposób zaznaczyć, że obecność nie była pełna.
Pełniej opiszę to przy walidacji danych, bo tam zaczyna się robić naprawdę ciekawie.
Dlaczego standard nazw zakładek był ważny
Kolejna rzecz to zakładki.
W pierwszej wersji nazwy zakładek były mało uporządkowane. Dla ludzi było to jeszcze do przeżycia, ale dla automatyzacji robiło się niewygodne.
Później pojawił się stały format nazw tygodniowych, na przykład 15.09-21.09.2025r.. A jeśli tydzień przechodził przez granicę roku, format mógł zawierać pełniejsze daty po obu stronach.
To nie było tylko estetyczne uporządkowanie. Stały format nazw sprawiał, że trenerzy wiedzieli, gdzie wpisywać dane, a skrypt mógł łatwiej tworzyć nowe tygodnie, ukrywać poprzednie zakładki i przygotowywać podsumowania.
Z czasem arkusze zaczęły być tworzone automatycznie raz w tygodniu. To był duży krok, bo zniknęło ręczne kopiowanie układu, poprawianie dat i pilnowanie, czy formuły są na miejscu.
Każdy trener miał swój arkusz
Ważne było też to, że każda grupa miała osobny arkusz, a każdy trener pracował na swoim obszarze.
To porządkowało codzienną pracę. Trener nie musiał szukać swojej grupy w jednym wielkim pliku. Otwierał swój arkusz i wpisywał dane tam, gdzie trzeba.
Jednocześnie struktura musiała być powtarzalna. Jeśli każdy trener miałby inny układ, inne nazwy zakładek i inne zasady wpisywania wartości, raportowanie szybko przestałoby mieć sens. Automatyzacja potrzebuje przewidywalności.
Dlatego z czasem pojawiły się dwa ważne mechanizmy: walidacja danych i ochrona zakresów.
Walidacja i ochrona zakresów
Gdy kilka osób pracuje na podobnych arkuszach, błędy są nieuniknione.
Ktoś wpisze 1, ktoś inny 1.0, ktoś przez pomyłkę wpisze 10 zamiast 1. W efekcie potrafią pojawić się dziwne wyniki, nawet takie jak ponad 100% obecności.
Dlatego w nowszej wersji arkusza trener nie mógł już wpisać dowolnej wartości. Arkusz pilnował, co jest dozwolone. Jeśli ktoś próbował wpisać coś spoza ustalonego zakresu, dostawał informację, że taka wartość nie jest poprawna, a zmiana nie była przyjmowana.
Podobnie z ochroną zakresów. Trener powinien wpisywać obecności albo kilometraż, ale nie powinien przypadkiem usuwać formuł, zmieniać dat, przesuwać podsumowań albo edytować części arkusza, które są potrzebne do raportów.
To jest jedna z tych rzeczy, które nie wyglądają efektownie, ale realnie oszczędzają dużo czasu. Mniej błędów w danych oznacza mniej ręcznego poprawiania i mniej sytuacji, w których raport nagle pokazuje coś bez sensu.
Od obecności do kilometrażu
Z czasem podobny układ zaczął służyć nie tylko do obecności.
W komórkach można było wpisywać również kilometraż. Wtedy tabela nadal działała podobnie: zawodnicy w wierszach, treningi w kolumnach, daty w nagłówkach i podsumowanie po prawej stronie.
Zmieniła się wartość wpisywana w komórkach, ale sama struktura dalej miała sens.
To dobrze pokazuje, dlaczego warto najpierw uporządkować arkusz. Jeśli struktura jest przemyślana, można później zmieniać sposób liczenia, dodawać raporty albo przechodzić z obecności na kilometraż bez zaczynania wszystkiego od zera.
Struktura przed kodem
Najważniejszy wniosek z tego etapu jest prosty: zanim zacząłem automatyzować arkusze, musiałem sprawić, żeby były przewidywalne.
Powtarzalne nazwy zakładek, daty w kolumnach, zawodnicy w wierszach, podsumowania po prawej stronie, puste komórki traktowane świadomie, walidacja danych i ochrona zakresów — to wszystko było podstawą.
Dopiero na tym można było budować kolejne elementy:
- automatyczne tworzenie tygodniowych arkuszy,
- ukrywanie poprzednich zakładek,
- raporty tygodniowe,
- raporty miesięczne,
- wysyłkę raportów mailem,
- późniejsze przejście w stronę kilometrażu.
W kolejnym wpisie opiszę dokładniej walidację danych, czyli to, jak zatrzymać błędy typu 10 zamiast 1 i dlaczego przy pracy kilku trenerów jedno źródło prawdy jest ważniejsze niż najbardziej rozbudowana formuła.