257 lines
6.2 KiB
HTML
257 lines
6.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>User – Excel Import / Export</title>
|
||
|
||
<script src="/backend/xlsx/xlsx.full.min.js"></script>
|
||
<script src="/backend/handsontable/handsontable/dist/handsontable.full.min.js"></script>
|
||
<link rel="stylesheet" href="/backend/handsontable/handsontable/dist/handsontable.full.min.css">
|
||
|
||
<style>
|
||
/* ===== BASE THEME (Workbench / HMI) ===== */
|
||
:root{
|
||
--bg:#0b1020;
|
||
--card:rgba(255,255,255,0.08);
|
||
--border:rgba(255,255,255,0.14);
|
||
--text:rgba(255,255,255,0.92);
|
||
--muted:rgba(255,255,255,0.6);
|
||
--accent:#4f7cff;
|
||
--shadow:0 16px 60px rgba(0,0,0,.4);
|
||
--radius:20px;
|
||
}
|
||
|
||
*{box-sizing:border-box}
|
||
html,body{height:100%}
|
||
|
||
body{
|
||
margin:0;
|
||
padding:16px;
|
||
font-family:-apple-system,system-ui,Segoe UI,Roboto;
|
||
background:
|
||
radial-gradient(900px 600px at 20% 10%, rgba(79,124,255,.35), transparent 60%),
|
||
var(--bg);
|
||
color:var(--text);
|
||
}
|
||
|
||
/* ===== LAYOUT ===== */
|
||
.app{
|
||
max-width:1400px;
|
||
margin:0 auto;
|
||
height:100%;
|
||
display:grid;
|
||
grid-template-rows:auto 1fr;
|
||
gap:16px;
|
||
}
|
||
|
||
.panel{
|
||
background:linear-gradient(180deg,var(--card),rgba(255,255,255,.04));
|
||
border:1px solid var(--border);
|
||
border-radius:var(--radius);
|
||
box-shadow:var(--shadow);
|
||
overflow:hidden;
|
||
}
|
||
|
||
.header{
|
||
padding:14px 18px;
|
||
display:flex;
|
||
align-items:center;
|
||
justify-content:space-between;
|
||
border-bottom:1px solid var(--border);
|
||
}
|
||
|
||
.header h1{
|
||
margin:0;
|
||
font-size:18px;
|
||
}
|
||
|
||
/* ===== CONTENT ===== */
|
||
.content{
|
||
padding:16px;
|
||
display:flex;
|
||
flex-direction:column;
|
||
gap:14px;
|
||
height:100%;
|
||
}
|
||
|
||
/* ===== ACTION BAR ===== */
|
||
.actions{
|
||
display:flex;
|
||
gap:12px;
|
||
align-items:center;
|
||
}
|
||
|
||
input[type="file"]{
|
||
color:var(--muted);
|
||
}
|
||
|
||
/* ===== BUTTONS ===== */
|
||
button{
|
||
padding:10px 18px;
|
||
border-radius:14px;
|
||
border:0;
|
||
background:var(--accent);
|
||
color:#fff;
|
||
font-size:14px;
|
||
cursor:pointer;
|
||
}
|
||
|
||
button.secondary{
|
||
background:rgba(255,255,255,.12);
|
||
}
|
||
|
||
button:hover{
|
||
filter:brightness(1.1);
|
||
}
|
||
|
||
/* ===== HANDSONTABLE ===== */
|
||
#import-table{
|
||
flex:1;
|
||
overflow:hidden;
|
||
border-radius:14px;
|
||
border:1px solid var(--border);
|
||
}
|
||
|
||
.handsontable{
|
||
background:transparent;
|
||
}
|
||
|
||
.ht_master .wtHolder{
|
||
background:transparent;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<main class="app">
|
||
|
||
<!-- HEADER -->
|
||
<section class="panel">
|
||
<div class="header">
|
||
<h1>User – Excel Import / Export</h1>
|
||
<div class="actions">
|
||
<button id="export-button" class="secondary">Excel Export</button>
|
||
<button id="send-button">Daten senden</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- CONTENT -->
|
||
<section class="panel content">
|
||
<div class="actions">
|
||
<input type="file" id="file-input" accept=".xlsx">
|
||
</div>
|
||
<div id="import-table"></div>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
let importedData = [];
|
||
let hot;
|
||
|
||
const url = sessionStorage.getItem("url");
|
||
const stationNumber = sessionStorage.getItem("stationNumber");
|
||
|
||
/* ===== EXPORT ===== */
|
||
function exportExcel() {
|
||
fetch(url + '/backend/api/getUsers', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ station: stationNumber })
|
||
})
|
||
.then(r => r.json())
|
||
.then(data => {
|
||
if (!data || data.length === 0) {
|
||
alert("Keine Daten zum Exportieren.");
|
||
return;
|
||
}
|
||
|
||
const headers = Object.keys(data[0]);
|
||
const rows = data.map(o => headers.map(h => o[h]));
|
||
const worksheet = XLSX.utils.aoa_to_sheet([headers, ...rows]);
|
||
const workbook = XLSX.utils.book_new();
|
||
XLSX.utils.book_append_sheet(workbook, worksheet, "Users");
|
||
XLSX.writeFile(workbook, "UsersExport.xlsx");
|
||
})
|
||
.catch(err => alert("Fehler beim Exportieren: " + err.message));
|
||
}
|
||
|
||
/* ===== IMPORT (leere Zeilen ignorieren) ===== */
|
||
function importExcelData() {
|
||
const fileInput = document.getElementById("file-input");
|
||
if (!fileInput.files.length) return;
|
||
|
||
const reader = new FileReader();
|
||
reader.onload = function (event) {
|
||
const workbook = XLSX.read(event.target.result, { type: "binary" });
|
||
const sheet = workbook.Sheets[workbook.SheetNames[0]];
|
||
const rawData = XLSX.utils.sheet_to_json(sheet, { header: 1 });
|
||
|
||
if (rawData.length < 2) return;
|
||
|
||
const headers = rawData[0];
|
||
|
||
// ✅ Leere Zeilen entfernen
|
||
importedData = rawData
|
||
.slice(1)
|
||
.filter(row =>
|
||
Array.isArray(row) &&
|
||
row.some(cell =>
|
||
cell !== null &&
|
||
cell !== undefined &&
|
||
String(cell).trim() !== ""
|
||
)
|
||
);
|
||
|
||
if (hot) {
|
||
hot.loadData(importedData);
|
||
hot.updateSettings({ colHeaders: headers });
|
||
} else {
|
||
hot = new Handsontable(document.getElementById("import-table"), {
|
||
data: importedData,
|
||
colHeaders: headers,
|
||
rowHeaders: true,
|
||
width: "100%",
|
||
height: "100%",
|
||
licenseKey: "non-commercial-and-evaluation"
|
||
});
|
||
}
|
||
};
|
||
reader.readAsBinaryString(fileInput.files[0]);
|
||
}
|
||
|
||
/* ===== SEND ===== */
|
||
function sendExcelData() {
|
||
const jsonData = importedData.map(row => {
|
||
const obj = {};
|
||
hot.getColHeader().forEach((h, i) => {
|
||
obj[h] = row[i] || "";
|
||
});
|
||
return obj;
|
||
});
|
||
|
||
fetch(url + '/backend/api/importUser', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ station: stationNumber, data: jsonData })
|
||
})
|
||
.then(r => {
|
||
if (!r.ok) throw new Error(r.status);
|
||
return r.json();
|
||
})
|
||
.then(() => alert("Daten erfolgreich gesendet!"))
|
||
.catch(err => alert("Fehler beim Senden der Daten: " + err.message));
|
||
}
|
||
|
||
document.getElementById("export-button").addEventListener("click", exportExcel);
|
||
document.getElementById("file-input").addEventListener("change", importExcelData);
|
||
document.getElementById("send-button").addEventListener("click", sendExcelData);
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|