Python i Excel. Odsłona pierwsza.

Dzisiejszy wpis w pierwszym rzędzie ma za zadanie zatrzeć wrażenie, że oto jakiś czas temu zaszła niespotykana rewolucja i obecnie można próbować poskramiać Excela za pomocą “bardziej poważanych” języków niż Visual Basic for Application, który nota bene od lat należy do najbardziej znienawidzonych dialektów programistycznych. Owszem Microsoft udostępnił odpowiednie API do swojego pakietu biurowego, a nawet przygotował własną – przydatną do tego celu bibliotekę – dla kodujących w Javascript, tym niemniej już wcześniej społeczności skupione wokół różnych języków zdążyły przygotować stosowne narzędzia. Nie inaczej rzecz jasna było w przypadki Pythona.

Przy okazji pisania poprzedniego wpisu przypomniałem sobie, że z okazji inauguracji moich studiów podyplomowych dostałem w prezencie książkę autorstwa Naomi Ceder, poświęconą Pythonowi właśnie. Nieduża część jednego z rozdziałów była poświęcona korzystaniu z arkuszy kalkulacyjnych przy pomocy tego języka. Sama książka dla osób początkujących jest całkiem znośna ze wskazaniem na dobra, choć trochę za mało tam ćwiczeń praktycznych. Patrząc z perspektywy tematyki poruszanej w dzisiejszym wpisie z przykrością muszę napisać, że niestety o współpracy Pythona z Excelem było tam naprawdę niewiele. Inna sprawa, że nie tego ta pozycja dotyczyła, więc trudno robić autorce z tego powodu jakiekolwiek wyrzuty. Tym niemniej dzięki lekturze fragmentów temu zagadnieniu poświęconym miałem jakiś punkt zaczepienia. Otóż Naomi Ceder „omawia” w tej części swojej książki bibliotekę openpyxl, choć przedstawia tam absolutne minimum w tym zakresie. Dlatego – rzecz jasna – dalszej „mądrości” w tym temacie zacząłem szukać w Internetach, przy okazji licząc na znalezienie jakiegoś ciekawego pomysłu na tekst (czy raczej pretekstu do jego napisania) w postaci jakiegoś ciekawego projektu praktycznego.

Niestety poszukiwania te okazały się mało pomocne, o czym więcej będzie za chwilę, natomiast w tym momencie chciałbym zwrócić uwagę na jedną kwestię, która rzuciła mi się w oczy w trakcie przeglądania Internetów. Otóż w przypadku zapytań użytkowników różnych portali dotyczących tego, jak rozwiązać problem X związany z arkuszem kalkulacyjnym, wcześniej czy później pojawiała propozycja, by wykorzystać bibliotekę pandas. Nie chcę w tym miejscu powiedzieć, że te sugestie były błędne, bo zazwyczaj dość dobrze adresowały rozwiązanie danego problemu. Tym niemniej jeśli ktoś myśli w pierwszym rzędzie o automatyzacji zadań w Excelu na wzór tego, co robi sam lub jego znajomi przy pomocy VBA, to powinien omijać takie propozycje szerokim łukiem, a przynajmniej stosować się do tej rady, jeśli jest na samym początku przygody z Pythonem. Uważam tak co najmniej z dwóch powodów. Po pierwsze, biblioteka pandas wymaga zrozumienia struktury danych, z którą mamy do czynienia w jej przypadku. Choć ramki danych (DataFrame) oraz serie (Series) oferowane przez pandas są dość intuicyjne, jeśli chodzi o ich czytanie czy analizę, to jednak praca z nimi odbiega dość znacznie od tego, co znamy w przypadku wbudowanych (standardowych) obiektów Pythona jak tablice czy słowniki. Więc na samym początku trzeba będzie się z tym oswoić i nauczyć jak efektywnie korzystać z tych „specjalnych” tablic, co wymaga trochę wysiłku, a poza tym odciąga początkującego od opanowania standardowych rozwiązań Pythona w rodzaju listy czy słownika.

Wspomniane wyżej zastrzeżenie nie jest jakoś szalenie istotne i ma bardziej charakter – powiedzmy – dydaktyczny. Moje dalece poważniejsze zastrzeżenie dotyczy tego, że tak naprawdę w tym wypadku nie pracujemy ze skoroszytem Excela, tylko wykorzystujemy dane tam zawarte. Tym samym choć pandas oferują możliwość bardzo prostego załadowania pliku xls czy xlxs, to tak naprawdę cała interakcja z Excelem do tego się sprowadza w tym scenariuszu. Biblioteka ta nie ma tak naprawdę do zaoferowania niczego w zakresie pracy z innymi “obiektami” arkusza kalkulacyjnego niż dane właśnie, choć to nie może dziwić, bo w sumie nie do tego ma ona służyć. Tymczasem taki openpyxl oferuje całe mnóstwo metod, które pozwalają chociażby manipulować przy tabelach przestawnych, majstrować z formatowaniem czy też tworzyć wykresy.  Innymi słowy: pozwala pracować z arkuszem kalkulacyjnych na zasadach znanych każdemu użytkownikowi tego narzędzia od Microsoftu

To napisawszy wracam do wątku niezbyt owocnych poszukiwań pomysłów na praktyczne ćwiczenie, które mógłbym na łamach mojego bloga zaprezentować. Niestety w ostatnich latach korzystam z Excela w bardzo ograniczonym zakresie, głównie jako nośnika danych już przetworzonych, chociażby w ramach skryptu SQL (plik wynikowy). W związku z tym potrzebowałem silnej inspiracji, by zaprezentować jakiś praktyczny przykład pokazujący faktyczne zalety takie rozwiązania. Niestety w tym przypadku Internety okazały się mało przydatne albo po prostu nieumiejętnie szukałem. Większość napotkanych przeze mnie wprowadzeń czy tutoriali przedstawia rozwiązania tak banalne lub wydumane, że w praktyce nie ma z nich żadnego pożytku, bo to samo nierzadko szybciej i łatwiej wykonać bezpośrednio w arkuszu kalkulacyjnym przy użyciu niezbyt wyszukanej formuły. Przy tym bardzo często jest to zwyczajnie powielanie dokumentacji w jakimś wąskim zakresie, co samo w sobie nie jest żadnym grzechem, a przynajmniej niezbyt ciężkim. Niestety autorzy takich wpisów rzadko w sposób twórczy operują na tym materiale, czyli na próżno szukać rozwinięcia wątków dostępnych w dokumentacji w postaci bardzo uproszczonej.

W efekcie  dzisiejszy wpis lepszy pod tym względem nie będzie, czyli jedynie zaprezentuję krótką zajawkę biblioteki openpyxl, w której spróbuję zaprezentować jak przy jej pomocy wczytać skoroszyt do pamięci, uzyskać dostęp do poszczególnych arkuszy oraz odczytać zawartość poszczególnych komórek oraz ewentualnie nadpisać jakieś wartości tam wpisane.

Moduł openpyxl nie jest częścią biblioteki standardowej, więc przed rozpoczęciem pracy należy go uprzednio zainstalować przy pomocy polecenia: pip install openpyxl. Ja korzystam z wersji 3.0.7, co może być dość istotne dla wykonania ćwiczenia z niniejszego tekstu, ponieważ z tego co się zorientowałem pewne dość popularne metody (get_sheet_by_name na ten przykład) w 3 wersji zostały porzucone.  W drugiej kolejności umieścić plik z interesującym nas arkuszem kalkulacyjnym w katalogu roboczym dla naszego skryptu. Oczywiście to ostatnie nie jest koniecznie, ale przynajmniej na etapie ćwiczeń unikniemy konieczności precyzyjnego wskazywania ścieżki dostępu.

Ja na potrzeby dzisiejszego ćwiczenia przygotowałem skoroszyt zawierający trzy arkusze o nazwch “Pierwszy”, “Drugi” oraz – a jakże – “Trzeci”. W ostatnim z nich umieściłem zaś niewielką tabelką, którą można podziwiać niżej.

ImięMiejsce zamieszkaniaPrzegieg w latachZapoznany
MarysiaSierociniec152021-04-19
KrzyśStumilowy Las122021-04-01
MikołajekGdzieś we Francji102021-04-10

Skoro już wszystko gotowe, to tworzymy skrypt pythona (o dowolnej nazwie), w którym na początku załadujemy moduł Openpyxl. Następnie przy jego pomocy wczytamy nasz skoroszyt i ten nowo utworzony obiekt przypiszemy od razu do zmiennej ws (jak workbook). Całość powinna wyglądać tak („Znajomi.xlsx” to nazwa, którą nadałem plikowi z moim skoroszytem):

import openpyxl 
wb = openpyxl.load_workbook('Znajomi.xlsx')

Przy pomocy obiektu w ten sposób utworzonego będziemy mogli dokonywać różnych zabiegów na interesującym nas pliku. Na samym początku możemy sprawdzić, jakie arkusze są w nim zawarte (metoda sheetnames), dzięki której otrzymamy stosowną listę. Przy okazji zweryfikować możemy arkusz, który w tym wypadku jest aktywny (metoda active).

print(wb.sheetnames)
print(wb.active)

Powiedzmy jednak, że doskonale wiemy, który z arkuszy nas interesuje i co by rozpocząć z nim pracę, chcemy przypisać do zmiennej ws (skrót od słowa worksheet). Jeśli jest to arkusz aktywny to rzecz jasna możemy użyć metody active, ale równie dobrze w tym przypadku możemy wskazać ten konkretnie nas interesujący i do tego należy skorzystać z notacja z nawiasami kwadratowymi. Akurat w moim przypadku oba wyniki będa tożsame, ale podaję oba warianty.

ws = wb['Trzeci']
ws2 = wb.active 
print(ws)
print(ws2)

Gdy już mamy dostęp do obiektu odpowiadającemu naszemu arkuszowi, w tym momencie możemy wreszcie realizować planowane zadania, czyli chociażby wyszukiwać i pobierać interesujące wartości, wstawiać odpowiednie formuły, majstrować przy stylach, czyli z grubsza robić to, co udostępnia aplikacja użytkownikowi. Tym jednak bardziej szczegółowo zajmiemy się w kolejnym wpisie i mam nadzieję, że do tego czasu uda mi się wymyślić lub chociaż skopiować czyjś pomysł na jakieś fajne ćwiczenie, które pokaże chociaż część możliwości tego pakietu.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *