📊 KPI-Werte aus Excel per Python-Skript an ValueStreamer übertragen
In diesem Artikel erfahren Sie, wie Sie KPI-Werte (Plan/Ist) aus einer Excel-Datei automatisiert über die ValueStreamer REST API an ein bestimmtes Team und eine bestimmte KPI-ID übertragen. Das Beispiel nutzt ein Python-Skript, das Excel-Werte ausliest, für die API aufbereitet und per PUT-Request überträgt.
🔍 Inhalt
- Voraussetzungen
- Authentifizierung
- Funktionsweise des Skripts
- Beispiel-Code
- Technische Hinweise
- Tipps & Best Practices
- FAQ
Voraussetzungen
-
Python 3.8+ installiert
-
Installierte Python-Pakete:
pip install requests python-dotenv openpyxl -
Eine
.env
-Datei mit gültigen API-Zugangsdaten:
API_USERNAME=<Ihr Benutzername>
API_PASSWORD=<Ihr Passwort>
TENANT=<Ihr Tenant-Name> # z. B. showroom -
Eine Excel-Datei mit Plan- und Ist-Werten:
-
Erwartete Ausgaben (Zelle
F11
) -
Tatsächliche Ausgaben (Zelle
G11
)
-
ℹ️ Hinweis: Das Skript ist für die Standardstruktur im ValueStreamer-Showcase aufgebaut. Zelladressen, KPI-IDs oder Team-IDs müssen ggf. angepasst werden.
🔑 Authentifizierung
Die Anmeldung erfolgt per HTTP Basic Auth.
Zugangsdaten werden aus der .env
geladen und beim API-Request automatisch in den Header gesetzt.
Beispiel-Header:
Authorization: Basic <Base64(API_USERNAME:API_PASSWORD)>
Content-Type: application/vs.v2.0+json
📜 Funktionsweise des Skripts
-
Laden der Zugangsdaten aus
.env
-
Auslesen der Plan-/Ist-Werte aus der Excel-Datei
-
Konvertieren der Werte in numerisches Format
-
Aufbau der Ziel-URL für den PUT-Request
-
Erstellen des JSON-Bodys mit
kpiValueId
und Wert -
Senden des PUT-Requests an die KPI-API
-
Ausgabe der API-Antwort im Terminal
💻 Beispiel-Code
import os, sys, json, datetime as dt, requests
from requests.auth import HTTPBasicAuth
from dotenv import load_dotenv
from openpyxl import load_workbook
# Pfade & IDs
BASE_DIR = r"C:\Pfad\Zu\API"
EXCEL_PATH = os.path.join(BASE_DIR, "Automate Show Case.xlsx")
ENV_PATH = os.path.join(BASE_DIR, "Zugang.env")
TEAM_ID = "<TEAM_ID>"
KPI_ID = "<KPI_ID>"
KPI_VALUE_ID_PLANNED = "<KPI_VALUE_ID_PLANNED>"
KPI_VALUE_ID_ACTUAL = "<KPI_VALUE_ID_ACTUAL>"
CELL_PLANNED = "F11"
CELL_ACTUAL = "G11"
HEADERS = {"Content-Type": "application/vs.v2.0+json", "Accept": "application/json"}
# Zugang laden
load_dotenv(ENV_PATH)
auth = HTTPBasicAuth(os.getenv("API_USERNAME"), os.getenv("API_PASSWORD"))
tenant = os.getenv("TENANT")
# Excel-Werte lesen
wb = load_workbook(EXCEL_PATH, data_only=True)
ws = wb.active
planned = float(ws[CELL_PLANNED].value or 0)
actual = float(ws[CELL_ACTUAL].value or 0)
# API-URL
date_str = dt.date.today().strftime("%Y-%m-%d")
url = f"https://api-{tenant}.valuestreamer.de/api/exchange/kpi-data/{date_str}/{TEAM_ID}/{KPI_ID}"
# JSON-Body
payload = {
"values": [
{"kpiValueId": KPI_VALUE_ID_PLANNED, "value": planned},
{"kpiValueId": KPI_VALUE_ID_ACTUAL, "value": actual}
]
}
# PUT-Request
resp = requests.put(url, headers=HEADERS, auth=auth, json=payload, timeout=20)
print(resp.status_code, resp.text)
⚠️ Achtung:
-
IDs (
TEAM_ID
,KPI_ID
,KPI_VALUE_ID_PLANNED
,KPI_VALUE_ID_ACTUAL
) müssen zum Ziel-KPI im ValueStreamer passen. -
Werte werden überschrieben, wenn für das Datum bereits Einträge existieren.
📸 Screenshot: Terminalausgabe bei erfolgreicher Übertragung
📌 Technische Hinweise
-
Datumsformat:
YYYY-MM-DD
-
Excel-Parsing: Skript konvertiert auch Formate wie
7.777,50
korrekt in7777.50
. -
Timeout: 20 Sekunden
-
Fehlerbehandlung: Bei HTTP-Fehlern wird der genaue API-Fehlercode im Terminal ausgegeben.
✨ Tipps & Best Practices
-
Skript zunächst in Test-/Showroom-Tenant ausführen, bevor es in Produktivumgebungen läuft.
-
Für wiederkehrende Aufgaben Skript z. B. per Windows Aufgabenplanung oder cron automatisch starten.
-
Falls mehrere KPIs übertragen werden müssen, die Logik für
KPI_ID
undkpiValueId
modular aufbauen.
❓ FAQ
Kann ich mehrere KPIs gleichzeitig übertragen?
→ Ja, indem Sie weitere Einträge in payload["values"]
hinzufügen.
Was passiert, wenn eine Zelle in Excel leer ist?
→ Der Wert wird als 0.0
übertragen.
Muss die .env
-Datei im selben Ordner wie das Skript liegen?
→ Nicht zwingend, der Pfad kann im Skript angepasst werden.