Add ODF (.ods) support via odfpy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 11:48:03 +02:00
parent a0be34f66e
commit 2d9bce014f
4 changed files with 33 additions and 3 deletions
+9 -1
View File
@@ -1,6 +1,14 @@
# excel-import
Generisches Kommandozeilen-Tool zum Import von Excel-Dateien (`.xls` und `.xlsx`) in Oracle- und PostgreSQL-Datenbanken.
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
+11 -2
View File
@@ -5,8 +5,17 @@ import pandas as pd
from .config import SheetConfig
_ENGINES = {
".xls": "xlrd",
".xlsx": "openpyxl",
".xlsm": "openpyxl",
".xlsb": "openpyxl",
".ods": "odf",
}
def _engine_for(path: Path) -> str:
return "xlrd" if path.suffix.lower() == ".xls" else "openpyxl"
return _ENGINES[path.suffix.lower()]
class ExcelReader:
@@ -14,7 +23,7 @@ class ExcelReader:
self.path = Path(path)
if not self.path.exists():
raise FileNotFoundError(f"Excel file not found: {self.path}")
if self.path.suffix.lower() not in {".xls", ".xlsx", ".xlsm", ".xlsb"}:
if self.path.suffix.lower() not in _ENGINES:
raise ValueError(f"Unsupported file type: {self.path.suffix}")
def sheet_names(self) -> list[str]:
+1
View File
@@ -10,6 +10,7 @@ dependencies = [
"pandas>=2.0",
"openpyxl>=3.1",
"xlrd>=2.0",
"odfpy>=1.4",
"sqlalchemy>=2.0",
"psycopg2-binary>=2.9",
"oracledb>=2.0",
+12
View File
@@ -72,6 +72,18 @@ def test_read_column_skip(xlsx_file: Path):
assert "Preis" not in df.columns
def test_read_ods(tmp_path: Path):
pytest.importorskip("odf")
path = tmp_path / "test.ods"
df = pd.DataFrame({"Name": ["Alice", "Bob"], "Wert": [1, 2]})
df.to_excel(path, index=False, engine="odf")
reader = ExcelReader(path)
result = reader.read(SheetConfig(sheet=0, target_table="t"))
assert len(result) == 2
assert list(result.columns) == ["Name", "Wert"]
def test_file_not_found():
with pytest.raises(FileNotFoundError):
ExcelReader("/nonexistent/path/file.xlsx")