W bieżącym wpisie opiszę skrypt, który wczytuje dane z listy tankowań w nowszym formacie MS Excel – xlsx.
Skrypt sumuje zakupione paliwo w danym okresie, następnie wyświetla, jaką ilość paliwa zatankowano do poszczególnych pojazdów. W razie rozbieżności z danymi źródłowymi – kartami kierowcy, można wyświetlić szczegółową listę tankowań dla konkretnego pojazdu.
Katalog ze skryptem zawiera również podkatalog „Dane”, w którym umieszczam pliki kolejnych list tankowań.
W pliku Excela komórki pierwszego wiersza definiują nazwy poszczególnych kolumn z danymi m.in. „Ilość” – określa ile paliwa zatankowano podczas jednego tankowania, „Data” – określa datę tankowania, „Numer rejestracyjny” – zawiera numer rejestracyjny pojazdu.
Skrypt zawiera jedną klasę Reports, która zawiera dwie metody: __init__() oraz parser().
W metodzie __init__() określam kolejno katalog, w którym jest umieszczony skrypt main.py i wartość tą przypisuję do zmiennej script_dir. Następnie definiuję zmienną data_dir, która zawiera ścieżkę do podkatalogu „Dane”, który zawiera pliki *.xlsx z danymi. Z plików tych jest sporządzana lista plików, z której jest wybierany najnowszy plik. Dane z najnowszego pliku są wczytywane jako obiekt ramki pandas, który to jest przypisane jako atrybut klasy – zmienna self.df, dzięki czemu obiekt ten będzie dostępny także dla innych metod klasy, gdy metoda __init__() zakończy swoje działanie. Następnie jest wywoływana metoda parser().
W metodzie parser() na początku czyszczę terminal z poprzednich wpisów:
os.system('cls' if os.name == 'nt' else 'clear')
W zależności od systemu, na którym jest uruchamiany skrypt wykonywana jest komenda cls – dla Windows lub clear dla Linux lub MacOS.
Następnie definiuję dwie zmienne: f_date oraz l_date, które przechowują daty odpowiednio pierwszego i ostatniego tankowania na liście tankowań. W kolejnym wierszu wyświetlam nagłówek zestawienia, a następnie zamieniam znak przecinka z danych z kolumny „Ilość” – separatora części dziesiętnej na znak kropki.
Całe pobrane paliwo na wszystkie samochody obliczam za pomocą:
self.df['Ilość'].sum()
W nieskończonej pętli while pobieram tekst zawierający dowolny fragment numeru rejestracyjnego lub „/q” – wyjście za pomocą wywołania wyjątku SystemExit lub „/m” – powrót do głównego zestawienia za pomocą wywołania metody self.parser().
W pętli – for key, value in cars_group[’Ilość’]: w kolejnych iteracjach sprawdzane jest, czy wybrany fragment tekstu wpisanego przez użytkownika (po zmianie na wielkie litery) jest obecny w numerze rejestracyjnym pojazdu. Jeśli powyższy warunek jest spełniony to zostają wyświetlone wszystkie daty i ilości tankowań. Oprócz wszystkich tankowań dla wybranego pojazdu, wyświetlane jest także podsumowanie zatankowanych litrów dla pojazdu.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
@ author: Sławomir Kwiatkowski
@ date: 2019.10.11
'''
import os
import glob
import pandas as pd
class Reports:
def __init__(self):
script_dir = os.path.dirname(os.path.abspath(__file__))
data_dir = os.path.join(script_dir, 'Dane')
list_of_files = glob.glob(os.path.join(data_dir, '*.xlsx'))
latest_file = max(list_of_files, key=os.path.getctime)
path_to_file = os.path.join(data_dir, latest_file)
self.df = pd.read_excel(path_to_file)
self.parser()
def parser(self):
os.system('cls' if os.name == 'nt' else 'clear')
print()
f_date = self.df['Data'].min()
l_date = self.df['Data'].max()
print('>>>Zestawienie paliwa za okres od {} do {}.{}.{}<<<'.format(f_date.day,
l_date.day, l_date.month, l_date.year))
self.df['Ilość'] = self.df['Ilość'].astype(str)
self.df['Ilość'] = self.df['Ilość'].str.replace(',', '.')
self.df['Ilość'] = self.df['Ilość'].astype(float)
print()
print('>>>Zakup paliwa: ', self.df['Ilość'].sum())
cars_group = self.df.groupby('Numer rejestracyjny')
print()
print(cars_group['Ilość'].sum())
print()
while True:
choice = input('Podaj nr rej. pojazdu (lub /q-wyjście, /m-ekran główny): ')
os.system('cls' if os.name == 'nt' else 'clear')
if choice == '/q': raise SystemExit
if choice == '/m': self.parser()
for key, value in cars_group['Ilość']:
if choice.upper() in key:
print('>>>Tankowania dla pojazdu: ', key)
total = 0
for i, v in zip(value.index, value.values):
print(self.df.loc[i, 'Data'], v)
total +=v
print(f'>>>Suma tankowań dla {key}: {total} ltr')
print()
if __name__ == "__main__":
reports = Reports()