96 lines
3.6 KiB
Python
96 lines
3.6 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
|
||
|
|
# Excel_Bruecke.py
|
||
|
|
"""
|
||
|
|
Kapitel Einfuehrung: Vom Excel-Solver zu Python - dieselbe Rechnung, dieselbe Datei.
|
||
|
|
|
||
|
|
Das Programm bildet den vollstaendigen Arbeitsweg ab, den ein Excel-Modell im
|
||
|
|
Betrieb sonst von Hand geht:
|
||
|
|
|
||
|
|
Tabellenblatt lesen -> Modell bauen -> loesen -> Ergebnis zurueckschreiben
|
||
|
|
|
||
|
|
Damit es ohne Vorbereitung laeuft, legt es die Eingabedatei beim ersten Start
|
||
|
|
selbst an. Ersetzen Sie sie durch Ihre eigene Datei - solange die Spalten
|
||
|
|
gleich heissen, aendert sich am Code nichts.
|
||
|
|
|
||
|
|
Die vier Arbeitsschritte kommen aus or_kern.py (Kapitel Praxisfallen). Was
|
||
|
|
hier steht, ist nur noch das, was diesen Fall ausmacht - der Rest ist
|
||
|
|
gemeinsamer Unterbau. Wer das Modul nicht kennt: Es ist im Buch vollstaendig
|
||
|
|
abgedruckt und liegt im selben Verzeichnis.
|
||
|
|
|
||
|
|
Erzeugte Dateien (im Arbeitsverzeichnis):
|
||
|
|
produktionsmix.xlsx Eingabe: Blaetter 'Produkte' und 'Kapazitaeten'
|
||
|
|
produktionsmix_ergebnis.xlsx Ausgabe: Blaetter 'Plan' und 'Kennzahlen'
|
||
|
|
|
||
|
|
Benoetigt: pandas, openpyxl, ortools, pydantic (ueber or_kern)
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
|
||
|
|
import pandas as pd
|
||
|
|
|
||
|
|
from or_kern import (lade_produktionsproblem, loese_mit_glop, pruefe_loesung,
|
||
|
|
schreibe_ergebnis)
|
||
|
|
|
||
|
|
EINGABE = "produktionsmix.xlsx"
|
||
|
|
AUSGABE = "produktionsmix_ergebnis.xlsx"
|
||
|
|
|
||
|
|
|
||
|
|
def lege_beispieldatei_an(pfad: str) -> None:
|
||
|
|
"""Schreibt die Eingabemappe, wie sie auch aus dem Controlling kaeme."""
|
||
|
|
produkte = pd.DataFrame({
|
||
|
|
"Produkt": ["Tisch", "Stuhl", "Regal"],
|
||
|
|
"Deckungsbeitrag": [240.0, 60.0, 130.0],
|
||
|
|
"Montagestunden": [3.0, 1.0, 2.0],
|
||
|
|
"Plattenmaterial": [6.0, 1.0, 4.0],
|
||
|
|
})
|
||
|
|
kapazitaeten = pd.DataFrame({
|
||
|
|
"Ressource": ["Montagestunden", "Plattenmaterial"],
|
||
|
|
"Verfuegbar": [150.0, 240.0],
|
||
|
|
})
|
||
|
|
with pd.ExcelWriter(pfad, engine="openpyxl") as mappe:
|
||
|
|
produkte.to_excel(mappe, sheet_name="Produkte", index=False)
|
||
|
|
kapazitaeten.to_excel(mappe, sheet_name="Kapazitaeten", index=False)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
if not os.path.exists(EINGABE):
|
||
|
|
lege_beispieldatei_an(EINGABE)
|
||
|
|
print(f"Beispiel-Eingabedatei angelegt: {EINGABE}")
|
||
|
|
|
||
|
|
# 1. Lesen und pruefen. Faellt hier etwas auf, ist der Fehler noch
|
||
|
|
# zuzuordnen - spaeter waere er nur noch eine merkwuerdige Zahl.
|
||
|
|
problem = lade_produktionsproblem(EINGABE)
|
||
|
|
|
||
|
|
# 2. Loesen. Einzige solverabhaengige Zeile des ganzen Programms -
|
||
|
|
# 'loese_mit_scipy' waere ein Einzeiler-Wechsel.
|
||
|
|
loesung = loese_mit_glop(problem)
|
||
|
|
|
||
|
|
# 3. Abnahmepruefung gegen die Anforderungen, ohne den Solver zu fragen.
|
||
|
|
beanstandungen = pruefe_loesung(problem, loesung)
|
||
|
|
if beanstandungen:
|
||
|
|
raise SystemExit("Abnahmepruefung fehlgeschlagen:\n - "
|
||
|
|
+ "\n - ".join(beanstandungen))
|
||
|
|
|
||
|
|
# 4. Zurueckschreiben - im Format, das die Fachabteilung ohnehin benutzt.
|
||
|
|
schreibe_ergebnis(AUSGABE, problem, loesung)
|
||
|
|
|
||
|
|
print("=" * 66)
|
||
|
|
print(" PRODUKTIONSPLAN AUS DER EXCEL-MAPPE")
|
||
|
|
print("=" * 66)
|
||
|
|
for produkt in problem.produkte:
|
||
|
|
menge = loesung.werte[produkt.name]
|
||
|
|
print(f"{produkt.name:<18} {menge:8.1f} Stueck "
|
||
|
|
f"{menge * produkt.deckungsbeitrag:12,.2f} EUR")
|
||
|
|
print("-" * 66)
|
||
|
|
print(loesung.als_bericht())
|
||
|
|
print("Abnahmepruefung: bestanden\n")
|
||
|
|
|
||
|
|
# Die Schattenpreise beantworten die Frage, die der Plan nicht stellt:
|
||
|
|
# Was waere eine zusaetzliche Einheit dieser Ressource wert?
|
||
|
|
for ressource, preis in loesung.schattenpreise.items():
|
||
|
|
print(f" eine Einheit {ressource:<18} mehr waere wert: {preis:7.2f} EUR")
|
||
|
|
print("=" * 66)
|
||
|
|
print(f"Ergebnis geschrieben nach: {AUSGABE}")
|