const { app, BrowserWindow, shell, dialog } = require('electron'); const path = require('path'); const express = require('express'); const xlsx = require('xlsx'); const fs = require('fs'); const Store = require('electron-store'); // --- Store Setup --- const store = new Store(); // --- Express Server Setup --- const expressApp = express(); const PORT = 3000; // Middleware expressApp.use(express.static(path.join(__dirname, 'public'))); expressApp.use(express.json()); // Excel-Ordnerpfad aus Store oder Standard let excelFolderPath = store.get('excelPath') || path.join(__dirname, 'tabellen'); // Sicherstellen, dass der Ordner existiert if (!fs.existsSync(excelFolderPath)) { fs.mkdirSync(excelFolderPath, { recursive: true }); } // --- Routen --- // Abrufen von Daten für Jahr & Monat expressApp.get('/api/daten/:jahr/:monat', (req, res) => { const { jahr, monat } = req.params; const excelPath = path.join(excelFolderPath, `${jahr}.xlsx`); try { let workbook; if (!fs.existsSync(excelPath)) { workbook = xlsx.utils.book_new(); xlsx.writeFile(workbook, excelPath); } else { workbook = xlsx.readFile(excelPath); } if (!workbook.Sheets[monat]) { const ws = xlsx.utils.aoa_to_sheet([]); xlsx.utils.book_append_sheet(workbook, ws, monat); xlsx.writeFile(workbook, excelPath); return res.json([]); } const data = xlsx.utils.sheet_to_json(workbook.Sheets[monat], { header: 1 }); res.json(data || []); } catch (err) { console.error('Fehler beim Abrufen der Daten:', err); res.status(500).json({ error: 'Interner Serverfehler.' }); } }); // Zeile speichern expressApp.post('/api/zeile-speichern', (req, res) => { let { rowIndex, updatedRowData, jahr, monat } = req.body; const excelPath = path.join(excelFolderPath, `${jahr}.xlsx`); try { if (!fs.existsSync(excelPath)) { return res.status(404).json({ error: `Datei für Jahr ${jahr} nicht gefunden.` }); } const workbook = xlsx.readFile(excelPath); if (!workbook.Sheets[monat]) { return res.status(404).json({ error: `Blatt für Monat ${monat} nicht gefunden.` }); } const worksheet = workbook.Sheets[monat]; const data = xlsx.utils.sheet_to_json(worksheet, { header: 1 }) || []; if (rowIndex < 0 || rowIndex >= data.length) { rowIndex = data.length; data.push(updatedRowData); } else { data[rowIndex] = updatedRowData; } workbook.Sheets[monat] = xlsx.utils.aoa_to_sheet(data); xlsx.writeFile(workbook, excelPath); res.json({ message: 'Zeile erfolgreich gespeichert!' }); } catch (err) { console.error('Fehler beim Speichern der Zeile:', err); res.status(500).json({ error: 'Interner Serverfehler.' }); } }); // Zeile löschen expressApp.post('/api/zeile-loeschen', (req, res) => { const { jahr, monat, zeileIndex } = req.body; const excelPath = path.join(excelFolderPath, `${jahr}.xlsx`); try { if (!fs.existsSync(excelPath)) { return res.status(404).json({ error: `Datei für Jahr ${jahr} nicht gefunden.` }); } const workbook = xlsx.readFile(excelPath); if (!workbook.Sheets[monat]) { return res.status(404).json({ error: `Blatt für Monat ${monat} nicht gefunden.` }); } const worksheet = workbook.Sheets[monat]; const data = xlsx.utils.sheet_to_json(worksheet, { header: 1 }) || []; if (zeileIndex < 0 || zeileIndex >= data.length) { return res.status(404).json({ error: `Zeile ${zeileIndex} nicht gefunden.` }); } data.splice(zeileIndex, 1); workbook.Sheets[monat] = xlsx.utils.aoa_to_sheet(data); xlsx.writeFile(workbook, excelPath); res.json({ message: 'Zeile erfolgreich gelöscht!' }); } catch (err) { console.error('Fehler beim Löschen der Zeile:', err); res.status(500).json({ error: 'Interner Serverfehler.' }); } }); // Ordner öffnen expressApp.get('/api/ordner-oeffnen', (req, res) => { try { shell.openPath(excelFolderPath); res.json({ message: 'Ordner geöffnet' }); } catch (err) { console.error(err); res.status(500).json({ error: 'Ordner konnte nicht geöffnet werden' }); } }); // Pfad ändern über Dialog expressApp.post('/api/pfad-aendern', async (req, res) => { try { const result = await dialog.showOpenDialog(mainWindow, { properties: ['openDirectory'] }); if (!result.canceled && result.filePaths.length > 0) { excelFolderPath = result.filePaths[0]; store.set('excelPath', excelFolderPath); console.log('Neuer Excel-Pfad:', excelFolderPath); return res.json({ message: 'Pfad geändert', path: excelFolderPath }); } res.json({ message: 'Abgebrochen' }); } catch (err) { console.error(err); res.status(500).json({ error: 'Pfad konnte nicht geändert werden' }); } }); // --- Express Server starten --- let server; function startExpressServer() { return new Promise((resolve, reject) => { server = expressApp.listen(PORT, 'localhost', (err) => { if (err) reject(err); else { console.log(`Express Server läuft auf http://localhost:${PORT}`); resolve(); } }); }); } // --- Electron App Setup --- let mainWindow; function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') }, show: false }); mainWindow.loadURL(`http://localhost:${PORT}`); mainWindow.once('ready-to-show', () => mainWindow.show()); if (process.env.NODE_ENV === 'development') { mainWindow.webContents.openDevTools(); } mainWindow.on('closed', () => { mainWindow = null; }); } // --- App Events --- app.whenReady().then(async () => { try { await startExpressServer(); createWindow(); } catch (error) { console.error('Fehler beim Starten:', error); app.quit(); } }); app.on('window-all-closed', () => { if (server) server.close(); if (process.platform !== 'darwin') app.quit(); }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); app.on('before-quit', () => { if (server) server.close(); });