Files
excel-import/README.md
T
2026-05-13 11:33:44 +02:00

251 lines
6.4 KiB
Markdown

# excel-import
Generisches Kommandozeilen-Tool zum Import von Excel-Dateien (`.xls` und `.xlsx`) in Oracle- und PostgreSQL-Datenbanken.
## Voraussetzungen
- Python 3.10+
- Für PostgreSQL: `psycopg2-binary`
- Für Oracle: `oracledb` (kein Oracle Client nötig, nutzt den Thin-Modus)
## Installation
```bash
pip install -e .
```
## Schnellstart
```bash
# 1. Struktur der Excel-Datei anzeigen
excel-import inspect meine_datei.xlsx
# 2. Starter-Konfiguration automatisch erzeugen
excel-import generate-config meine_datei.xlsx --dsn "postgresql+psycopg2://user:pass@localhost/mydb"
# 3. Konfiguration anpassen (siehe unten)
# 4. Import ausführen
excel-import run meine_datei.xlsx import_config.yaml
```
---
## Befehle
### `inspect`
Zeigt die Sheets, Spalten und Zeilenzahl einer Excel-Datei — ohne Datenbank-Verbindung.
```bash
excel-import inspect datei.xlsx
```
Beispielausgabe:
```
Sheets in datei.xlsx:
[0] Artikel
Columns (4): Artikelnummer, Bezeichnung, Preis, Interne Notiz
Rows: 1250
[1] Kunden
Columns (3): Kundennummer, Name, E-Mail
Rows: 340
```
---
### `generate-config`
Erzeugt eine YAML-Konfigurationsdatei aus der Struktur der Excel-Datei. Die Datei kann danach manuell angepasst werden.
```bash
excel-import generate-config datei.xlsx \
--dsn "postgresql+psycopg2://user:pass@localhost/mydb" \
--output config.yaml
```
| Option | Standard | Beschreibung |
|--------|----------|--------------|
| `--dsn` | PostgreSQL-Beispiel | SQLAlchemy-DSN der Zieldatenbank |
| `--output` / `-o` | `import_config.yaml` | Ausgabedatei |
---
### `run`
Führt den Import anhand einer YAML-Konfigurationsdatei durch.
```bash
excel-import run datei.xlsx config.yaml
excel-import run datei.xlsx config.yaml --verbose
```
| Option | Beschreibung |
|--------|--------------|
| `-v` / `--verbose` | Ausführliche Ausgabe inkl. SQL-Details |
---
## Konfigurationsdatei
Die YAML-Konfiguration steuert, welche Sheets importiert werden, wie Spalten gemappt werden und welcher Import-Modus verwendet wird.
```yaml
# SQLAlchemy DSN — Beispiele:
# PostgreSQL: postgresql+psycopg2://user:pass@localhost/mydb
# Oracle: oracle+oracledb://user:pass@localhost:1521/?service_name=MYDB
dsn: "postgresql+psycopg2://user:pass@localhost/mydb"
default_varchar_length: 255 # Fallback-Länge für Text-Spalten
sheets:
- sheet: "Artikel" # Sheet-Name oder Index (0, 1, ...)
header_row: 0 # 0-basierter Zeilenindex der Kopfzeile
skip_rows: 0 # Zeilen vor der Kopfzeile überspringen
target_table: "artikel" # Ziel-Tabelle (wird angelegt, falls nicht vorhanden)
mode: "replace" # append | replace | upsert
upsert_keys: [] # Primärschlüssel-Spalten für Upsert
columns:
- source: "Artikelnummer"
target: "artikelnummer"
dtype: "VARCHAR(50)" # optional: Typ-Override
- source: "Bezeichnung"
target: "bezeichnung"
- source: "Preis"
target: "preis"
dtype: "NUMERIC(12,2)"
- source: "Interne Notiz"
target: "interne_notiz"
skip: true # Spalte nicht importieren
```
### Import-Modi
| Modus | Verhalten |
|-------|-----------|
| `append` | Zeilen werden an die bestehende Tabelle angehängt |
| `replace` | Tabelle wird geleert (TRUNCATE), dann neu befüllt |
| `upsert` | Zeilen werden eingefügt oder aktualisiert (anhand `upsert_keys`) |
### Spalten-Konfiguration
| Feld | Pflicht | Beschreibung |
|------|---------|--------------|
| `source` | ja | Spaltenname in der Excel-Datei |
| `target` | ja | Spaltenname in der Datenbank |
| `dtype` | nein | Typ-Override, z.B. `VARCHAR(100)`, `NUMERIC(12,2)`, `DATE` |
| `skip` | nein | Spalte komplett ignorieren (`true`/`false`) |
Unterstützte Typ-Overrides: `VARCHAR(n)`, `TEXT`, `CLOB`, `INTEGER`, `NUMBER`, `NUMERIC(p,s)`, `DECIMAL(p,s)`, `FLOAT`, `DATE`, `DATETIME`, `TIMESTAMP`, `BOOLEAN`.
Ohne `dtype` erkennt das Tool den Typ automatisch aus den Daten.
### Verbindungs-DSN
**PostgreSQL:**
```
postgresql+psycopg2://user:password@host:5432/datenbankname
```
**Oracle (Thin-Modus, kein Client nötig):**
```
oracle+oracledb://user:password@host:1521/?service_name=MYSERVICE
```
```
oracle+oracledb://user:password@host:1521/SID
```
---
## Tabellen-Verwaltung
Existiert die Ziel-Tabelle noch nicht, wird sie automatisch angelegt. Das Schema wird aus den Daten und der Spalten-Konfiguration abgeleitet.
Existiert die Tabelle bereits, werden die Daten entsprechend dem gewählten Modus eingefügt — die Tabellenstruktur wird **nicht** geändert. Soll das Schema angepasst werden, muss die Tabelle vorher manuell geändert oder gelöscht werden.
---
## Beispiele
### Vollständiger Import mit Upsert
```yaml
dsn: "postgresql+psycopg2://user:pass@localhost/mydb"
sheets:
- sheet: "Kunden"
target_table: "kunden"
mode: "upsert"
upsert_keys: ["kundennummer"]
columns:
- source: "Kundennummer"
target: "kundennummer"
dtype: "VARCHAR(20)"
- source: "Name"
target: "name"
- source: "E-Mail"
target: "email"
```
### Sheet per Index ansprechen
```yaml
sheets:
- sheet: 2 # drittes Sheet (0-basiert)
header_row: 1 # Kopfzeile ist in Zeile 2 (0-basiert: 1)
skip_rows: 0
target_table: "rohdaten"
mode: "append"
columns: [] # alle Spalten importieren, keine Umbenennung
```
### Mehrere Sheets in einem Lauf
```yaml
dsn: "oracle+oracledb://scott:tiger@localhost:1521/?service_name=ORCL"
sheets:
- sheet: "Artikel"
target_table: "artikel"
mode: "replace"
columns:
- source: "ArtNr"
target: "art_nr"
dtype: "VARCHAR(50)"
- source: "Preis"
target: "preis"
dtype: "NUMERIC(12,2)"
- sheet: "Lager"
target_table: "lagerbestand"
mode: "replace"
columns: []
```
---
## Projektstruktur
```
excel-import/
├── pyproject.toml
├── examples/
│ └── import_config.yaml
├── excel_import/
│ ├── config.py # Konfigurationsklassen + YAML-Loader
│ ├── reader.py # Excel-Einlesen (.xls + .xlsx)
│ ├── schema.py # Automatische Typ-Erkennung + DDL
│ ├── importer.py # Import-Logik (append/replace/upsert)
│ └── cli.py # Kommandozeilen-Interface
└── tests/
├── test_config.py
├── test_reader.py
└── test_importer.py
```
## Tests ausführen
```bash
pip install -e ".[dev]"
pytest
```