scapeTableau
scapeTableau is a zero-dependency, pure-Python engine for migrating legacy Tableau workbooks (.twb and .twbx) into warehouse SQL for Snowflake, BigQuery, Postgres, DuckDB, and dbt.
python cli.py process or streamlit run app_local.py.Tableau workbooks are XML (or a zip of XML plus extracts). Calculated fields hide inside proprietary syntax — IIF, ZN, IFNULL, LODs — that warehouses do not run. Rebuilding those formulas by hand is slow, and packaged tables plus hidden columns stay buried unless you unzip the file yourself.
Offloading the workbook to a generic LLM is a privacy non-starter for most corporate audits. You need a deterministic parser you can run locally, plus a hosted try-it path that does not keep the file.
| Capability | What actually ships |
|---|---|
| In-memory workbook parse | Reads .twb / .twbx in process memory with stdlib xml.etree + zipfile. Hosted uploads are not written to disk and are not sent to an LLM. |
| Formula transpilation | IIF / ZN / IFNULL / CONTAINS / STARTSWITH (plus IF/CASE, LEN, TRIM, UPPER/LOWER, ABS, ROUND) become CASE / COALESCE / LIKE and ANSI SQL. LOD FIXED / INCLUDE / EXCLUDE stay isolated as -- TODO: Review LOD logic comments — they are not rewritten as SQL. |
| dbt-ready SQL views | Emits CREATE VIEW SQL with comments you can drop into a dbt model file. schema.yml is not auto-written; this is not a full dbt package scaffold. |
| Extract Data | Packaged CSV / TSV / XLS / XLSX become a downloadable .xlsx. Custom SQL is copied to extra sheets, not executed. Hyper extracts are listed only. |
| Inspect Schema | Datasources, all columns (including hidden), parameters, redacted connections, and printable dashboard wireframes. |
| Air-gapped local run | CLI and Streamlit stay on-device. This hosted app is in-memory and non-persistent — it is not air-gapped. |
Python is the source of truth. The Next.js routes stream the upload to the engine and return JSON or xlsx. Nothing is stored after the response.
[ .twb / .twbx bytes ]
│
▼
┌──────────────────────┐
│ engine/parser.py │ (xml.etree + zipfile)
└───────────┬──────────┘
│
▼
┌──────────────────────┐
│ engine/schema.py │ (Pydantic v2 Models)
└───────────┬──────────┘
│
▼
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
engine/transpiler.py engine/extract.py engine/inspect.py
│ │ │
└──────────┬───────────┴──────────┬───────────┘
▼ ▼
TranspileResult xlsx bytes
(calculated_fields, sql_script,
inspect, extract_inventory, dashboards)
│
┌────────┼────────┐
▼ ▼ ▼
[ cli.py ] [ app_local.py ] [ /api/transpile + /api/extract ]Drop a .twb or .twbx. One pass transpiles SQL, extracts packaged tables, and inspects schema.