Fallstudie · Handel

Excel, das weiterrechnet, statt Zahlen zu zeigen

Der Einkauf zieht seine Bestellvorschläge auf Knopfdruck aus dem ERP. Was herauskommt, ist eine Excel-Mappe mit echten Formeln: Menge im Blatt ändern, und die Reichweite rechnet sich neu.

Kunde
scoop Beschläge Produktion GmbH
Branche
Handel
Leistung
Office-Automatisierung, ERP-Anbindung, Betrieb
Zeitraum
Seit Dezember 2025, laufend

Ausgangslage

Die Bestellplanung im Einkauf lief über mehrere Exporte aus dem ERP, die von Hand zusammengeführt wurden: Artikelstamm, Bedarf, offene Bestellungen, Lagerbestand. Daraus entstand eine Arbeitsmappe, in der der Einkäufer dann gerechnet hat, welche Artikel nachbestellt werden müssen und wie lange der Bestand noch reicht.

Das funktioniert, kostet aber jedes Mal dieselbe Stunde, und jeder Schritt ist eine Stelle, an der eine Spalte verrutschen kann.

Ziel

Dieselben Zahlen und derselbe Aufbau wie bisher, nur ohne das Zusammenkopieren. Wichtig war dem Fachbereich, dass die Ausgabe eine echte Excel-Mappe bleibt, in der weitergearbeitet wird, und keine Weboberfläche, die Ergebnisse nur anzeigt.

Dazu ein paar feste Vorgaben: die Schwellenwerte für Reichweite und Kontrollverhältnis, ein Blatt je Artikelgruppe und Zugriff auf das ERP nur read-only.

Lösung

Eine Weboberfläche mit drei Registerkarten, eine je Auswertung. Oben wählt der Nutzer die Datenquelle: entweder direkt aus den Datenbanken oder, als Fallback, aus hochgeladenen Dateien. Jede hochgeladene Datei wird sofort geprüft, und der Erzeugen-Button bleibt gesperrt, solange etwas fehlt. Die Meldung benennt dann Spalte und Datei, statt dass der Lauf mittendrin abbricht.

Nach dem Klick fragt die App die Datenbanken ab, rechnet und baut die Arbeitsmappe: pro Artikelgruppe ein Blatt, je Artikel eine Hauptzeile und darunter Unterzeilen für offene Bestellungen und geplante Lieferungen. Die Spalten für Reichweite in Monaten und das „reicht bis“-Datum sind Formeln, und an der Kontrollspalte hängt eine bedingte Formatierung, die rot wird, wenn es knapp ist.

Oberfläche der Einkaufsanwendung mit den drei Auswertungen und der Auswahl zwischen Datenbankabfrage und Datei-Upload
Drei Auswertungen und die Auswahl der Datenquelle.

Ergebnis

Drei Auswertungen auf Knopfdruck statt aus vier Exporten von Hand zusammengeführt
Die Mappe rechnet weiter Menge anpassen, Reichweite und Datum aktualisieren sich im Blatt
Fehler vor dem Lauf fehlt eine Pflichtspalte, steht in der Meldung welche und in welcher Datei

Wo es knifflig wurde

Die Ausgabe muss selbst rechnen

Der Einkauf arbeitet in der erzeugten Datei weiter und will sehen, wie sich Reichweite und „reicht bis“-Datum ändern, wenn eine Menge angepasst wird. Fertige Zahlen hineinzuschreiben wäre einfach und wertlos, weil die erste Änderung im Blatt sie falsch macht. Die Mappe braucht also echte Formeln, und die müssen auf die Zeilen und Tabellen zeigen, an denen sie am Ende tatsächlich stehen. Damit lassen sich Sortierung, Gruppierung und Blattaufteilung nicht mehr von den Formeln trennen: jede spätere Umsortierung bricht die Bezüge. Position und Formel entstehen deshalb gemeinsam, bevor geschrieben wird.

Der Liefertermin ist ein Freitextfeld

Im ERP steht in diesem Feld, was Einkauf und Lieferanten hineingeschrieben haben: vollständige Datumsangaben, Angaben ohne Jahr, Kalenderwochen in mehreren Schreibweisen und Text wie „before CNY“. Einfach einen Datumsparser drüberlaufen zu lassen hilft nicht. Er scheitert an dem einen Teil und, schlimmer, er rät beim anderen das Jahr. Das ist der gefährliche Fall: eine Angabe ohne Jahr wird um den Jahreswechsel in die falsche Richtung aufgelöst, und eine längst überfällige Lieferung erscheint als künftige. Dazu muss die nicht auswertbare Angabe im Ergebnis erhalten bleiben, weil der Einkauf mit ihr etwas anfangen kann.

Bezahlte Ware, die noch nicht da ist, sieht man nicht

Für die Frage „was kommt noch?“ reicht die Liste offener Bestellungen nicht. Ware, die schon berechnet und bezahlt, aber noch nicht im Wareneingang verbucht ist, fällt aus der Bestellsicht heraus, obwohl sie disponiert werden muss. Naiv dazuaddiert zählt sie doppelt. Nötig war eine zweite Abfrage über Bestellung, Rechnung und Wareneingang, die je Position die schon empfangenen Mengen gegenrechnet. Und eine Anforderung, die man leicht übersieht: beide Auswertungen müssen auf demselben Datenstand beruhen, sonst passen Übersicht und Detailblatt nicht zusammen.

Technische Umsetzung

R Shiny box openxlsx2 pool odbc DBI bslib blastula renv Docker ShinyProxy GitHub Actions

Das zentrale Paket ist hier openxlsx2. Es ist das einzige der gängigen Excel-Pakete, mit dem sich Formeln, benannte Tabellen, bedingte Formatierung, Zellformate und verbundene Zellen in einem Durchgang setzen lassen, und genau das ist bei diesem Projekt das Produkt. Formelspalten werden dabei eigens markiert, damit Excel sie als Formel übernimmt statt als Text.

Die drei Module enthalten nur Ablaufsteuerung: prüfen, Button sperren, Fehler behandeln. Die Fachlogik liegt daneben und ist frei von Shiny. Deshalb hat der Wechsel von Datei-Upload auf direkte Datenbankabfragen die Oberfläche kaum berührt: jede Ladefunktion nimmt entweder einen Dateipfad oder einen fertigen Datensatz, und im Datenbankmodus fällt der Excel-Leseschritt einfach weg. Der Dateimodus bleibt damit als Fallback drin, wenn die Datenbank nicht erreichbar ist.

Die Abfragen sind handgeschriebenes SQL über einen Connection Pool, read-only. Sie bilden die Views des ERP nach und verknüpfen Bestellung, Rechnung und Wareneingang; in dplyr-Syntax wäre das nicht mehr lesbar. Die App selbst ist stateless: keine eigene Datenbank, kein Session-State, das Ergebnis ist die heruntergeladene Datei.

Geht etwas schief, sieht der Nutzer eine verständliche Meldung mit dem Hinweis, dass der Support informiert wurde, und das passiert auch: die App schickt automatisch eine Mail mit den beteiligten Dateien im Anhang. Bei einer Anwendung, deren Eingaben aus einem Freitextfeld und vier Exporten bestehen, ist das mehr wert als ein Logfile, in das niemand schaut.

Betrieb und Weiterentwicklung

Ein Push auf main baut das Image, legt es in einer privaten Registry ab und aktualisiert die Anwendung auf dem Server. Ausgeliefert wird über ShinyProxy, der auch den Login davor übernimmt; die Anwendung läuft im Container unter einem eigenen Benutzer. Credentials kommen nur zur Laufzeit aus Umgebungsvariablen.

R-Version und Paketstände sind über renv gepinnt, und die Systempakete für den Build werden aus dem Lockfile abgeleitet statt von Hand gelistet. Bei einer Anwendung, die einen ODBC-Treiber braucht, ist das ein spürbarer Unterschied.

Einen Scheduler gibt es nicht, alles läuft auf Klick. Ein Punkt bleibt bewusst offen: die Bedarfsauswertung muss auch im Datenbankmodus bei jedem Lauf hochgeladen werden, weil sie die einzige Größe ist, die nicht aus dem ERP kommt. Das ist die naheliegende nächste Ausbaustufe.