Als Selbstständiger kenne ich die Herausforderungen mit verschiedenen CSV-Formaten nur zu gut. Besonders die Exportdateien von CardComplete (GetMyInvoices) benötigen oft manuelle Nachbearbeitung für die Buchhaltung bzw. muss aus einer Reihe von Spalten der CardComplete CSV Export Datei die jeweils zugehörige Spalte von GetMyInvoices.com ausgewählt werden.
Heute zeige ich dir, wie ich eine einfache Desktop-App entwickelt habe, die diese Arbeit automatisiert.
Was wir entwickeln
Eine Mac/Windows-App, die per Drag & Drop CardComplete CSV-Dateien in ein standardisiertes Format umwandelt. Die fertige App ist sowohl für macOS als auch Windows verfügbar.
Voraussetzungen
- Node.js und npm
- Ein Code-Editor (VS Code empfohlen)
- Terminal/Kommandozeile
- Für Mac-Builds: macOS
- Für Windows-Builds auf Mac: Wine
Los geht’s: Projekt aufsetzen
Öffne dein Terminal und führe diese Befehle aus:
mkdir cardcomplete-converter
cd cardcomplete-converter
npm init -y
npm install electron electron-builder --save-dev
npm install csv-parser csv-writer
Die Projektstruktur
Wir benötigen folgende Dateien:
- main.js (Electron Hauptprozess)
- index.html (Benutzeroberfläche)
- renderer.js (Verarbeitungslogik)
- package.json (Projektkonfiguration)
- Ein Icon im build/icons Ordner
Die package.json
Hier ist unsere vollständige package.json:
{
"name": "cardcomplete-converter",
"version": "1.0.0",
"description": "CSV Converter for CardComplete GetMyInvoices data",
"author": "Your Name",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder --mac",
"build:win": "electron-builder --win",
"build:all": "electron-builder -mw"
},
"build": {
"appId": "com.csvconverter.app",
"mac": {
"category": "public.app-category.utilities",
"icon": "build/icons/icon.icns"
},
"win": {
"icon": "build/icons/icon.ico",
"target": [
{
"target": "nsis",
"arch": ["x64"]
},
{
"target": "portable"
}
]
}
},
"devDependencies": {
"electron": "^25.0.0",
"electron-builder": "^24.0.0"
},
"dependencies": {
"csv-parser": "^3.0.0",
"csv-writer": "^1.6.0"
}
}
Die Hauptanwendung (main.js)
const { app, BrowserWindow } = require('electron');
const path = require('path');
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
icon: path.join(__dirname, 'build/icons/icon.png')
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
Die Benutzeroberfläche (index.html)
<!DOCTYPE html>
<html>
<head>
<title>CardComplete CSV Converter</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
#dropZone {
width: calc(100% - 40px);
height: 300px;
border: 2px dashed #ccc;
border-radius: 10px;
text-align: center;
padding: 20px;
margin: 20px;
background: repeating-linear-gradient(
45deg,
#ffebeb,
#ffebeb 10px,
#fff5f5 10px,
#fff5f5 20px
);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2em;
color: #666;
transition: all 0.3s ease;
}
#dropZone:hover {
border-color: #999;
color: #333;
}
</style>
</head>
<body>
<div id="dropZone">
Drag & Drop CardComplete CSV File Here
</div>
<script src="renderer.js"></script>
</body>
</html>
Die Verarbeitungslogik (renderer.js)
const csv = require('csv-parser');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
const fs = require('fs');
const dropZone = document.getElementById('dropZone');
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
const files = e.dataTransfer.files;
if (files.length > 0) {
processCSV(files[0].path);
}
});
function processCSV(filePath) {
const results = [];
let isFirstLine = true;
fs.createReadStream(filePath)
.pipe(csv())
.on('data', (data) => {
if (isFirstLine && Object.values(data)[0] === 'SEP=,') {
isFirstLine = false;
return;
}
results.push({
value_date: data['DATUM-DATE'],
booking_date: data['BUCHUNGSDATUM-POSTING_DATE'],
transaction_type: data['BRANCHE-CATEGORY'],
description: data['HAENLDERNAME-MERCHANT_NAME'],
amount: data['BETRAG-AMOUNT'],
currency_code: data['WAEHRUNG-CURRENCY'],
client_account: '',
client_bank_code: '',
client_iban: '',
payment_partner_name: data['HAENLDERNAME-MERCHANT_NAME'],
tags: ''
});
isFirstLine = false;
})
.on('end', () => {
const outputPath = filePath.replace('.csv', '_converted.csv');
const csvWriter = createCsvWriter({
path: outputPath,
header: [
{id: 'booking_date', title: 'Buchungstag'},
{id: 'value_date', title: 'Wertstellung'},
{id: 'transaction_type', title: 'Umsatzart'},
{id: 'description', title: 'Buchungstext'},
{id: 'amount', title: 'Betrag'},
{id: 'currency_code', title: 'Währung'},
{id: 'client_account', title: 'Auftraggeberkonto'},
{id: 'client_bank_code', title: 'Bankleitzahl Auftraggeberkonto'},
{id: 'client_iban', title: 'IBAN Auftraggeberkonto'},
{id: 'payment_partner_name', title: 'Zahlungspartnername'},
{id: 'tags', title: 'Tags'}
]
});
csvWriter.writeRecords(results)
.then(() => {
alert('CSV conversion completed!');
});
});
}
Die App kompilieren
Für Mac:
npm run build
Für Windows:
npm run build:win
Die fertigen Installationsdateien findest du im dist Ordner.
Was macht die App?
- Zeigt eine Drop-Zone für CSV-Dateien
- Erkennt CardComplete CSV-Dateien
- Entfernt die „SEP=,“ Zeile
- Wandelt die Spaltennamen um
- Erstellt eine neue, bereinigte CSV-Datei
Besonderheiten
- Drag & Drop Interface
- Automatische Bereinigung
- Standardisierte Ausgabe
- Plattformunabhängig
- Keine Installation nötig (portable Version verfügbar)
Fazit
Mit dieser App sparen wir uns die manuelle Nachbearbeitung von CardComplete CSV-Dateien. Der Konvertierungsprozess ist auf einen Drag & Drop reduziert, und die Ausgabedatei ist sofort verwendbar.
Veröffentlicht am 14. Januar 2025



