IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

User

[Actualité] Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel

Noter ce billet
par , 10/04/2023 à 10h23 (8170 Affichages)
I. Introduction

Dans un précédent billet nous avons pu planifier les disponibilités de véhicules de location. On s'intéresse maintenant à la gestion de matériel informatique et on souhaite connaître les quantités d'articles disponibles en fonction des mouvements (entrées/sorties) de stock.

Nom : materiel-informatique.jpg
Affichages : 4224
Taille : 34,3 Ko

L'objectif est en fait de générer la liste des quantités d'articles ou de matériel disponibles en stock à partir de données enregistrées dans un fichier Excel ou dans des tables SQLite.

Cette opération sera réalisée en 3 étapes principales :

  1. importation des données externes dans des listes de dictionnaires ;
  2. génération de la liste des disponibilités du matériel en stock ;
  3. exportation de cette liste dans une feuille Excel.



II. Données externes

Dans notre cas, les données sont enregistrées dans des feuilles Excel ou dans des tables SQLite.


II-A. Fichier contenant les données sur les articles

Structure du fichier :

Nom : tableau_materiel.png
Affichages : 2452
Taille : 9,1 Ko


Aperçu du contenu de la feuille Excel :

Nom : materiel.png
Affichages : 2479
Taille : 30,6 Ko


II-B. Fichier contenant les données sur les mouvements de stock

Structure du fichier source :

Nom : tableau_mouvements.png
Affichages : 2457
Taille : 9,7 Ko


Aperçu du contenu de la feuille Excel :

Nom : mouvements_materiel.png
Affichages : 2464
Taille : 29,9 Ko


Note importante : pour simplifier, on garde uniquement les colonnes essentielles et on affiche la référence du matériel au lieu de son identifiant pour savoir directement quel article est entré ou sorti du stock.

Les quantités initiales des articles sont naturellement enregistrées comme des quantités entrées dans le stock et on ne gère pas d'inventaire.

Comme on le verra plus loin, on peut également extraire ces informations d'une base de données SQLite.


III. Module openpyxl

Il permet de lire et d'écrire dans des feuilles de fichiers Excel au format xlsx ou xlsm.


III-A. Installation

Pour installer la librairie exécutez simplement la commande :

pip install openpyxl

C'est plus simple qu'avec pandas.


III-B. Code exemple

On donne ici quelques lignes de code prises dans la documentation pour mieux comprendre comment utiliser openpyxl :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from openpyxl import Workbook
 
wb = Workbook()
 
# pointe sur la feuille active
ws = wb.active
 
# copie la valeur 42 dans la cellule A1
ws['A1'] = 42
 
# ajout d'une ligne à la feuille
ws.append([1, 2, 3])
 
# copie la date et l'heure actuelle dans la cellule A2
import datetime
ws['A2'] = datetime.datetime.now()
 
# sauvegarde du fichier
wb.save("sample.xlsx")

Autre exemple, pour lire le contenu d'une cellule Excel :


Permet de copier le contenu de la cellule A1 de la feuille ws dans la variable var.

Equivalent à :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
var = ws.cell(row = 1, column = 1).value

On peut donc lire et écrire dans des cellules précises et sur des lignes ou des colonnes pas forcément adjacentes, ce qui n'est pas vraiment possible avec pandas.


III-C. Création d'un graphique

On peut également créer un graphique dans une feuille Excel à partir de valeurs contenues dans des plages de cellules :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from openpyxl.chart import BarChart, Reference, Series
...
 
# pointe sur la feuille active
ws = wb.active
 
# plage de cellules contenant les labels : colonne A
labels = Reference(ws, min_col = 1, min_row = 2, max_row = len(liste_dispos))
 
# plage de cellules contenant les valeurs : colonne D
values = Reference(ws, min_col=4, min_row=2, max_row=len(liste_dispos))
 
chart = BarChart() # on choisit un graphique à barres verticales
 
# ajout des valeurs pour les y
chart.add_data(values)
 
# mise à jour des labels sur le graphique
chart.set_categories(labels)
 
# choix du titre du graphique
chart.title = "Quantités de matériel en stock"
 
chart.legend = None # pas de légende
 
# ajout du graphique dans la feuille, avec le coin supérieur gauche du graphique positionné sur la cellule F2.
ws.add_chart(chart, "F2")
 
# sauvegarde du classeur
wb.save("sample.xlsx")

Si vous souhaitez avoir plus d'information sur ce module je vous invite à consulter ce tutoriel.


Note importante : on donnera en complément pour chacune des fonctions utilisant openpyxl le code équivalent avec pandas.



IV. Importation des données dans des listes de dictionnaires


IV-A. Fichier Excel

On récupère les données des deux feuilles Excel dans des listes Python à l'aide du module openpyxl :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from openpyxl import load_workbook # module utilisé pour lire le contenu du fichier xlsx
 
def importer_feuille(ws):
    # lecture et importation des données de la feuille ws dans une liste de dicos
 
    # initialisation de la liste des dictionnaires
    liste_dicos=[]
 
    # mémorisation des indices maxi. de ligne et de colonne 
    ligne_max = ws.max_row
    col_max = ws.max_column
 
    # parcours les lignes de la feuille Excel en commençant par la 2e ligne
    for i in range(2, ligne_max + 1):
        dico = {} # initialisation du dico
        # parcours des colonnes de la feuille
        for j in range(1, col_max + 1):
            # copie de la valeur associée à la clé dans le dictionnaire : dico['id_materiel'] = ws.cell(row = i, column = 1)
            cle = ws.cell(row = 1, column = j).value
            dico[cle] = ws.cell(row = i, column = j).value
 
        # ajout du dico à la liste
        liste_dicos.append(dico)
 
    return liste_dicos # retourne la liste des dicos
 
def importer_donnees(chemin_fichier):
    # importe les données sur les articles et les locations qui sont contenues dans le fichier Excel
 
    # ouverture du classeur dont l'emplacement est passé en argument
    wb = load_workbook(chemin_fichier)
 
    # on pointe sur la feuille materiel
    ws = wb["materiel"]
 
    # récupération dans une liste des données de la feuille materiel
    liste_materiel = importer_feuille(ws)
 
    # on pointe maintenant sur la feuille mouvements_materiel
    ws = wb["mouvements_materiel"]
 
    # récupération dans une liste des données de la feuille mouvements_materiel
    liste_mouvements = importer_feuille(ws)
 
    return (liste_materiel,liste_mouvements) # renvoi des 2 listes de dicos

Fonction équivalente avec pandas :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pandas
 
def importer_donnees(chemin_fichier):
    # importe les données sur les articles et les mouvements qui sont contenues dans le fichier Excel    
 
    # lecture et importation du contenu de la feuille materiel dans un DataFrame
    df = pandas.read_excel(chemin_fichier, sheet_name="materiel")
    # transformation du DataFrame en liste de dictionnaires
    liste_materiel = df.to_dict('records')
 
    # lecture et importation du contenu de la feuille mouvements_materiel dans un DataFrame
    df = pandas.read_excel(chemin_fichier, sheet_name="mouvements_materiel")
    # transformation du DataFrame en liste de dictionnaires
    liste_mouvements = df.to_dict('records')
 
    return (liste_materiel,liste_mouvements) # renvoi des 2 listes de dicos


IV-B. Base de données SQLite

On peut également extraire les données de tables SQLite à l'aide de la librairie sqlite3 :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import sqlite3
from sqlite3 import Error
 
def create_connection(db_file):
    """ crée une connexion à la base de données SQLite
        specifié par le chemin du fichier passé en argument
    :param db_file: chemin du fichier db
    :return: un objet connexion ou renvoie none
    """
    conn = None
    try:
        conn = sqlite3.connect(db_file) # on crée l'objet connexion
        return conn
    except Error as e: # gestion de l'erreur
        print(e) # affichage du message d'erreur
 
    return conn
 
def importer_table(connexion, nom_table, liste_cles):
    # importation des données de la table dans une liste de dicos 
 
    cur = connexion.cursor()
 
    cur.execute("select * from " + nom_table)
 
    # initialise la liste qui contiendra les données de la table
    liste_dicos=[]
 
    # récupère le contenu de la table dans une liste
    liste_donnees = cur.fetchall()
 
    # parcours de la liste contenant les lignes de la table
    for row in liste_donnees:
        # initialisation du dico et de l'indice de colonne
        dico = {}; j=0
 
        # copie des données de la ligne dans un dictionnaire
        for cle in liste_cles:
            dico[cle]= row[j]
            j+=1 # incrémentation de l'indice de colonne
 
        # ajout du dictionnaire à la liste
        liste_dicos.append(dico)
 
    return liste_dicos # renvoi la liste de dicos
 
 
def importer_donnees():
    # importe les données sur les articles et les mouvements qui sont contenues dans les tables sqlite
 
    database = r"C:\sqlite\db\base_materiel.db" # chemin de la base de données
 
    # création de la connexion à la base de données sqlite
    conn = create_connection(database)
 
    # si la connexion a été réalisée
    if conn is not None:
 
        # liste des clés des dicos pour le matériel
        liste_cles = ['id_materiel','ref_materiel', 'modele_materiel','categorie_materiel','fabricant']
 
        # récupération des données de la table materiel dans une liste
        liste_materiel = importer_table(conn, 'materiel', liste_cles)
 
        # liste des clés des dicos pour les mouvements du stock
        liste_cles = ['id_mouvement','ref_materiel', 'date_mouvement','type_mouvement','qte_mouvement']
 
        # récupération des données de la table mouvements_materiel dans une liste
        liste_mouvements = importer_table(conn, 'mouvements_materiel', liste_cles)
 
        return (liste_materiel, liste_mouvements) # renvoi les 2 listes de dicos
 
    else:
        print("Erreur! impossible de créer la connexion à la base !")

Résultat obtenu pour les mouvements de stock :

Code Javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[
    {
        "id_mouvement": 1,
        "ref_materiel": "ESPR_V5505",
        "date_mouvement": datetime.datetime(2023, 3, 14, 15, 0),
        "type_mouvement": "entrée",
        "qte_mouvement": 10
    },
    {
        "id_mouvement": 2,
        "ref_materiel": "ESPR_V6505",
        "date_mouvement": datetime.datetime(2023, 4, 3, 12, 0),
        "type_mouvement": "entrée",
        "qte_mouvement": 12
    },
    {
        "id_mouvement": 3,
        "ref_materiel": "ESPR_V5535",
        "date_mouvement": datetime.datetime(2023, 4, 24, 12, 0),
        "type_mouvement": "entrée",
        "qte_mouvement": 8
    },
    ...
]


Note importante : l'utilisation de dictionnaires va nous aider par la suite à identifier chaque colonne dans le code Python.



V. Génération des disponibilités du matériel en stock

Si on souhaite par exemple obtenir la quantité disponible pour la référence ESPR_D9510 :

Nom : calcul_qte_dispo.png
Affichages : 2463
Taille : 14,5 Ko Nom : stock_materiel2.png
Affichages : 2466
Taille : 15,0 Ko


On fait donc la somme des quantités entrées dans le stock pour cette référence :

Qté entrées = 15 + 5 = 20

Puis, la somme des quantités sorties :

Qté sorties = 7 + 3 = 10

Enfin, la différence entre ces 2 sommes nous donne la quantité disponible :

Qté stock = Qté entrées - Qté sorties = 20 - 10 = 10


Cette opération sera réalisée à l'aide de la fonction Python présentée maintenant.


V-A. Evaluation de la quantité disponible pour un article

La fonction eval_quantité_disponible va permettre de déterminer la quantité en stock de chaque matériel informatique.

Arguments de la fonction :

  • liste_mouvements : liste des mouvements des articles (liste de dictionnaires) ;
  • ref_materiel : référence du matériel recherché.


Déroulé de la fonction :

  • 1. évaluation de la somme des quantités entrées en stock pour la référence ;
  • 2. évaluation de la somme des quantités sorties du stock pour la référence ;
  • 3. calcul de la quantité en stock égale à la différence entre les sommes précédentes ;
  • 4. renvoi de la quantité disponible pour l'article.


Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
def eval_quantite_dispo(liste_mouvements, ref_materiel):
    # détermine la quantité en stock du matériel
 
    # évaluation de la somme des quantités du matériel entrées en stock 
    qte_entrees = sum([mouv['qte_mouvement'] for mouv in liste_mouvements if (mouv['ref_materiel']==ref_materiel) and (mouv['type_mouvement']=='entrée')])
 
    # évaluation de la somme des quantités du matériel sorties du stock 
    qte_sorties = sum([mouv['qte_mouvement'] for mouv in liste_mouvements if (mouv['ref_materiel']==ref_materiel) and (mouv['type_mouvement']=='sortie')])
 
    # détermination de la quantité en stock de l'article : qté_dispo = qté_entrées - qté_sorties
    qte_dispo = qte_entrees - qte_sorties
 
    return qte_dispo # renvoi la quantité disponible pour l'article


V-B. Génération des disponibilités du matériel

La fonction generer_disponibilites va permettre de générer la liste des disponibilités des articles en stock.

Arguments de la fonction :

  • liste_materiel : liste des articles (liste de dictionnaires) ;
  • liste_mouvements : liste des mouvements du stock (liste de dictionnaires).


Déroulé de la fonction :

  • 1. parcours de la liste des références de matériel ;
  • ---2.1. pour chaque référence, évaluation de la quantité en stock ;
  • ---2.2. pour chaque référence, ajout de la quantité à la liste des disponibilités ;
  • 3. renvoi de la liste des disponibilités.


Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def generer_disponibilites(liste_materiel, liste_mouvements):
    # génère la liste des quantités disponibles pour chaque article
 
    # tri de la liste de articles par catégorie, modèle et référence
    liste_materiel = sorted(liste_materiel, key=lambda k: (k['categorie_materiel'], k['modele_materiel'], k['ref_materiel']))
 
    # initialise la liste des disponibilités
    liste_dispos = []
 
    # parcours de la liste
    for materiel in liste_materiel:
        # évaluation de la quantité disponible pour l'article
        qte_dispo = eval_quantite_dispo(liste_mouvements, materiel['ref_materiel'])
 
        # création du dico contenant les références de l'article avec sa quantité disponible en stock
        dispo_materiel = {'ref_materiel': materiel['ref_materiel'], 'modele_materiel': materiel['modele_materiel'],'categorie_materiel': materiel['categorie_materiel'],
                    'qte_dispo': qte_dispo}
 
        liste_dispos.append(dispo_materiel) # ajout à liste_dispos
 
    return liste_dispos # renvoi la liste des disponibilités


Elle renvoie une liste de dictionnaires de la forme :

Code Javascript : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
    {
        "ref_materiel": "ESPR_D9510",
        "modele_materiel': 'Esprimo mobile D9510",
        "categorie_materiel": "LAPTOP",
        "qte_dispo": 10
    },
    {
        "ref_materiel": "ESPR_M9400",
        "modele_materiel': 'Esprimo mobile M9400",
        "categorie_materiel": "LAPTOP",
        "qte_dispo": 7
    },
    {
        "ref_materiel": "ESPR_M9410",
        "modele_materiel': 'Esprimo mobile M9410",
        "categorie_materiel": "LAPTOP",
        "qte_dispo": 12
    },
    ...
]


VI. Exportation de la liste de dictionnaires dans une feuille Excel

On exporte ensuite la liste obtenue dans une feuille Excel et on crée le graphique correspondant à l'aide de cette fonction :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def exporter_dispos(chemin_fichier, nom_feuille, liste_dispos):
    # exporte les disponibilités dans une feuille du fichier Excel
 
    # création d'un objet Workbook
    wb = Workbook()
 
    # pointe sur la feuille active
    ws = wb.active
 
    # renomme la feuille active
    ws.title = nom_feuille
 
    # récupération des clés du dictionnaire
    liste_cles = list(liste_dispos[0].keys())
 
    # mise à jour des entêtes de colonne de la feuille : 1re ligne
    ws.append(liste_cles)
 
    # parcours de la liste des dispos
    for dispo in liste_dispos:
        liste_valeurs = list(dispo.values()) # liste de valeurs du dictionnaire
        # ajout d'une ligne de valeurs
        ws.append(liste_valeurs)
 
    # plage de cellules contenant les labels : colonne A
    labels = Reference(ws, min_col = 1, min_row = 2, max_row = len(liste_dispos)+1)
 
    # plage de cellules contenant les valeurs : colonne D
    values = Reference(ws, min_col=4, min_row=2, max_row=len(liste_dispos)+1)
 
    chart = BarChart() # on choisit un graphique à barres verticales
 
    # ajout des valeurs pour les y
    chart.add_data(values)
 
    # mise à jour des labels sur le graphique
    chart.set_categories(labels)
 
    # choix du titre du graphique
    chart.title = "Quantités de matériel en stock"
 
    chart.legend = None # pas de légende
 
    # ajout du graphique dans la feuille, avec le coin supérieur gauche du graphique positionné sur la cellule F2
    ws.add_chart(chart, "F2")
 
    # sauvegarde du classeur
    wb.save(chemin_fichier)

On utilise à nouveau le module openpyxl mais cette fois-ci pour copier les données dans une feuille Excel.

Fonction équivalente avec pandas sans la création du graphique :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
import pandas
 
def exporter_dispos(chemin_fichier, nom_feuille, liste_dispos):
    # exporte les disponibilités dans une feuille du fichier Excel
 
    # conversion de la liste de dicos en DataFrame
    df = pandas.DataFrame(liste_dispos)
    # copie du DataFrame dans une feuille du fichier Excel
    df.to_excel(chemin_fichier, sheet_name= nom_feuille)

Résultat obtenu :

Nom : dispo_materiel.png
Affichages : 2452
Taille : 50,3 Ko



VII. Module complet de test

Finalement, nous donnons le module complet contenant les fonctions permettant de générer les quantités de matériel en stock :

Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from openpyxl import load_workbook # module openpyxl utilisé pour lire et écrire dans un fichier xlsx
from openpyxl import Workbook # ---
from openpyxl.chart import BarChart, Reference, Series # permet de créer le graphique
from datetime import datetime
import os
#import pandas
 
 
def importer_feuille(ws):
    # lecture et importation des données de la feuille ws dans une liste de dicos
 
    # initialisation de la liste des dictionnaires
    liste_dicos=[]
 
    # mémorisation des indices maxi. de ligne et de colonne 
    ligne_max = ws.max_row
    col_max = ws.max_column
 
    # parcours les lignes de la feuille Excel en commençant par la 2e ligne
    for i in range(2, ligne_max + 1):
        dico = {} # initialisation du dico
        # parcours des colonnes de la feuille
        for j in range(1, col_max + 1):
            # copie de la valeur associée à la clé dans le dictionnaire : dico['id_materiel'] = ws.cell(row = i, column = 1)
            cle = ws.cell(row = 1, column = j).value
            dico[cle] = ws.cell(row = i, column = j).value
 
        # ajout du dico à la liste
        liste_dicos.append(dico)
 
    return liste_dicos # retourne la liste des dicos
 
 
def importer_donnees(chemin_fichier):
    # importe les données sur les articles et les mouvements qui sont contenues dans le fichier Excel
 
    # ouverture du classeur dont l'emplacement est passé en argument
    wb = load_workbook(chemin_fichier)
 
    # on pointe sur la feuille materiel
    ws = wb["materiel"]
 
    # récupération dans une liste des données de la feuille materiel
    liste_materiel = importer_feuille(ws)
 
    # on pointe maintenant sur la feuille mouvements_materiel
    ws = wb["mouvements_materiel"]
 
    # récupération dans une liste des données de la feuille mouvements_materiels
    liste_mouvements = importer_feuille(ws)
 
    return (liste_materiel,liste_mouvements) # renvoi des 2 listes de dicos
 
 
def importer_donnees_v2(chemin_fichier):
    # importe les données sur le matériel et les mouvements qui sont contenues dans le fichier Excel
 
    # lecture et importation du contenu de la feuille materiel dans un DataFrame
    df = pandas.read_excel(chemin_fichier, sheet_name="materiel")
    # transformation du DataFrame en liste de dictionnaires
    liste_materiel = df.to_dict('records')
 
    # lecture et importation du contenu de la feuille mouvements_materiel dans un DataFrame
    df = pandas.read_excel(chemin_fichier, sheet_name="mouvements_materiel")
    # transformation du DataFrame en liste de dictionnaires
    liste_mouvements = df.to_dict('records')
 
    return (liste_materiel,liste_mouvements) # renvoi des 2 listes de dicos
 
 
def exporter_dispos(chemin_fichier, nom_feuille, liste_dispos):
    # exporte les disponibilités dans une feuille du fichier Excel
 
    # création d'un objet Workbook
    wb = Workbook()
 
    # pointe sur la feuille active
    ws = wb.active
 
    # renomme la feuille active
    ws.title = nom_feuille
 
    # récupération des clés du dictionnaire
    liste_cles = list(liste_dispos[0].keys())
 
    # mise à jour des entêtes de colonne de la feuille : 1re ligne
    ws.append(liste_cles)
 
    # parcours de la liste des dispos
    for dispo in liste_dispos:
        liste_valeurs = list(dispo.values()) # liste de valeurs du dictionnaire
        # ajout d'une ligne de valeurs
        ws.append(liste_valeurs)
 
    # plage de cellules contenant les labels : colonne A
    labels = Reference(ws, min_col = 1, min_row = 2, max_row = len(liste_dispos)+1)
 
    # plage de cellules contenant les valeurs : colonne D
    values = Reference(ws, min_col=4, min_row=2, max_row=len(liste_dispos)+1)
 
    chart = BarChart() # on choisit un graphique à barres verticales
 
    # ajout des valeurs pour les y
    chart.add_data(values)
 
    # mise à jour des labels sur le graphique
    chart.set_categories(labels)
 
    # choix du titre du graphique
    chart.title = "Quantités de matériel en stock"
 
    chart.legend = None # pas de légende
 
    # ajout du graphique dans la feuille, avec le coin supérieur gauche du graphique positionné sur la cellule F2
    ws.add_chart(chart, "F2")
 
    # sauvegarde du classeur
    wb.save(chemin_fichier)
 
def exporter_dispos_v2(chemin_fichier, nom_feuille, liste_dispos):
    # exporte les disponibilités dans une feuille du fichier Excel
 
    # conversion de la liste de dicos en DataFrame
    df = pandas.DataFrame(liste_dispos)
    # copie du DataFrame dans une feuille du fichier Excel
    df.to_excel(chemin_fichier, sheet_name= nom_feuille)
 
 
def eval_quantite_dispo(liste_mouvements, ref_materiel):
    # détermine la quantité en stock du matériel
 
    # évaluation de la somme des quantités du matériel entrées en stock 
    qte_entrees = sum([mouv['qte_mouvement'] for mouv in liste_mouvements if (mouv['ref_materiel']==ref_materiel) and (mouv['type_mouvement']=='entrée')])
 
    # évaluation de la somme des quantités du matériel sorties du stock 
    qte_sorties = sum([mouv['qte_mouvement'] for mouv in liste_mouvements if (mouv['ref_materiel']==ref_materiel) and (mouv['type_mouvement']=='sortie')])
 
    # détermination de la quantité en stock de l'article : qté_dispo = qté_entrées - qté_sorties
    qte_dispo = qte_entrees - qte_sorties
 
    return qte_dispo # renvoi la quantité disponible pour l'article
 
 
def generer_disponibilites(liste_materiel, liste_mouvements):
    # génère la liste des quantités disponibles pour chaque article
 
    # tri de la liste de articles par catégorie, modèle et référence
    liste_materiel = sorted(liste_materiel, key=lambda k: (k['categorie_materiel'], k['modele_materiel'], k['ref_materiel']))
 
    # initialise la liste des disponibilités
    liste_dispos = []
 
    # parcours de la liste
    for materiel in liste_materiel:
        # évaluation de la quantité disponible pour l'article
        qte_dispo = eval_quantite_dispo(liste_mouvements, materiel['ref_materiel'])
 
        # création du dico contenant les références de l'article avec sa quantité disponible en stock
        dispo_materiel = {'ref_materiel': materiel['ref_materiel'], 'modele_materiel': materiel['modele_materiel'],'categorie_materiel': materiel['categorie_materiel'],
                    'qte_dispo': qte_dispo}
 
        liste_dispos.append(dispo_materiel) # ajout à liste_dispos
 
    return liste_dispos # renvoi la liste des disponibilités
 
 
# importation du contenu du fichier mouvements_materiel.xlsx dans 2 listes de dictionnaires
liste_materiel, liste_mouvements = importer_donnees("mouvements_materiel.xlsx")
 
print("Liste du matériel :\n")
 
# affiche le contenu de la liste du matériel
print(liste_materiel)
 
print()
print("Liste des mouvements :\n")
 
# affiche le contenu de la liste des mouvements
print(liste_mouvements)
 
# génération de la liste des disponibilités des articles
liste_dispos = generer_disponibilites(liste_materiel, liste_mouvements)
 
if liste_dispos: # si la liste n'est pas vide
 
    print()
    print("Liste des disponibilités :\n")
 
    # affiche les disponibilités par article
    print(liste_dispos)
 
    # composition du chemin du fichier et du nom de la feuille de destination
    chemin_fichier = 'dispo_materiel.xlsx'
    nom_feuille = 'dispo_materiel'
 
    # export du résultat dans une feuille du fichier Excel
    exporter_dispos(chemin_fichier, nom_feuille, liste_dispos)
    os.startfile(chemin_fichier)
 
    print()
    print("Ouverture du fichier résultat..\n")
 
else:
 
    print("Pas de résultat !")

Si vous le souhaitez, vous pouvez récupérer le dossier complet pour tester le code :

disponibilités matériel.zip



VIII. Conclusion

Ce module Python offre donc une solution relativement simple pour obtenir les quantités de matériel ou d'articles en stock à partir de données enregistrées dans des feuilles Excel ou dans des tables SQLite.

Chacun pourra ensuite librement adapter le code à sa gestion de stock ou à sa base de données.


Sources :

https://docs.python.org/fr/3/tutoria...tructures.html
https://openpyxl.readthedocs.io/en/latest/index.html
https://docs.python.org/fr/3/library/sqlite3.html
https://docs.python.org/fr/3.11/library/datetime.html

Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Viadeo Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Twitter Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Google Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Facebook Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Digg Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Delicious Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog MySpace Envoyer le billet « Python : générer les disponibilités d'articles en stock à partir de données extraites d'un fichier Excel » dans le blog Yahoo

Mis à jour 10/04/2023 à 12h10 par User

Catégories
Programmation , Python , Excel , Algorithmique

Commentaires