From a04748b82f35d904cabf8c73ae9adb325f72dd80 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Fri, 11 Sep 2026 15:45:16 +0200 Subject: [PATCH] Excel-Dateien: keine Sackgasse mehr im Auswahlfenster Filipe: "wenn ich auf screen1 druecke geht mein ordner auf aber meine excel datei kann ich nicht auswaehlen wieso??" Im Feld stand accept=".csv,text/csv,text/plain". Die .xlsx war damit ausgegraut -- ohne ein Wort dazu. Eine Sackgasse ohne Wegweiser ist schlimmer als eine Absage mit Begruendung: Man sucht den Fehler bei sich. WARUM SIE NICHT EINFACH GELESEN WIRD: Der Leser dahinter (csvZerlegen) versteht Text -- Komma, Semikolon, Tabulator. Eine .xlsx ist in Wahrheit ein ZIP-Archiv. Als Text gelesen ergibt sie Zeichensalat, und der schlimmste Ausgang waere nicht "geht nicht", sondern eine Vorschau mit Zahlen aus dem Dateikopf. Das Feld einfach zu oeffnen, ohne den Fall zu behandeln, haette aus einer klaren Sperre einen unklaren Fehlschlag gemacht. Jetzt laesst sich jede Datei waehlen, und WAS sie ist, sagt der INHALT -- die ersten Bytes, nicht die Endung. Eine umbenannte Datei ist keine andere Datei. .xlsx beginnt mit "PK" (ZIP), die alte .xls mit dem OLE-Kennzeichen D0 CF 11 E0. Und dann steht da, was stattdessen zu tun ist, mit ZWEI Wegen: 1. In Excel markieren, Strg+C, und den Knopf "Backstage-Tabelle einfuegen" nehmen -- der versteht TAB-getrennte Zeilen, also genau das, was beim Kopieren aus Excel in der Zwischenablage liegt. Das geht sofort und ohne Umspeichern. 2. Oder in Excel als "CSV UTF-8" speichern. Der erste Weg funktionierte schon vorher -- er stand nur nirgends. Nebenbei: Eine leere Datei meldet jetzt "Die Datei ist leer" statt durch die Vorschau zu laufen, und eine abgewiesene Datei bleibt nicht im Feld stehen. pruef-backstage-import 66 -> 72. Geprueft wird an einem echten ZIP-Kopf, nicht an der Endung: Die Testdatei heisst .xlsx UND traegt das Kennzeichen -- eine Pruefung ueber den Namen waere gruen, ohne die Erkennung je zu beruehren. Mit Gegenprobe, dass eine echte CSV denselben Weg weiterhin durchlaeuft; sonst hiesse das nur, dass gar nichts mehr eingelesen wird. Co-Authored-By: Claude Opus 5 --- server/pruef-backstage-import.mjs | 59 +++++++++++++++++++++++++++++++ workspace/app.webmanifest | 8 ++--- workspace/assets/js/leistung.js | 42 ++++++++++++++++++++++ workspace/aufgaben.html | 24 ++++++------- workspace/automation.html | 26 +++++++------- workspace/bereich.html | 34 +++++++++--------- workspace/calls.html | 28 +++++++-------- workspace/chat.html | 26 +++++++------- workspace/content.html | 30 ++++++++-------- workspace/crew-index.html | 10 +++--- workspace/crew.webmanifest | 8 ++--- workspace/dateien.html | 26 +++++++------- workspace/index.html | 8 ++--- workspace/kalender.html | 28 +++++++-------- workspace/leistung.html | 47 +++++++++++++++--------- workspace/personen.html | 26 +++++++------- workspace/profil.html | 28 +++++++-------- workspace/report.html | 28 +++++++-------- workspace/scouting.html | 26 +++++++------- workspace/start.html | 24 ++++++------- workspace/startcheck.html | 28 +++++++-------- workspace/steckbrief.html | 26 +++++++------- workspace/team.html | 26 +++++++------- workspace/teamlage.html | 24 ++++++------- workspace/uebersicht.html | 26 +++++++------- workspace/wissen.html | 26 +++++++------- 26 files changed, 403 insertions(+), 289 deletions(-) diff --git a/server/pruef-backstage-import.mjs b/server/pruef-backstage-import.mjs index fc65afd6..532f333e 100644 --- a/server/pruef-backstage-import.mjs +++ b/server/pruef-backstage-import.mjs @@ -397,6 +397,65 @@ console.log("\n=== Die Seite ==="); ok(/Backstage/.test(netzSatz), "unter den Knöpfen steht dauerhaft, woher die Zahlen kommen"); + /* ---- EINE EXCEL-DATEI IST EINE SACKGASSE MIT WEGWEISER ---------- + Filipe: "meine excel datei kann ich nicht auswaehlen wieso??" + + Sie liess sich nicht einmal AUSWAEHLEN -- ausgegraut, ohne ein + Wort dazu. Jetzt laesst sie sich waehlen und bekommt eine Antwort, + die weiterhilft. + + GEPRUEFT WIRD AN EINEM ECHTEN ZIP-KOPF ("PK"), denn genau das ist + eine .xlsx. Die Erkennung haengt am INHALT, nicht an der Endung -- + deshalb heisst die Testdatei hier bewusst ".xlsx" UND traegt den + richtigen Kopf; eine Pruefung ueber die Endung waere gruen, ohne + die Erkennung je zu beruehren. */ + await seite.click("#import-oeffnen"); + await seite.waitForTimeout(300); + await seite.setInputFiles("#datei", { + name: "backstage.xlsx", + mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + buffer: Buffer.from([0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00, 0x08, 0x00]), + }); + await seite.waitForTimeout(600); + const xlsx = await seite.evaluate(() => ({ + text: document.getElementById("import-fehler")?.textContent || "", + vorschau: document.getElementById("vorschau")?.hidden, + los: document.getElementById("import-los")?.disabled, + feld: document.getElementById("datei")?.value || "", + })); + ok(/Excel/.test(xlsx.text), `es steht da, dass es eine Excel-Datei ist (${xlsx.text.slice(0, 50)}…)`); + ok(/Backstage-Tabelle einfügen/.test(xlsx.text), + "und welcher Knopf stattdessen hilft"); + ok(/CSV/.test(xlsx.text), "und wie man sie umspeichert"); + ok(xlsx.vorschau === true && xlsx.los === true, + "es entsteht KEINE Vorschau und der Übernehmen-Knopf bleibt gesperrt"); + ok(xlsx.feld === "", + "und das Feld ist wieder leer -- eine Datei, die nicht geht, bleibt nicht stehen"); + if (process.env.SCHIRM) { + await seite.locator("#import-dialog").screenshot( + { path: join(HIER, "pruef-import-excel.png") }); + } + + /* GEGENPROBE: Eine echte Text-Tabelle geht durch denselben Weg + weiterhin hindurch. Sonst hiesse das oben nur, dass gar nichts + mehr eingelesen wird. */ + await seite.setInputFiles("#datei", { + name: "tage.csv", + mimeType: "text/csv", + buffer: Buffer.from(`Datum;Diamanten;LIVE-Dauer (Minuten) +${gestern};1234;90 +`, "utf8"), + }); + await seite.waitForTimeout(900); + const csv = await seite.evaluate(() => ({ + fehler: document.getElementById("import-fehler")?.textContent || "", + vorschau: document.getElementById("vorschau")?.hidden, + })); + ok(csv.vorschau === false && !/Excel/.test(csv.fehler), + `eine CSV kommt weiterhin durch (Vorschau da: ${csv.vorschau === false})`); + await seite.click("#import-zu"); + await seite.waitForTimeout(250); + /* ---- DER WEG UEBER DIE TIKTOK-DATEI IST WEG (11.09.2026) -------- Filipe: "ich will keine daten von denen kriegen, nur wir." diff --git a/workspace/app.webmanifest b/workspace/app.webmanifest index 075b7aee..64591473 100644 --- a/workspace/app.webmanifest +++ b/workspace/app.webmanifest @@ -13,25 +13,25 @@ "theme_color": "#06090f", "icons": [ { - "src": "/assets/img/app-symbole/workspace-192.png?v=202609111522", + "src": "/assets/img/app-symbole/workspace-192.png?v=202609111545", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-512.png?v=202609111522", + "src": "/assets/img/app-symbole/workspace-512.png?v=202609111545", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609111522", + "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609111545", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609111522", + "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609111545", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/assets/js/leistung.js b/workspace/assets/js/leistung.js index 70e2ab9a..6acb200c 100644 --- a/workspace/assets/js/leistung.js +++ b/workspace/assets/js/leistung.js @@ -456,6 +456,41 @@ $('vorschau').hidden = true; $('import-los').disabled = true; + /* WAS IST DAS UEBERHAUPT FUER EINE DATEI? (11.09.2026) + + Filipe: "meine excel datei kann ich nicht auswaehlen wieso??" + + Bis heute stand im Auswahlfeld nur `.csv` -- eine .xlsx war + ausgegraut, ohne ein Wort dazu. Eine Sackgasse ohne Wegweiser + ist schlimmer als eine Absage mit Begruendung: Man sucht den + Fehler bei sich. + + Jetzt laesst sich jede Datei waehlen, und WAS sie ist, sagt der + INHALT -- nicht die Endung. Eine umbenannte Datei ist keine + andere Datei. Eine .xlsx ist in Wahrheit ein ZIP-Archiv und + beginnt mit "PK"; die alte .xls beginnt mit dem + OLE-Kennzeichen D0 CF 11 E0. + + WARUM WIR SIE NICHT EINFACH LESEN: Der Leser dahinter versteht + Text (Komma, Semikolon, Tabulator). Ein ZIP-Archiv als Text + gelesen ergibt Zeichensalat -- und der schlimmste Ausgang waere + nicht "geht nicht", sondern eine Vorschau mit Zahlen, die + irgendwo aus dem Dateikopf stammen. */ + const anfang = new Uint8Array(await datei.slice(0, 8).arrayBuffer()); + const beginnt = (...b) => b.every((x, i) => anfang[i] === x); + if (beginnt(0x50, 0x4b) || beginnt(0xd0, 0xcf, 0x11, 0xe0)) { + $('import-fehler').innerHTML = + 'Das ist eine Excel-Datei. Hier passt eine Text-Tabelle ' + + '(CSV) hinein. Zwei Wege, beide dauern keine Minute:
' + + '1. In Excel alles markieren (Strg+A), kopieren (Strg+C) – ' + + 'und statt hier den Knopf „Backstage-Tabelle einfügen" nehmen. ' + + 'Dort einfügen, fertig.
' + + '2. Oder in Excel: Datei → Speichern unter und als ' + + 'Dateityp CSV UTF-8 (durch Trennzeichen getrennt) wählen.'; + $('datei').value = ''; + return; + } + try { importText = await datei.text(); } catch { @@ -463,6 +498,13 @@ return; } + /* Eine leere Datei ist kein Lesefehler, sieht aber wie einer aus. */ + if (!importText.trim()) { + $('import-fehler').textContent = 'Die Datei ist leer.'; + $('datei').value = ''; + return; + } + /* ERST DIE VORSCHAU. Ein Import, der sofort schreibt, ist bei einer falsch zugeordneten Spalte nicht mehr zurückzuholen. */ try { diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 2aa06edf..c1ac7b6e 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -12,19 +12,19 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + - + @@ -252,10 +252,10 @@ - - - - - + + + + + diff --git a/workspace/automation.html b/workspace/automation.html index 9909421c..dfd2f027 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -147,10 +147,10 @@ - - - - - + + + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 5a6719cd..44e2e991 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -181,14 +181,14 @@ - - - - - - - - - + + + + + + + + + diff --git a/workspace/calls.html b/workspace/calls.html index 0fb005db..27eec72f 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -89,11 +89,11 @@ - - - - - - + + + + + + diff --git a/workspace/chat.html b/workspace/chat.html index d6004f11..f8ab107d 100644 --- a/workspace/chat.html +++ b/workspace/chat.html @@ -12,26 +12,26 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + - + @@ -341,10 +341,10 @@ - - - - - + + + + + diff --git a/workspace/content.html b/workspace/content.html index 4034a81f..73b80fd4 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -179,12 +179,12 @@ - - - - - - - + + + + + + + diff --git a/workspace/crew-index.html b/workspace/crew-index.html index bb0ab2f4..61a4ccdf 100644 --- a/workspace/crew-index.html +++ b/workspace/crew-index.html @@ -30,15 +30,15 @@ - - - + + + - + @@ -252,6 +252,6 @@ - + diff --git a/workspace/crew.webmanifest b/workspace/crew.webmanifest index 86f77415..7d89803d 100644 --- a/workspace/crew.webmanifest +++ b/workspace/crew.webmanifest @@ -13,25 +13,25 @@ "theme_color": "#06090f", "icons": [ { - "src": "/assets/img/app-symbole/crew-192.png?v=202609111522", + "src": "/assets/img/app-symbole/crew-192.png?v=202609111545", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-512.png?v=202609111522", + "src": "/assets/img/app-symbole/crew-512.png?v=202609111545", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609111522", + "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609111545", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609111522", + "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609111545", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/dateien.html b/workspace/dateien.html index 021a8d26..c25ffa27 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -108,10 +108,10 @@ - - - - - + + + + + diff --git a/workspace/index.html b/workspace/index.html index 54f8a0fa..6f4709d0 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -30,9 +30,9 @@ - - - + + + @@ -401,6 +401,6 @@ - + diff --git a/workspace/kalender.html b/workspace/kalender.html index c697db52..d34849df 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -377,11 +377,11 @@ - - - - - - + + + + + + diff --git a/workspace/leistung.html b/workspace/leistung.html index cc6cdc67..2d7f5533 100644 --- a/workspace/leistung.html +++ b/workspace/leistung.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -332,14 +332,27 @@

Aus dem Export einlesen

- Die CSV-Datei aus TikTok LIVE Backstage. Erst siehst du, was passieren - würde – geschrieben wird erst, wenn du bestätigst. Dieselbe Datei - zweimal einzulesen richtet keinen Schaden an. + Eine Text-Tabelle (CSV) mit einer Zeile je Tag. Erst + siehst du, was passieren würde – geschrieben wird erst, wenn du + bestätigst. Dieselbe Datei zweimal einzulesen richtet keinen Schaden an. +
Eine Excel-Datei (.xlsx) passt hier + nicht hinein – dafür gibt es den Knopf „Backstage-Tabelle einfügen": + in Excel markieren, kopieren, dort einfügen.

- + +
@@ -353,10 +366,10 @@
- - - - - + + + + + diff --git a/workspace/personen.html b/workspace/personen.html index 32c4641d..e7f320f6 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -396,10 +396,10 @@ - - - - - + + + + + diff --git a/workspace/profil.html b/workspace/profil.html index ec231d14..9395aafe 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -214,11 +214,11 @@ - - - - - - + + + + + + diff --git a/workspace/report.html b/workspace/report.html index b37a5fb3..02d5e3fb 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -106,11 +106,11 @@ - - - - - - + + + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index cfa82b03..a53a4d24 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -173,10 +173,10 @@ - - - - - + + + + + diff --git a/workspace/start.html b/workspace/start.html index e59b7e4e..19f28341 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -12,21 +12,21 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - + + - + @@ -674,10 +674,10 @@

- - - - - + + + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index fa0da082..4abefc62 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -85,11 +85,11 @@ - - - - - - + + + + + + diff --git a/workspace/steckbrief.html b/workspace/steckbrief.html index d13eba2d..f4531768 100644 --- a/workspace/steckbrief.html +++ b/workspace/steckbrief.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -126,10 +126,10 @@ - - - - - + + + + + diff --git a/workspace/team.html b/workspace/team.html index 3abe3786..4e7506b0 100644 --- a/workspace/team.html +++ b/workspace/team.html @@ -7,20 +7,20 @@ - - - - - - - + + + + + + + - + @@ -110,10 +110,10 @@ - - - - - + + + + + diff --git a/workspace/teamlage.html b/workspace/teamlage.html index 2305940d..59f113a4 100644 --- a/workspace/teamlage.html +++ b/workspace/teamlage.html @@ -7,20 +7,20 @@ - - - - - - - + + + + + + + - + - - - - + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index a96d0b3e..ff6bc8fd 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -12,22 +12,22 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + - + @@ -149,11 +149,11 @@ - + - - - - + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index fd9188a3..17eaea38 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -190,10 +190,10 @@ - - - - - + + + + +