Skip to content

Audit the data sources inside a .twbx.

Read the workbook’s connection metadata, tables, joins and Custom SQL locally. This audit lists definitions; it never connects to the named server.

Updated

Read locally in this browser.

↳sales-ops-audit-sample.twbxSynthetic sample

Which connections and SQL does this workbook contain?

This synthetic workbook declares three sources, one join and one Custom SQL query. The internal-looking host name is fictional; no database is contacted.

“List sources, joins and Custom SQL before migration.”

Worked example · authored synthetic data

  1. Read .twb metadataKeep the original archive in the browser
  2. List connection definitionsDo not contact the declared server
  3. Inspect joins and Custom SQLReview the actual saved SQL text
  4. Save packaged filesDownload locally when needed

Calculation or query in this example

SELECT o.order_id, o.amount FROM prod_raw.orders o

Exact sample file · Definitions and expected values

xmetricWorkbook connection audit

Opening the labelled sample…

The browser is reading the sample’s workbook definitions.

Use your own file

Drop one file anywhere on this page. It is read in your browser; no file is uploaded.

Nothing is uploaded.

Read locallyThe original file stays in the browser.

Share deliberatelyMCP shares supported metadata and requested results with the chat host.

Separate actionsOnline saves and support uploads require their own actions.

How does this workflow work?

What is the direct answer to this workbook question?

A .twb is XML, and a .twbx is a zip with that XML plus packaged data. Each data source's connection (server, database, user), its tables and joins, any Custom SQL and any extract are written in the <datasources> section. Drop a workbook below to list them in your browser, or run the Python script on this page over a folder of workbooks. No database credentials or Tableau install needed.

When should I audit workbook data sources?

Before a warehouse migration or a dbt refactor, someone has to find which workbooks still read a deprecated table or carry their own Custom SQL. Opening forty workbooks one by one in Tableau Desktop is slow, and the people doing the audit often don't have a Tableau seat. Tableau Desktop does have a free edition for one person: Tableau Desktop Free Edition: full Desktop analytics for one person, stored locally; no publishing, online sharing or sharing packaged workbooks. A Creator seat costs $75 per user/month, billed annually (checked 2026-10-18). For an audit you need neither: everything is in the file.

Which XML nodes describe connections and queries?

Read connection attributes for server and database names, relation nodes for tables and joins, and text relations for Custom SQL.

WhatWhere in the .twbWhy it matters
Connection<named-connection><connection class=… server=… dbname=…>Which database, server and user each source depends on
Tables and joins<relation type='table' table=…>, <relation type='join'>The exact upstream tables, and joins that can fan out rows
Custom SQL<relation type='text'>Queries pasted into the workbook, invisible to lineage tools
Extract<extract>, and .hyper files inside a .twbxA copy of company data that travels with the file

How can I run the same audit from a script?

Run it on one workbook or a whole folder (python3 audit.py *.twbx), or hand it to a coding agent such as Claude Code or Codex and ask for a lineage table. It uses only the Python standard library. On the sample workbook above it prints the same server, tables, join, Custom SQL, extract and packaged file the page shows.

import sys, zipfile
import xml.etree.ElementTree as ET

def audit(path):
    if path.lower().endswith(".twbx"):
        with zipfile.ZipFile(path) as zf:
            names = zf.namelist()
            twb = next(n for n in names if n.lower().endswith(".twb"))
            root = ET.fromstring(zf.read(twb))
            print("Packaged files:", [n for n in names if n != twb and not n.endswith("/")])
    else:
        root = ET.parse(path).getroot()
    for ds in root.iter("datasource"):
        if ds.get("name") == "Parameters" or ds.find("connection") is None:
            continue
        print(f"\n=== {ds.get('caption') or ds.get('name')} ===")
        for c in ds.iter("connection"):
            if c.get("class") not in (None, "federated", "hyper"):
                print("Connection:", {k: c.get(k) for k in ("class", "server", "dbname", "username", "filename") if c.get(k)})
        for rel in ds.iter("relation"):
            if rel.get("type") == "table":
                print("Table:", rel.get("table"))
            elif rel.get("type") == "join":
                print("Join:", rel.get("join"))
            elif rel.get("type") == "text":
                print("Custom SQL:\n" + (rel.text or "").strip())
        for ex in ds.iter("extract"):
            for c in ex.iter("connection"):
                print("Extract:", c.get("dbname"))

for workbook in sys.argv[1:]:
    print(f"##### {workbook}")
    audit(workbook)

How can I move Custom SQL out of a workbook?

Tableau runs Custom SQL as a subquery, wrapping your statement in its own SELECT, and the logic is invisible to warehouse lineage tools. Once the audit has found it, move the query into a versioned view or dbt model (for example analytics.valid_orders) and point the workbook at that table. The workbook keeps working, and the next migration can see the dependency.

What can a packaged workbook expose?

Tableau's documentation describes a packaged workbook as the workbook plus copies of local file data sources and extracts. Anyone who has the file can read the connection details, filter values and the packaged data, even without access to the database. Check what is inside before you email one.

Does this work on a Mac or Linux?

Yes. The audit above runs in the browser on any system, and the script needs only Python 3.

Are passwords stored in the workbook?

Connections usually keep the server, database and user name. Whether a password is embedded depends on how the workbook was saved and published; treat any workbook from a shared drive as sensitive.

What about workbooks that blend two data sources?

Each data source still appears in datasources, so the audit lists both. The fields that link them are recorded with each worksheet's data source dependencies.

Is my workbook uploaded?

No. The file is read in this browser tab.

Have a workbook? Audit it above, or open the full workbook inspector. Every formula it finds has its SQL in the function reference; test one in the playground.

What data does this worked example use?

The initial view uses authored synthetic data, not customer data or a captured agent session.

The example record lists its file, calculation or SQL and expected values. The live browser result is computed by xmetric’s existing engine or workbook inspector. Samples are excluded from own-data activation reporting.