Tässä on koodi kirjastoaikani python3-koodille, joka hakee varauslistasta generoidusta excel-tiedostosta, haettavat varaukset ja käsittelee näiden dataa alla olevien koodien perusteella. Lopulta matplotlib sitten tekee frekvenssi-kuvaajat, joka näytetään Flask palvelimella.

import numpy as np
from io import BytesIO
from matplotlib.figure import Figure
import base64
from collections import Counter
# Luodaan erilaisia kuvaajia ja dataa ladatuista varaustiedoista.
# Datat:
# Nideluokka (kirja, cd, paikka (aikuiset nuoret), varauspaikka

def create_bar_chart(data, title, xlabel, ylabel):
    fig = Figure(figsize=(6,3))
    ax = fig.subplots()
    items = list(data.items())
    labels, values = zip(*items)
    ax.bar(labels, values, width=0.4)
    ax.set_title(title)
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.tick_params(axis='x', rotation=45)
    fig.tight_layout()
    buffer = BytesIO()
    with BytesIO() as buffer:
        fig.savefig(buffer, format="png", dpi=600)
        buffer.seek(0)
        img_base64 = base64.b64encode(buffer.read()).decode("utf-8")
    return img_base64
def calc_unique_count(excel_data):
    reservations_total = len(excel_data)
    # Counter on kätevä - laskee jokaisen uniikin arvon määrän mitä siihen tungetaan!
    reservations_by_lib = Counter(row["res"] for row in excel_data)
    reservations_by_type = Counter(row["type"] for row in excel_data)
    reservations_by_loc = Counter(row["loc"] for row in excel_data)
    reservations_by_signum = Counter(str(row["signum"]) for row in excel_data)
    graphs = {
        "reservations_by_lib": create_bar_chart(dict(reservations_by_lib),"Varaukset kirjastoittain", "Kirjasto", "Määrä"),
        "reservations_by_type": create_bar_chart(dict(reservations_by_type), "Varaukset nideluokittain", "Nideluokka", "Määrä"),
        "reservations_by_loc": create_bar_chart(dict(reservations_by_loc), "Varaukset sijainnittain", "Sijainti", "Määrä"),
        "reservations_by_signum": create_bar_chart(dict(reservations_by_signum), "Varaukset signumeittain", "Signum", "Määrä")
    }
    return {
        "total": reservations_total,
        "reservations_by_lib": dict(reservations_by_lib),
        "reservations_by_type": dict(reservations_by_type),
        "reservations_by_loc": dict(reservations_by_loc),
        "reservations_by_signum": dict(reservations_by_signum),
        "graphs": graphs
    }
Lataa calc.py

Yllä oleva calc.py koodi laskeskelee tarvittavat arvot. Seuraavaksi koodi joka käsittelee Excel-tiedoston sisältämän datan Pandas-kirjaston avulla:

import conf # config-tiedosto
import pandas as pd
filters = conf.filters
home = conf.settings["HOME"]
signum_id = conf.settings["signum_id"]
available_index = conf.settings["available_index"]
reservation_index = conf.settings["reservation_index"]
signum_index = conf.settings["signum_index"]
name_index = conf.settings["name_index"]
type_index = conf.settings["type_index"]
loc_index = conf.settings["loc_index"]
class ConfigurationError(Exception):
    def __init__(self, message):
        super().__init__(message)
def parse_signum(parsable_data: str):
    #if conf.settings["parse_signum"].lower() == "true":
    #    return parsable_data
    print(parsable_data)
    indexes = []
    temp = []
    pairs = []
    track = False
    if parsable_data[-1] != " ":
        parsable_data = parsable_data + " "
        
    if parsable_data[0] != " ":
        parsable_data = " " + parsable_data
    for i, char in enumerate(parsable_data):
        if char == " ":
            indexes.append(i)
    for i in range(0,len(indexes)-1):
        element = parsable_data[indexes[i]:indexes[i+1]]
        temp.append(element.replace(" ", ""))
    for k in range(0, len(temp)-1):
        if temp[k] == signum_id or temp[k+1] == signum_id:
            if temp[k].isnumeric():
                return temp[k]
            else: return temp[k+1]
    return parsable_data # Jos paria ei löydy, tulostetaan kaikki.

def process_excel(file_path: str):
    pickup_rows = []
    df = pd.read_excel(file_path, keep_default_na=False, na_values=['jokuarvo123'])
    # pandas-kirjasto luulee että luokka NA (nuoret aikuiset) on nan-datatyyppi.
    for index, row in df.iterrows():
        delete = None 
        available = row.iloc[available_index]
        reservation = row.iloc[reservation_index]
        if reservation == home:
            delete = False
        elif reservation in available:
            delete = False
        else:
            if reservation in filters and len(filters[reservation]) > 0:
                for k in filters[reservation]:
                    if k in available:
                        delete = True
                        break
        if not delete:
            pickup_rows.append({
                "res": reservation,
                "signum": parse_signum(row.iloc[signum_index]),
                "type": row.iloc[type_index],
                "name": row.iloc[name_index],
                "loc": row.iloc[loc_index]
            })
    return pickup_rows
Lataa excel.py

Ja vielä conf.py tiedoston lähdekoodi:

import json, os

filters_path = os.path.join(os.path.dirname(__file__), 'settings', 'filters.json')
settings_path = os.path.join(os.path.dirname(__file__), 'settings', 'settings.json')
filters = None
settings = None
# Haetaan tiedot tiedostoista yms.

with open(filters_path, "r", encoding="utf-8") as file:
    filters = json.load(file)
with open(settings_path, "r", encoding="utf-8") as file:
    settings = json.load(file)
# Poistaa oman filtterin
filters.pop(settings["HOME"])
Lataa conf.py

conf.py hakee settings kansiosta tarvittavat filtterit, joita käyttämällä Excel-tiedosto pystytään käsittelemään ja haettua noudettavat varaukset yms.

Tällä sivulla annettuja koodipätkiä saa hyödyntää :)