Enhance Excel export functionality in backend and frontend; implement Excel file generation and update download logic for correct file extension

This commit is contained in:
Torsten Schulz (local)
2025-10-18 00:03:11 +02:00
parent 6a519fc4d4
commit 6b89272335
5 changed files with 872 additions and 23 deletions

View File

@@ -34,7 +34,7 @@ class ExportController {
}
/**
* Exportiert Daten als Excel
* Exportiert Daten als Excel (.xlsx)
*/
async exportExcel(req, res) {
try {
@@ -47,11 +47,11 @@ class ExportController {
});
}
const excel = await ExportService.exportExcel(userId, startDate, endDate);
const buffer = await ExportService.exportExcel(userId, startDate, endDate);
res.setHeader('Content-Type', 'text/csv; charset=utf-8');
res.setHeader('Content-Disposition', `attachment; filename="zeiterfassung_${startDate}_${endDate}.csv"`);
res.send(excel);
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', `attachment; filename="zeiterfassung_${startDate}_${endDate}.xlsx"`);
res.send(buffer);
} catch (error) {
console.error('Fehler beim Excel-Export:', error);
res.status(500).json({

View File

@@ -29,17 +29,49 @@ class ExportService {
}
/**
* Exportiert Daten als Excel (CSV mit Excel-kompatiblem Encoding)
* Exportiert Daten als echte Excel-Datei (.xlsx)
* @param {number} userId - User-ID
* @param {string} startDate - Startdatum
* @param {string} endDate - Enddatum
* @returns {Promise<string>} Excel-kompatibles CSV mit BOM
* @returns {Promise<Buffer>} Excel-Datei als Buffer
*/
async exportExcel(userId, startDate, endDate) {
const csv = await this.exportCSV(userId, startDate, endDate);
const ExcelJS = require('exceljs');
const data = await this._getExportData(userId, startDate, endDate);
// UTF-8 BOM für Excel
return '\ufeff' + csv;
// Erstelle Workbook
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Zeiterfassung');
// Definiere Spalten
worksheet.columns = [
{ header: 'Datum', key: 'date', width: 12 },
{ header: 'Uhrzeit', key: 'time', width: 10 },
{ header: 'Aktivität', key: 'activity', width: 20 },
{ header: 'Gesamt-Netto-Arbeitszeit', key: 'netWorkTime', width: 25 }
];
// Style für Header
worksheet.getRow(1).font = { bold: true };
worksheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE0E0E0' }
};
// Füge Daten hinzu
data.forEach(row => {
worksheet.addRow({
date: row.date,
time: row.time,
activity: row.activity,
netWorkTime: row.netWorkTime
});
});
// Generiere Buffer
const buffer = await workbook.xlsx.writeBuffer();
return buffer;
}
/**