Files
excel-import/README.md
T
2026-05-13 12:05:29 +02:00

6.8 KiB
Raw Blame History

excel-import

Generisches Kommandozeilen-Tool zum Import von Tabellendateien in Oracle- und PostgreSQL-Datenbanken.

Unterstützte Formate:

Format Endung Paket
Excel 972003 .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

pip install -e .

Schnellstart

# 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.

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.

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.

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.

# 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. Der Spaltentyp wird aus den Daten und der Spalten-Konfiguration abgeleitet.

Enthält target_table einen Punkt (z.B. dl.tabelle1), wird der Teil vor dem Punkt als Datenbankschema interpretiert. Existiert dieses Schema noch nicht, wird es ebenfalls automatisch angelegt.

Existiert die Tabelle bereits, werden die Daten entsprechend dem gewählten Modus eingefügt — die Tabellenstruktur wird nicht geändert. Soll die Struktur angepasst werden, muss die Tabelle vorher manuell geändert oder gelöscht werden.


Beispiele

Vollständiger Import mit Upsert

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

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

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

pip install -e ".[dev]"
pytest