Table Format Converter
A browser-only tool to read structured tabular data (CSV, Parquet, JSON, NDJSON,
Excel, ODS, Apple Numbers, DuckDB, SQLite, Markdown, HTML), inspect its structure, adjust the parsing heuristic, and
export it to a different format. Your data never leaves the browser — all
processing happens locally with DuckDB-WASM and SheetJS.
Workflow
- Drop a file onto the drop zone, or click to pick one. You can also select
several files at once — see Multiple files below.
- The app detects format and parsing parameters from a small sample
and shows a preview of the first 10 rows plus the schema.
- Adjust any parameter on the left panel — the preview re-runs live
(debounced ~300 ms).
- Pick a target format and options, then click Export. Only at
this point is the full file read end-to-end.
Sample-first performance
Drop is instant regardless of file size, and the first preview appears
within ~100 ms even for multi-GB files:
- Files > 512 KB — registered as a lazy
FileReader handle (no bytes loaded). A small
512 KB head slice is pre-loaded into the WASM
heap and used for all preview / detection queries — they never touch
the rest of the file.
- Files ≤ 512 KB — loaded entirely into the heap
once and reused for both preview and export.
- Parquet — column-pruned + row-group-pruned by DuckDB,
so even full reads only fetch what the query actually needs.
- JSON (array) — a JSON array is one value, so a full read
would load the whole file. The preview instead parses only a
head slice and extracts the first complete elements; the full array is
read only on export.
- SQLite — read with sql.js, which loads the whole
database into memory (practical up to ~1 GB). DuckDB-WASM's sqlite
scanner can't open a lazily-registered browser file, so larger databases
can't be opened in-browser — convert the needed table to Parquet first
(see below).
- Excel / ODS / Numbers — must be loaded fully (SheetJS
doesn't stream), but parsed in a compact (
dense) model and
the heuristic peeks at only the first 100 rows per sheet.
- Markdown — table detection / preview parse only a 1 MB
head slice; the full file is re-parsed on export.
- Export — always reads the full file; this is
the only stage where the entire dataset is touched.
Multiple files (combine)
Select or drop several files at once to stack them into a single table
(e.g. monthly CSV exports or a partitioned Parquet set). Supported for
CSV/TSV, Parquet, JSON and NDJSON; all files must be the
same type and have the same structure (identical columns & types).
If a file's structure differs, the import stops with an error naming the file and the
mismatch. Detection (delimiter, header, …) runs on the first file and applies to all; the
combined data is read via DuckDB and behaves like one source for preview, filter and export.
Other formats (Excel/ODS/Numbers, SQLite, DuckDB, Markdown, HTML) are imported one at a time.
SQL editor
The SQL card lets you run read queries against the current source, which is
exposed as a view named data — e.g.
SELECT region, sum(revenue) FROM data GROUP BY region ORDER BY 2 DESC.
Run with the button or Ctrl/⌘+Enter. It honours the parsing
heuristic (delimiter, header, selected sheet/table, multi-file combine), and works for every
source — CSV, Parquet, JSON/NDJSON, Excel/ODS/Numbers, SQLite, DuckDB, Markdown and pasted data
(non-DuckDB sources are materialized once for querying). Queries are wrapped as a sub-select, so
only reads are possible.
Results are paginated at 100 rows per page (Prev / Next): each page is fetched
with LIMIT/OFFSET, so only 100 rows ever enter the browser — large result sets won't
exhaust memory. Export result → Parquet writes the full query result
(all rows, not just the current page) straight to a Parquet file via DuckDB COPY
(zstd-compressed), without materializing every row in the page.
For large files in a row-oriented format (CSV, JSON, Excel — or several combined
files), a hint appears: each query re-scans the whole file. For complex or repeated analysis,
export to Parquet first and run your queries on the Parquet file — it is columnar
and pruned, so analysis is dramatically faster and lighter on memory.
Supported formats
- CSV / TSV — auto-detects encoding, BOM, line ending,
delimiter, quote, skiprows, header.
- Parquet — schema is read from metadata directly; no
heuristic needed.
- JSON (array) — full file is parsed (a JSON array is a
single value). For files > 100 MB the app suggests NDJSON instead.
- NDJSON / JSON Lines — schema inferred from the first ~100
lines.
- Excel (.xlsx / .xls), OpenDocument (.ods / .fods) and Apple Numbers
(.numbers) — all read via SheetJS through the same path: sheet selection,
data-block detection (bounding box), header row, plus a visual range picker. Formulas
are read as their cached values. ODS is also available as an export
target.
- HTML (.html / .htm) — all
<table> elements are
extracted (pick one via the Table dropdown). Also available as an export target
(a standalone HTML document with one table).
- DuckDB (.duckdb / .ddb / .db) — attached read-only;
pick which table to read from. Schema and types come straight from
the file. Can also be produced as an export target.
- SQLite (.sqlite / .sqlite3 / .db) — read via sql.js,
which loads the whole database into memory (practical up to ~1 GB);
pick which table to read from, then convert it to any supported export
format. Larger databases can't be opened in-browser (DuckDB-WASM's sqlite
scanner can't open a lazily-registered file) — convert the table you need
to Parquet with the DuckDB CLI first, e.g.
duckdb -c "INSTALL sqlite; LOAD sqlite; COPY (SELECT * FROM sqlite_scan('db.sqlite','mytable')) TO 'mytable.parquet' (FORMAT parquet);",
then import the Parquet here. (.db is auto-detected as SQLite
or DuckDB from the file's magic bytes.)
- Paste from clipboard — the Paste table from clipboard button
imports a table copied from Excel/Sheets, a browser table, or CSV/TSV text. Rich HTML
tables are read directly; for plain text the delimiter (tab /
; /
| / , / whitespace / Markdown) is auto-detected
and can be overridden, and the first row is treated as the header (toggleable). Multiple
tables → pick one via the Table dropdown.
- Source editor / new table — pasted text appears in an editable
Source editor with live preview; New / blank table opens an empty editor
to author a table from scratch (e.g. a Markdown pipe table). An HTML-pasted table can be
turned editable via Edit as text.
- Markdown (.md / .markdown) — GitHub-flavored pipe tables.
All tables in the file are detected; pick which one to read via the
Table dropdown (labelled by the nearest preceding heading). Column
types are inferred (Markdown carries none). Also available as an export
target — emits a GFM pipe table (cells with
| or newlines are
escaped; capped at 50,000 rows).
Notes & limitations (v1)
- Excel sheets with multiple disjoint data blocks: only the first/largest is
detected. Use the range picker to select another block manually.
- Nested structures (Struct/List/Map) are shown as JSON strings in the preview;
Parquet export preserves native types.
- If your browser blocks cross-origin
SharedArrayBuffer (typical
for file://), DuckDB falls back to the single-threaded MVP build —
slightly slower but otherwise functional.
- External libs (DuckDB-WASM, SheetJS) are loaded from public CDNs. Internet
access is therefore needed on first load; browsers cache aggressively
afterwards.
- Everything runs in a 32-bit WebAssembly heap (~2–4 GB ceiling).
Formats that must be read in full — JSON arrays on export, Excel/ODS/Numbers,
and SQLite via the sql.js fallback — can hit that ceiling on very large
files. Converting to Parquet and continuing from there is
the most memory-efficient path.
Table Format Converter
Ein reines Browser-Werkzeug, um strukturierte Tabellendaten zu lesen (CSV, Parquet, JSON,
NDJSON, Excel, ODS, Apple Numbers, DuckDB, SQLite, Markdown, HTML), ihre Struktur zu
prüfen, die Parsing-Heuristik anzupassen und in ein anderes Format zu exportieren.
Deine Daten verlassen den Browser nicht — alles wird lokal mit
DuckDB-WASM und SheetJS verarbeitet.
Ablauf
- Eine Datei in den Ablagebereich ziehen oder klicken, um eine auszuwählen. Du kannst auch
mehrere Dateien gleichzeitig wählen — siehe Mehrere Dateien unten.
- Die App erkennt Format und Parsing-Parameter anhand einer kleinen Stichprobe
und zeigt eine Vorschau der ersten 10 Zeilen samt Schema.
- Jeden Parameter links anpassen — die Vorschau läuft live neu
(entprellt, ca. 300 ms).
- Zielformat und Optionen wählen, dann auf Exportieren klicken. Erst zu
diesem Zeitpunkt wird die vollständige Datei gelesen.
Stichprobe zuerst — Performance
Das Ablegen erfolgt unabhängig von der Dateigröße sofort, und die erste Vorschau erscheint
innerhalb von ca. 100 ms — auch bei Dateien von mehreren Gigabyte:
- Dateien > 512 KB — als lazy
FileReader-Handle registriert (es werden keine Bytes geladen). Ein kleines
512 KB großes Kopfstück wird vorab in den WASM-Speicher geladen und
für alle Vorschau- und Erkennungsabfragen genutzt — der Rest der Datei wird dabei nie
angefasst.
- Dateien ≤ 512 KB — einmal vollständig in den Speicher geladen
und für Vorschau wie Export wiederverwendet.
- Parquet — DuckDB beschränkt den Zugriff auf die benötigten Spalten und
Row-Groups, sodass selbst vollständige Lesevorgänge nur holen, was die Abfrage braucht.
- JSON (Array) — ein JSON-Array ist ein einziger Wert, ein vollständiges
Lesen würde also die ganze Datei laden. Die Vorschau parst stattdessen nur ein
Kopfstück und entnimmt die ersten vollständigen Elemente; das komplette Array wird erst
beim Export gelesen.
- SQLite — wird mit sql.js gelesen, das die gesamte Datenbank in den
Speicher lädt (praktikabel bis ca. 1 GB). Der SQLite-Scanner von DuckDB-WASM kann
keine lazy registrierte Browser-Datei öffnen, daher lassen sich größere Datenbanken nicht
im Browser öffnen — wandle die benötigte Tabelle vorher nach Parquet um (siehe unten).
- Excel / ODS / Numbers — müssen vollständig geladen werden (SheetJS
arbeitet nicht streamend), werden aber in einem kompakten (
dense) Modell
geparst; die Heuristik betrachtet nur die ersten 100 Zeilen je Blatt.
- Markdown — Tabellenerkennung und Vorschau parsen nur ein 1 MB
großes Kopfstück; beim Export wird die vollständige Datei erneut geparst.
- Export — liest immer die vollständige Datei; dies ist die
einzige Phase, in der der gesamte Datenbestand angefasst wird.
Mehrere Dateien (zusammenführen)
Wähle oder ziehe mehrere Dateien gleichzeitig, um sie zu einer Tabelle zu
stapeln (etwa monatliche CSV-Exporte oder einen partitionierten Parquet-Satz). Unterstützt für
CSV/TSV, Parquet, JSON und NDJSON; alle Dateien müssen
vom selben Typ sein und dieselbe Struktur haben (identische Spalten und Typen).
Weicht die Struktur einer Datei ab, bricht der Import mit einer Fehlermeldung ab, die Datei und
Abweichung benennt. Die Erkennung (Trennzeichen, Kopfzeile, …) läuft auf der ersten Datei und
gilt für alle; die zusammengeführten Daten werden über DuckDB gelesen und verhalten sich für
Vorschau, Filter und Export wie eine einzige Quelle. Andere Formate (Excel/ODS/Numbers, SQLite,
DuckDB, Markdown, HTML) werden einzeln importiert.
SQL-Editor
Über die Karte SQL kannst du lesende Abfragen auf die aktuelle Quelle
ausführen, die als View namens data bereitsteht — etwa
SELECT region, sum(umsatz) FROM data GROUP BY region ORDER BY 2 DESC.
Ausführen per Schaltfläche oder Strg/⌘+Enter. Die Abfrage
berücksichtigt die Parsing-Heuristik (Trennzeichen, Kopfzeile, gewähltes Blatt bzw. gewählte
Tabelle, Zusammenführung mehrerer Dateien) und funktioniert für jede Quelle — CSV, Parquet,
JSON/NDJSON, Excel/ODS/Numbers, SQLite, DuckDB, Markdown und eingefügte Daten (Quellen außer
DuckDB werden dafür einmal materialisiert). Abfragen werden als Unterabfrage gekapselt, es
sind also nur Lesezugriffe möglich.
Ergebnisse werden zu 100 Zeilen je Seite geblättert (Zurück / Weiter): jede
Seite wird mit LIMIT/OFFSET geholt, sodass immer nur 100 Zeilen im Browser
landen — große Ergebnismengen sprengen den Speicher also nicht.
Ergebnis → Parquet schreibt das vollständige Abfrageergebnis
(alle Zeilen, nicht nur die aktuelle Seite) über DuckDB COPY direkt in eine
Parquet-Datei (zstd-komprimiert), ohne jede Zeile im Browser aufzubauen.
Bei großen Dateien in einem zeilenorientierten Format (CSV, JSON, Excel — oder
mehreren zusammengeführten Dateien) erscheint ein Hinweis: jede Abfrage liest die gesamte Datei
erneut. Für komplexe oder wiederholte Auswertungen daher
zuerst nach Parquet exportieren und die Abfragen auf der Parquet-Datei
ausführen — sie ist spaltenorientiert und wird gezielt gelesen, wodurch Auswertungen drastisch
schneller und speicherschonender werden.
Unterstützte Formate
- CSV / TSV — erkennt Zeichensatz, BOM, Zeilenende,
Trennzeichen, Anführungszeichen, zu überspringende Zeilen und Kopfzeile automatisch.
- Parquet — das Schema wird direkt aus den Metadaten gelesen, eine
Heuristik ist nicht nötig.
- JSON (Array) — die vollständige Datei wird geparst (ein JSON-Array ist
ein einziger Wert). Bei Dateien > 100 MB schlägt die App stattdessen NDJSON vor.
- NDJSON / JSON Lines — das Schema wird aus den ersten ca. 100 Zeilen
abgeleitet.
- Excel (.xlsx / .xls), OpenDocument (.ods / .fods) und Apple Numbers
(.numbers) — werden alle über SheetJS auf demselben Weg gelesen: Blattauswahl,
Erkennung des Datenbereichs (umschließendes Rechteck), Kopfzeile sowie ein visueller
Bereichswähler. Formeln werden als ihre zwischengespeicherten Werte gelesen.
ODS steht auch als Exportziel zur Verfügung.
- HTML (.html / .htm) — alle
<table>-Elemente werden
extrahiert (Auswahl über das Feld Tabelle). Ebenfalls als Exportziel verfügbar
(ein eigenständiges HTML-Dokument mit einer Tabelle).
- DuckDB (.duckdb / .ddb / .db) — wird schreibgeschützt eingebunden;
wähle die zu lesende Tabelle. Schema und Typen stammen direkt aus der Datei. Auch als
Exportziel verfügbar.
- SQLite (.sqlite / .sqlite3 / .db) — wird über sql.js gelesen, das die
gesamte Datenbank in den Speicher lädt (praktikabel bis ca. 1 GB); wähle die zu
lesende Tabelle und wandle sie in ein beliebiges unterstütztes Exportformat um. Größere
Datenbanken lassen sich nicht im Browser öffnen (der SQLite-Scanner von DuckDB-WASM kann
keine lazy registrierte Datei öffnen) — wandle die benötigte Tabelle zuvor mit der
DuckDB-CLI nach Parquet um, etwa
duckdb -c "INSTALL sqlite; LOAD sqlite; COPY (SELECT * FROM sqlite_scan('db.sqlite','meine_tabelle')) TO 'meine_tabelle.parquet' (FORMAT parquet);",
und importiere das Parquet hier. (.db wird anhand der Magic Bytes automatisch
als SQLite oder DuckDB erkannt.)
- Aus der Zwischenablage einfügen — die Schaltfläche
Tabelle aus Zwischenablage importiert eine aus Excel/Sheets, einer Browser-Tabelle
oder als CSV/TSV-Text kopierte Tabelle. Formatierte HTML-Tabellen werden direkt gelesen;
bei reinem Text wird das Trennzeichen (Tab /
; / | /
, / Leerzeichen / Markdown) automatisch erkannt und lässt
sich überschreiben, die erste Zeile gilt als Kopfzeile (umschaltbar). Bei mehreren
Tabellen → Auswahl über das Feld Tabelle.
- Quell-Editor / neue Tabelle — eingefügter Text erscheint in einem
bearbeitbaren Quell-Editor mit Live-Vorschau; Neue / leere Tabelle öffnet
einen leeren Editor, um eine Tabelle von Grund auf anzulegen (etwa als Markdown-Tabelle).
Eine als HTML eingefügte Tabelle lässt sich über Als Text bearbeiten in den
Editor übernehmen.
- Markdown (.md / .markdown) — Pipe-Tabellen im GitHub-Stil.
Alle Tabellen der Datei werden erkannt; die zu lesende wählst du über das Feld
Tabelle (benannt nach der nächstgelegenen vorangehenden Überschrift). Spaltentypen
werden abgeleitet (Markdown enthält keine). Ebenfalls als Exportziel verfügbar — erzeugt
eine GFM-Pipe-Tabelle (Zellen mit
| oder Zeilenumbrüchen werden maskiert;
begrenzt auf 50.000 Zeilen).
Hinweise & Grenzen (v1)
- Excel-Blätter mit mehreren getrennten Datenbereichen: nur der erste bzw. größte wird
erkannt. Über den Bereichswähler lässt sich ein anderer Block manuell wählen.
- Verschachtelte Strukturen (Struct/List/Map) erscheinen in der Vorschau als
JSON-Zeichenketten; der Parquet-Export erhält die nativen Typen.
- Blockiert dein Browser
SharedArrayBuffer über Origin-Grenzen hinweg
(typisch bei file://), weicht DuckDB auf den einkernigen MVP-Build aus —
etwas langsamer, aber ansonsten voll funktionsfähig.
- Externe Bibliotheken (DuckDB-WASM, SheetJS) werden von öffentlichen CDNs geladen. Beim
ersten Laden ist daher ein Internetzugang nötig; Browser cachen anschließend aggressiv.
- Alles läuft in einem 32-Bit-WebAssembly-Speicher (Obergrenze ca. 2–4 GB).
Formate, die vollständig gelesen werden müssen — JSON-Arrays beim Export, Excel/ODS/Numbers
sowie SQLite über den sql.js-Weg — können diese Grenze bei sehr großen Dateien erreichen.
Der speichersparendste Weg ist, nach Parquet zu wandeln und von dort
weiterzuarbeiten.