2d9bce014f
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
259 lines
6.6 KiB
Markdown
259 lines
6.6 KiB
Markdown
# excel-import
|
||
|
||
Generisches Kommandozeilen-Tool zum Import von Tabellendateien in Oracle- und PostgreSQL-Datenbanken.
|
||
|
||
Unterstützte Formate:
|
||
|
||
| Format | Endung | Paket |
|
||
|--------|--------|-------|
|
||
| Excel 97–2003 | `.xls` | `xlrd` |
|
||
| Excel 2007+ | `.xlsx`, `.xlsm`, `.xlsb` | `openpyxl` |
|
||
| OpenDocument (LibreOffice) | `.ods` | `odfpy` |
|
||
|
||
## 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
|
||
```
|