| Title: | Parse 'Tableau' Workbooks into Functional Data |
|---|---|
| Description: | High-performance parsing of 'Tableau' workbook files into tidy data frames and dependency graphs for other visualization tools like R 'Shiny' or 'Power BI' replication, plus an interactive 'Shiny' workbook inspector for uploaded .twb and .twbx files. |
| Authors: | George Arthur [aut, cre] (ORCID: <https://orcid.org/0000-0002-1975-1459>) |
| Maintainer: | George Arthur <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.5.1 |
| Built: | 2026-09-28 22:16:21 UTC |
| Source: | https://github.com/prigasg/twbparser |
Batch parses .twb and .twbx files and returns migration-oriented
inventory tables. The summary table is one row per workbook; detail tables
retain workbook identity so they can be filtered or joined downstream.
audit_tableau_folder( path, recursive = TRUE, pattern = NULL, write_csv = FALSE, output_dir = NULL )audit_tableau_folder( path, recursive = TRUE, pattern = NULL, write_csv = FALSE, output_dir = NULL )
path |
Folder containing Tableau workbooks, or a character vector of
|
recursive |
Logical; search folders recursively. Default |
pattern |
Optional regular expression applied to file basenames. |
write_csv |
Logical; write each returned table as a CSV file.
Default |
output_dir |
Directory for CSV output when |
A named list with class twbparser_audit containing:
One row per parsed workbook with counts and migration complexity flags.
Datasource inventory across parsed workbooks.
Calculated field complexity across workbooks.
Worksheet field usage across workbooks.
Combined lineage edge table across workbooks.
Files that could not be parsed and their error messages.
demo <- system.file("extdata", package = "twbparser") if (nzchar(demo)) { audit <- audit_tableau_folder(demo) audit$workbooks }demo <- system.file("extdata", package = "twbparser") if (nzchar(demo)) { audit <- audit_tableau_folder(demo) audit$workbooks }
Creates a directed graph where edges point from input fields used in a
formula to the calculated output field. Tokens are extracted from bracketed
references like [Table].[Field] or [Field].
build_dependency_graph(fields_df)build_dependency_graph(fields_df)
fields_df |
A data frame with at least columns |
An igraph directed graph where vertices are field names and edges
represent dependencies (input → output).
fields <- tibble::tibble( name = c("X_plus_Y", "Z"), formula = c("[X] + [Y]", "[X_plus_Y] * 2") ) g <- build_dependency_graph(fields)fields <- tibble::tibble( name = c("X_plus_Y", "Z"), formula = c("[X] + [Y]", "[X_plus_Y] * 2") ) g <- build_dependency_graph(fields)
Writes a folder of migration artifacts such as inventory CSVs, lineage, compatibility results, formula translation candidates, and a Markdown brief.
export_migration_bundle( x, target = c("powerbi", "shiny", "quarto", "looker", "superset"), path = "twbparser-migration-bundle", include_scaffold = TRUE )export_migration_bundle( x, target = c("powerbi", "shiny", "quarto", "looker", "superset"), path = "twbparser-migration-bundle", include_scaffold = TRUE )
x |
A |
target |
Target tool. One of |
path |
Output directory. |
include_scaffold |
Logical; include a Shiny or Quarto scaffold when
|
Invisibly returns a tibble of written files.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) out <- file.path(tempdir(), "twbparser-bundle") export_migration_bundle(parser, target = "shiny", path = out) }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) out <- file.path(tempdir(), "twbparser-bundle") export_migration_bundle(parser, target = "shiny", path = out) }
Finds columns that contain <calculation>nodes and returns metadata and
formulas, with a heuristic flag for table calculations.
extract_calculated_fields(xml_doc, include_parameters = FALSE)extract_calculated_fields(xml_doc, include_parameters = FALSE)
xml_doc |
An xml2 document for a Tableau .twb. |
include_parameters |
Logical. If TRUE, include items from the "Parameters" datasource or columns with @param-domain-type. Default FALSE. |
A tibble with columns:
Datasource name.
User-visible caption or cleaned internal name.
Internal Tableau name (often bracketed).
Tableau datatype.
Tableau role.
Calculation formula string.
Tableau calc class (often "tableau").
Heuristic flag for table calcs (e.g., WINDOW_, LOOKUP).
Raw table reference.
Cleaned table name.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) calcs <- extract_calculated_fields(xml) head(calcs)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) calcs <- extract_calculated_fields(xml) head(calcs)
Scans top-level <datasource> nodes (excluding view-specific references) and
returns fields with raw names/captions, cleaned table/field names, and basic
metadata.
extract_columns_with_table_source(xml_doc)extract_columns_with_table_source(xml_doc)
xml_doc |
An |
A tibble with columns:
Datasource name.
Raw column name (may include brackets/qualifiers).
Column caption if present.
Tableau datatype.
Tableau role.
Semantic role if present.
Raw table reference.
Cleaned table name (no brackets/suffix).
Cleaned field name.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml)
Gathers runtime tables (from the object graph), merges in named-connection
metadata (class, caption, targets), and augments with top-level datasource
definitions (field counts, connection type, location). Also returns the
workbook's parameter fields via extract_parameters().
extract_datasource_details(xml_doc)extract_datasource_details(xml_doc)
xml_doc |
An |
A named list with:
Tibble of datasources joined with connection metadata.
Tibble of parameter fields from extract_parameters().
Same as data_sources (placeholder for future variants).
# Preferred: from a tiny .twb twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { xml <- xml2::read_xml(twb) res <- extract_datasource_details(xml) head(res$data_sources) } # Alternative: from a tiny .twbx (guarded) twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") if (nzchar(twbx) && file.exists(twbx)) { members <- twbx_list(twbx) twb_rows <- members$name[grepl("\\.twb$", members$name)] if (length(twb_rows) > 0L && !is.na(twb_rows[1])) { twb_member <- twb_rows[1] xml <- xml2::read_xml(utils::unzip(twbx, twb_member, exdir = tempdir())) res <- extract_datasource_details(xml) head(res$data_sources) } }# Preferred: from a tiny .twb twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { xml <- xml2::read_xml(twb) res <- extract_datasource_details(xml) head(res$data_sources) } # Alternative: from a tiny .twbx (guarded) twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") if (nzchar(twbx) && file.exists(twbx)) { members <- twbx_list(twbx) twb_rows <- members$name[grepl("\\.twb$", members$name)] if (length(twb_rows) > 0L && !is.na(twb_rows[1])) { twb_member <- twb_rows[1] xml <- xml2::read_xml(utils::unzip(twbx, twb_member, exdir = tempdir())) res <- extract_datasource_details(xml) head(res$data_sources) } }
<relation type="join"> nodesHandles both column-based clauses (<clause><column/></clause>) and
expression-based predicates (<expression op=...>) found in TWB XML.
extract_joins(xml_doc)extract_joins(xml_doc)
xml_doc |
An |
A tibble with columns:
Join kind (e.g., inner, left), if available.
Left table name (cleaned).
Left field name.
Predicate operator (defaults to "=" when missing).
Right table name (cleaned).
Right field name.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) extract_joins(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) extract_joins(xml)
<named-connection> entries from a TWBRich, safe extraction of <named-connection> nodes and their <connection>
attributes into a tidy tibble.
extract_named_connections(xml_doc)extract_named_connections(xml_doc)
xml_doc |
An |
Tibble with columns like connection_id, connection_caption,
connection_class, connection_target, dbname, schema, warehouse,
region, filename, and location_named.
# Preferred: read from a tiny '.twb' twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { xml <- xml2::read_xml(twb) extract_named_connections(xml) } twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") if (nzchar(twbx) && file.exists(twbx)) { members <- twbx_list(twbx) twb_rows <- members$name[grepl("\\.twb$", members$name)] if (length(twb_rows) > 0L && !is.na(twb_rows[1])) { twb_member <- twb_rows[1] xml <- xml2::read_xml(utils::unzip(twbx, twb_member, exdir = tempdir())) extract_named_connections(xml) } }# Preferred: read from a tiny '.twb' twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { xml <- xml2::read_xml(twb) extract_named_connections(xml) } twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") if (nzchar(twbx) && file.exists(twbx)) { members <- twbx_list(twbx) twb_rows <- members$name[grepl("\\.twb$", members$name)] if (length(twb_rows) > 0L && !is.na(twb_rows[1])) { twb_member <- twb_rows[1] xml <- xml2::read_xml(utils::unzip(twbx, twb_member, exdir = tempdir())) extract_named_connections(xml) } }
Returns parameter columns (those with param-domain-type) and basic metadata,
including a best-effort current value if present.
extract_parameters(xml_doc)extract_parameters(xml_doc)
xml_doc |
An |
A tibble with columns:
Datasource name.
User-visible caption or cleaned internal name.
Internal Tableau name.
Tableau datatype.
Tableau role.
Tableau parameter domain type.
Underlying data-type (if present).
Current value if specified.
Always TRUE.
Raw table reference.
Cleaned table name.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) params <- extract_parameters(xml) head(params)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) params <- extract_parameters(xml) head(params)
Returns raw columns excluding calculated fields and parameters.
extract_raw_fields(xml_doc)extract_raw_fields(xml_doc)
xml_doc |
An |
A tibble with columns:
Datasource name.
User-visible caption or cleaned internal name.
Internal Tableau name.
Tableau datatype.
Tableau role.
Whether the field is hidden.
Always FALSE.
Raw table reference.
Cleaned table name.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) raw_fields <- extract_raw_fields(xml) head(raw_fields)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) raw_fields <- extract_raw_fields(xml) head(raw_fields)
<relation> tags from a TWBReturns a tibble of <relation> elements found in a Tableau TWB XML,
with key attributes and any custom SQL text.
extract_relations(xml_doc)extract_relations(xml_doc)
xml_doc |
An |
A tibble with columns:
name |
Relation name |
table |
Table reference |
connection |
Connection ID |
type |
Relation type (table, join, etc.) |
join |
Join type if applicable |
custom_sql |
Inline SQL text if present |
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml) inferred <- infer_implicit_relationships(fields) head(inferred)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml) inferred <- infer_implicit_relationships(fields) head(inferred)
Parses Tableau "relationships" (introduced in 2020.2) between logical tables, including the join predicate fields and operator.
extract_relationships(xml_doc)extract_relationships(xml_doc)
xml_doc |
An |
A tibble with columns:
relationship_type |
Always "Relationship" |
left_table |
Left table name |
right_table |
Right table name |
left_field |
Field name on left side |
operator |
Join operator (e.g., "=") |
right_field |
Field name on right side |
left_is_calc |
Logical, whether left field is a calculation |
right_is_calc |
Logical, whether right field is a calculation |
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) extract_relationships(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) extract_relationships(xml)
Extract the .twb (and optionally all files) from a .twbx
extract_twb_from_twbx( twbx_path, extract_dir = file.path(tempdir(), paste0("twbx_", tools::file_path_sans_ext(basename(twbx_path)), "_", format(Sys.time(), "%Y%m%d%H%M%S"))), extract_all = FALSE )extract_twb_from_twbx( twbx_path, extract_dir = file.path(tempdir(), paste0("twbx_", tools::file_path_sans_ext(basename(twbx_path)), "_", format(Sys.time(), "%Y%m%d%H%M%S"))), extract_all = FALSE )
twbx_path |
Path to a |
extract_dir |
Directory to extract into (defaults to a timestamped temp dir). |
extract_all |
If |
List with twb_path, exdir, twbx_path, and manifest (tibble).
twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") res <- extract_twb_from_twbx(twbx, extract_all = FALSE) basename(res$twb_path)twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") res <- extract_twb_from_twbx(twbx, extract_all = FALSE) basename(res$twb_path)
Generates candidate join pairs by:
Matching semantic_role across different tables.
Matching field names (case-insensitive) across different tables.
infer_implicit_relationships(fields_df, max_pairs = 50000L)infer_implicit_relationships(fields_df, max_pairs = 50000L)
fields_df |
A data frame like the output of
|
max_pairs |
Maximum number of candidate pairs to return (default 50,000). |
A tibble with columns:
Left table name.
Left field name.
Right table name.
Right field name.
Why the pair was suggested.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml) inferred <- infer_implicit_relationships(fields) head(inferred)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) fields <- extract_columns_with_table_source(xml) inferred <- infer_implicit_relationships(fields) head(inferred)
parse_twb() is a convenience wrapper for non-interactive use: it parses a
.twb/.twbx workbook with TwbParser and writes a structured set of
outputs into output_dir — a human-readable report, one CSV per key table
(including the rebuild kit: unused fields, calculation build order, and
parameter usage), per-worksheet visualization specs, a plain-text
replication brief, and the field dependency graph as GraphML (readable with
igraph/ggraph or any GraphML tool).
parse_twb(path, output_dir = "results", overwrite = FALSE, quiet = FALSE)parse_twb(path, output_dir = "results", overwrite = FALSE, quiet = FALSE)
path |
Path to a |
output_dir |
Directory to write outputs into. Created if needed (including parents). |
overwrite |
If |
quiet |
If |
The normalized output_dir, invisibly.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { out <- parse_twb(twb, output_dir = file.path(tempdir(), "twbparser-demo"), quiet = TRUE) list.files(out) }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { out <- parse_twb(twb, output_dir = file.path(tempdir(), "twbparser-demo"), quiet = TRUE) list.files(out) }
Draws a quick base-graphics plot of a dependency graph. Vertices that are
calculated fields (present in fields_df$name) are drawn differently.
plot_dependency_graph(g, fields_df = NULL, seed = NULL)plot_dependency_graph(g, fields_df = NULL, seed = NULL)
g |
An |
fields_df |
Optional data frame with a |
seed |
Optional integer seed to make the layout reproducible. If |
Invisibly returns g.
fields <- tibble::tibble( name = c("X_plus_Y", "Z"), formula = c("[X] + [Y]", "[X_plus_Y] * 2") ) g <- build_dependency_graph(fields) plot_dependency_graph(g, fields) # nondeterministic layout plot_dependency_graph(g, fields, seed = 1) # deterministic layoutfields <- tibble::tibble( name = c("X_plus_Y", "Z"), formula = c("[X] + [Y]", "[X_plus_Y] * 2") ) g <- build_dependency_graph(fields) plot_dependency_graph(g, fields) # nondeterministic layout plot_dependency_graph(g, fields, seed = 1) # deterministic layout
Uses relationships_df with columns left_table, right_table,
left_field, right_field, and optional operator.
plot_relationship_graph(relationships_df, seed = NULL)plot_relationship_graph(relationships_df, seed = NULL)
relationships_df |
Data frame of field-level relationships. |
seed |
Optional integer seed to make the layout reproducible. If |
Invisibly returns the plotted graph.
Visualizes joins between sources. Expects joins_df with columns
left_table, right_table, left_field, right_field. If
relationships_df is provided (modern relationships), it will render a
second graph highlighting those relationships.
plot_source_join_graph(joins_df, relationships_df = NULL, seed = NULL)plot_source_join_graph(joins_df, relationships_df = NULL, seed = NULL)
joins_df |
Data frame with join edges. |
relationships_df |
Optional data frame with modern relationships. |
seed |
Optional integer seed to make layouts reproducible. If |
Invisibly returns the join graph, or a list list(joins = g, relationships = gr)
if relationships_df is provided.
Add a prettified formula column to calculated fields table
prettify_calculated_fields(calcs, strip_brackets = FALSE, wrap = 100L)prettify_calculated_fields(calcs, strip_brackets = FALSE, wrap = 100L)
calcs |
tibble from extract_calculated_fields() |
strip_brackets |
logical |
wrap |
integer wrap width; default 100 |
tibble with extra column formula_pretty
Creates a Markdown migration brief from parsed workbook metadata and optional target-specific compatibility notes.
render_migration_brief( x, target = c("powerbi", "shiny", "quarto", "looker", "superset"), output = NULL )render_migration_brief( x, target = c("powerbi", "shiny", "quarto", "looker", "superset"), output = NULL )
x |
A |
target |
Target tool. |
output |
Optional file path. When supplied, the brief is written to disk. |
A character scalar containing Markdown.
Opens an interactive workbook inspector for .twb and .twbx files.
run_twbparser_app(...)run_twbparser_app(...)
... |
Additional arguments passed to |
The value returned by shiny::runApp().
Writes a minimal Quarto dashboard with one section per Tableau dashboard and worksheet placeholders.
scaffold_quarto_dashboard(x, path = "quarto-scaffold")scaffold_quarto_dashboard(x, path = "quarto-scaffold")
x |
A |
path |
Output directory. |
Path to the written .qmd file.
Writes a minimal app.R with one tab per Tableau dashboard and placeholders
for worksheets detected in the workbook.
scaffold_shiny_dashboard(x, path = "shiny-scaffold")scaffold_shiny_dashboard(x, path = "shiny-scaffold")
x |
A |
path |
Output directory. |
Path to the written app.R.
Prettify a Tableau calculation formula for display
tableau_formula_pretty(formula, strip_brackets = FALSE, wrap = NA_integer_)tableau_formula_pretty(formula, strip_brackets = FALSE, wrap = NA_integer_)
formula |
character scalar |
strip_brackets |
logical; remove [ ] around field names (default FALSE) [ ]: R:%20 |
wrap |
optional integer to hard-wrap lines (use NA to disable) |
character scalar (multi-line, indented)
Performs deterministic, best-effort formula rewrites for common Tableau functions. Complex Tableau features such as LOD expressions and table calculations are flagged for manual review.
translate_tableau_calc(formula, target = c("dax", "sql", "r"))translate_tableau_calc(formula, target = c("dax", "sql", "r"))
formula |
Character vector of Tableau formulas. |
target |
Target language: |
A tibble with source formula, translated formula, confidence, and review notes.
translate_tableau_calc("IF [Sales] > 0 THEN [Profit] ELSE 0 END", target = "sql")translate_tableau_calc("IF [Sales] > 0 THEN [Profit] ELSE 0 END", target = "sql")
Returns every calculated field topologically sorted so that each field
appears after the calculated fields its formula depends on. Recreate the
fields in build_order sequence and every reference will already exist.
Fields caught in a dependency cycle cannot be ordered: they get
build_order = NA and is_cyclic = TRUE (plus a warning naming them).
twb_calc_build_order(x)twb_calc_build_order(x)
x |
A |
A formula token is treated as a calc-on-calc dependency only when it
matches a calculated field and not a raw field or parameter, so
SUM([Sales]) inside a calc captioned "Sales" does not create a false
self-loop. This is a rebuild-ordering aid, not a duplicate of
twb_calc_complexity(): that function classifies complexity and counts
dependencies, while this one gives the concrete creation sequence plus the
human-readable dependency list.
A tibble with columns:
Integer creation sequence (NA for cyclic fields).
Datasource the field belongs to.
Human-readable field name / caption.
Bracketed internal Tableau name.
Raw formula string.
Comma-separated names of the calculated fields this
formula directly depends on (NA when none).
Integer count of direct calc-on-calc dependencies.
Logical; TRUE when the field is part of a dependency
cycle and could not be ordered.
twb_calc_complexity() for complexity classification,
twb_unused_fields() for calculations nothing references.
twb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # "Adjusted Ratio" is built after "Profit Ratio"; the Cycle A/B pair is flagged twb_calc_build_order(xml) parser <- TwbParser$new(twb) parser$get_calc_build_order() parser$calc_build_ordertwb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # "Adjusted Ratio" is built after "Profit Ratio"; the Cycle A/B pair is flagged twb_calc_build_order(xml) parser <- TwbParser$new(twb) parser$get_calc_build_order() parser$calc_build_order
Returns every calculated field in the workbook enriched with a computation
category (calc_type), LOD sub-type, dependency count, and dependency depth
— the maximum number of calc-on-calc hops in the field's dependency chain.
twb_calc_complexity(x, include_parameters = FALSE)twb_calc_complexity(x, include_parameters = FALSE)
x |
A |
include_parameters |
Logical; if |
A tibble with columns:
Datasource the field belongs to.
Human-readable field name.
Bracketed internal Tableau name.
Field data type.
"measure" or "dimension".
One of "lod", "table_calc", "aggregate", "raw".
Tested in that precedence order.
"fixed", "include", or "exclude"; NA if not LOD.
Logical; existing heuristic flag preserved for backward compatibility.
Integer; longest chain of calc-on-calc dependencies.
0 means the field only references raw fields (or has no references).
Integer; count of distinct bracketed tokens in the formula.
Raw formula string.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_calc_complexity(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_calc_complexity(xml)
Chart (mark) types per worksheet.
twb_charts(x)twb_charts(x)
x |
TwbParser or xml2 document. |
Tibble with columns: worksheet, mark_types (comma-separated).
Colors and palettes referenced in the workbook.
twb_colors(x)twb_colors(x)
x |
TwbParser or xml2 document. |
Tibble with columns describing palette names and explicit colors.
Detects Tableau workbook features that commonly affect migrations and maps them to target-tool support levels.
twb_compatibility( x, targets = c("powerbi", "shiny", "quarto", "looker", "superset") )twb_compatibility( x, targets = c("powerbi", "shiny", "quarto", "looker", "superset") )
x |
A |
targets |
Character vector of targets. Supported values are |
A tibble with one row per detected/checked feature and target.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) twb_compatibility(parser, targets = c("powerbi", "shiny")) }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) twb_compatibility(parser, targets = c("powerbi", "shiny")) }
Finds every <relation formula="..."> node that looks like a SQL statement
and returns its name, type, raw SQL text, and a flag for whether it starts
with SELECT or WITH.
twb_custom_sql(x)twb_custom_sql(x)
x |
A |
A tibble with columns:
Name attribute of the relation node.
Type attribute (e.g. "text", "table").
Full SQL text.
TRUE when the text begins with SELECT or WITH.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_custom_sql(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_custom_sql(xml)
Parses <action> nodes from dashboard <actions> sections and the
top-level workbook <actions> section. Returns one row per action.
twb_dashboard_actions(x, dashboard = NULL)twb_dashboard_actions(x, dashboard = NULL)
x |
A |
dashboard |
Optional character scalar. When supplied, only actions
whose |
A tibble with columns:
Caption / display name of the action.
"filter", "highlight", "url", "set", or
another type string from the XML.
Comma-separated list of source worksheet names.
Target worksheet name, or NA for URL actions.
Trigger: "select", "menu", or "hover".
URL value for URL-type actions; NA otherwise.
xml <- xml2::read_xml( '<workbook> <actions> <action caption="Filter 1" name="act1" type="filter"> <source-sheets> <source-sheet name="Sheet1"/> </source-sheets> <target-sheets> <target-sheet name="Sheet2"/> </target-sheets> <run-on type="select"/> </action> </actions> </workbook>' ) twb_dashboard_actions(xml)xml <- xml2::read_xml( '<workbook> <actions> <action caption="Filter 1" name="act1" type="filter"> <source-sheets> <source-sheet name="Sheet1"/> </source-sheets> <target-sheets> <target-sheet name="Sheet2"/> </target-sheets> <run-on type="select"/> </action> </actions> </workbook>' ) twb_dashboard_actions(xml)
Filters found on dashboards and their positions.
twb_dashboard_filters(x, dashboard = NULL)twb_dashboard_filters(x, dashboard = NULL)
x |
TwbParser or xml2 document. |
dashboard |
Optional dashboard name to filter to. |
Tibble with columns: dashboard, zone_id, zone_type, field, presentation, x, y, w, h.
Returns one row per zone per dashboard, including the parent-zone relationship and a tiled/floating classification.
twb_dashboard_layout(x, dashboard = NULL)twb_dashboard_layout(x, dashboard = NULL)
x |
A |
dashboard |
Optional character scalar to restrict output to one dashboard. |
A tibble with columns:
Dashboard name.
Zone identifier.
Parent zone identifier (NA for root zones).
"worksheet", "filter", "legend",
"parameter_control", "text", "image", "container", or "blank".
Referenced worksheet name or object, if applicable.
"floating" or "tiled".
Horizontal offset, or NA.
Vertical offset, or NA.
Width, or NA.
Height, or NA.
xml <- xml2::read_xml( '<workbook> <dashboards> <dashboard name="Overview"> <zones> <zone id="1" type="layoutV"> <zone id="2" worksheet="Sheet1" x="0" y="0" w="600" h="400"/> <zone id="3" type="filter" x="0" y="400" w="600" h="50"/> </zone> </zones> </dashboard> </dashboards> </workbook>' ) twb_dashboard_layout(xml)xml <- xml2::read_xml( '<workbook> <dashboards> <dashboard name="Overview"> <zones> <zone id="1" type="layoutV"> <zone id="2" worksheet="Sheet1" x="0" y="0" w="600" h="400"/> <zone id="3" type="filter" x="0" y="400" w="600" h="50"/> </zone> </zones> </dashboard> </dashboards> </workbook>' ) twb_dashboard_layout(xml)
Returns one row per worksheet per dashboard, with the zone's position on the canvas.
twb_dashboard_sheets(x, dashboard = NULL)twb_dashboard_sheets(x, dashboard = NULL)
x |
A |
dashboard |
Optional character scalar to restrict output to one dashboard. |
A tibble with columns:
Dashboard name.
Referenced worksheet name.
Zone identifier.
Horizontal offset (pixels), or NA.
Vertical offset (pixels), or NA.
Width (pixels), or NA.
Height (pixels), or NA.
xml <- xml2::read_xml( '<workbook> <dashboards> <dashboard name="Overview"> <zones> <zone id="1" worksheet="Sheet1" x="0" y="0" w="600" h="400"/> </zones> </dashboard> </dashboards> </workbook>' ) twb_dashboard_sheets(xml)xml <- xml2::read_xml( '<workbook> <dashboards> <dashboard name="Overview"> <zones> <zone id="1" worksheet="Sheet1" x="0" y="0" w="600" h="400"/> </zones> </dashboard> </dashboards> </workbook>' ) twb_dashboard_sheets(xml)
Reads the <size> element of each dashboard, which records how the page is
sized: a fixed pixel size, an automatic (fit-to-window) size, or a range.
twb_dashboard_size(x, dashboard = NULL)twb_dashboard_size(x, dashboard = NULL)
x |
A |
dashboard |
Optional character scalar to restrict output to one dashboard. |
A tibble with columns:
Dashboard name.
"fixed", "automatic", "range", or another mode
string; NA if no <size> element is present.
Minimum width in pixels, or NA.
Minimum height in pixels, or NA.
Maximum (or fixed) width in pixels, or NA.
Maximum (or fixed) height in pixels, or NA.
xml <- xml2::read_xml( '<workbook><dashboards> <dashboard name="Overview"> <size sizing-mode="fixed" maxwidth="1200" maxheight="800" minwidth="1200" minheight="800"/> </dashboard> </dashboards></workbook>' ) twb_dashboard_size(xml)xml <- xml2::read_xml( '<workbook><dashboards> <dashboard name="Overview"> <size sizing-mode="fixed" maxwidth="1200" maxheight="800" minwidth="1200" minheight="800"/> </dashboard> </dashboards></workbook>' ) twb_dashboard_size(xml)
Per-dashboard summary (filters count and chart types).
twb_dashboard_summary(x)twb_dashboard_summary(x)
x |
TwbParser or xml2 document. |
Tibble with columns: dashboard, worksheet_count, zone_count, filters, chart_types.
Dashboards overview (count of zones and referenced worksheets).
twb_dashboards(x)twb_dashboards(x)
x |
TwbParser or xml2 document. |
Tibble with columns: dashboard, worksheet_count, zone_count.
Combines shelf placement and filter usage into a tidy long tibble showing where each field appears and in what capacity across all (or selected) worksheets.
twb_field_usage( x, include_filters = TRUE, include_shelves = TRUE, wide = FALSE )twb_field_usage( x, include_filters = TRUE, include_shelves = TRUE, wide = FALSE )
x |
A |
include_filters |
Logical; include filter appearances. Default |
include_shelves |
Logical; include shelf appearances (rows, cols, color,
size, etc.). Default |
wide |
Logical; if |
Long form (wide = FALSE): a tibble with columns:
Human-readable field name.
Datasource the field belongs to.
Worksheet name.
Usage context, e.g. "shelf:rows", "shelf:color",
"filter".
Number of times the field appears in this context on this sheet (handles multi-pill rows/cols).
Wide form (wide = TRUE): one row per (field_clean, datasource),
one column per sheet, cell value is a comma-separated context string or
NA.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_field_usage(xml) twb_field_usage(xml, wide = TRUE)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_field_usage(xml) twb_field_usage(xml, wide = TRUE)
Walks every <format> entry inside a <style-rule> and returns a tidy
table of formatting attributes. This is where fonts, colours, number/date
formats, alignment, and shading live in a Tableau workbook. Filter the
attr column for what you need (e.g. attr == "number-format", or
startsWith(attr, "font")).
twb_formatting(x, scope = NULL)twb_formatting(x, scope = NULL)
x |
A |
scope |
Optional character scalar ( |
A tibble with columns:
"worksheet", "dashboard", or "workbook".
Worksheet or dashboard name (NA for workbook scope).
The styled element, e.g. "mark", "axis", "pane",
"cell", "title".
Field the rule targets, if any; NA otherwise.
Palette bucket or other target value, if any; NA
otherwise.
Formatting attribute, e.g. "font-family", "font-size",
"color", "number-format", "encoding-color".
Attribute value.
xml <- xml2::read_xml( '<workbook><worksheets><worksheet name="Sales"><table><style> <style-rule element="mark"> <format attr="mark-labels-cull" value="true"/> <format attr="number-format" value="$#,##0"/> </style-rule> </style></table></worksheet></worksheets></workbook>' ) twb_formatting(xml)xml <- xml2::read_xml( '<workbook><worksheets><worksheet name="Sales"><table><style> <style-rule element="mark"> <format attr="mark-labels-cull" value="true"/> <format attr="number-format" value="$#,##0"/> </style-rule> </style></table></worksheet></worksheets></workbook>' ) twb_formatting(xml)
Returns any <initial-sql> nodes found inside connection or
named-connection elements.
twb_initial_sql(x)twb_initial_sql(x)
x |
A |
A tibble with columns:
Name or caption of the parent connection element.
SQL text of the initial statement.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_initial_sql(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_initial_sql(xml)
Produces a graph-shaped representation of workbook dependencies from datasources and tables through fields, calculated fields, worksheets, and dashboards.
twb_lineage( x, format = c("tables", "igraph", "mermaid"), include_calc_dependencies = TRUE )twb_lineage( x, format = c("tables", "igraph", "mermaid"), include_calc_dependencies = TRUE )
x |
A |
format |
Output format: |
include_calc_dependencies |
Logical; include field-to-calculation and
calculation-to-calculation dependencies parsed from formulas. Default
|
Depends on format. The default is a list with:
Tibble with id, label, and type.
Tibble with from, to, and relationship.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) lineage <- twb_lineage(parser) lineage$nodes lineage$edges }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) lineage <- twb_lineage(parser) lineage$nodes lineage$edges }
Scores workbook complexity and summarizes likely migration risks for a target visualization tool.
twb_migration_assessment( x, target = c("powerbi", "shiny", "quarto", "looker", "superset") )twb_migration_assessment( x, target = c("powerbi", "shiny", "quarto", "looker", "superset") )
x |
A |
target |
Target tool. One of |
A named list with summary, compatibility, and recommendations.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) twb_migration_assessment(parser, target = "shiny")$summary }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) twb_migration_assessment(parser, target = "shiny")$summary }
For a dashboard: one row per zone with component type, target (worksheet or field), filter presentation (if applicable), and x/y/w/h when present. For a worksheet: mark types, filters, legends, parameter controls. For a story: one row per story point with its referenced target.
twb_page_composition(x, name)twb_page_composition(x, name)
x |
TwbParser or xml2 document. |
name |
Page name (character scalar). |
Tibble with columns: page_type, page_name, component_type, zone_id, target, field, presentation, x, y, w, h.
List all pages (dashboards, worksheets, stories).
twb_pages(x)twb_pages(x)
x |
TwbParser or xml2 document. |
Tibble with columns: page_type, name.
Summary of all pages (counts and quick descriptors).
twb_pages_summary(x)twb_pages_summary(x)
x |
TwbParser or xml2 document. |
Tibble with columns including page_type, name, and count columns such as n_zones, n_worksheets, n_filters, n_legends, n_parameter_controls, n_story_points, and mark_types for worksheets.
One row per parameter usage: calculated-field formulas that reference the parameter, worksheet shelves and filters it appears on, and dashboard filter zones bound to it. Parameters become variables when rebuilding in another tool, so this is the map of everywhere each variable's value flows.
twb_parameter_usage(x)twb_parameter_usage(x)
x |
A |
Parameters with no usages do not appear here; find them with
twb_unused_fields(). There is no overlap with twb_field_usage():
that function maps fields to worksheets, while this one maps
parameters to every consumption point including formulas.
A tibble with columns:
Human-readable parameter name / caption.
Datasource the parameter belongs to.
Parameter data type.
Current value if specified in the workbook.
Where it is used: "formula", "shelf:<shelf>"
(e.g. "shelf:rows"), "filter", or "dashboard_filter".
Calculated field name, worksheet name, or dashboard name, depending on context.
twb_unused_fields() for parameters nothing references,
extract_parameters() for parameter definitions.
twb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # "Top N" is used in the "Adjusted Ratio" formula and on a worksheet filter twb_parameter_usage(xml) parser <- TwbParser$new(twb) parser$get_parameter_usage() parser$parameter_usagetwb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # "Top N" is used in the "Adjusted Ratio" formula and on a worksheet filter twb_parameter_usage(xml) parser <- TwbParser$new(twb) parser$get_parameter_usage() parser$parameter_usage
Inspects datasource nodes and heuristically flags those that reference a published (server-side) source rather than an embedded one.
twb_published_refs(x)twb_published_refs(x)
x |
A |
A tibble with columns:
Internal datasource name.
User-visible caption.
Value of the hasconnection attribute.
TRUE when hasconnection = false or when the
node text contains published-source markers.
Short explanation of the classification.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_published_refs(xml)twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) twb_published_refs(xml)
Assembles all extracted intelligence — datasources, parameters, calculated fields with complexity classifications, field usage, filters, sorts, chart types, dashboard layout, and actions — into a single named list (or formatted text) ready for use when porting to another visualisation tool.
twb_replication_brief( x, dashboard = NULL, include_sql = TRUE, include_formulas = TRUE, format = c("list", "text") )twb_replication_brief( x, dashboard = NULL, include_sql = TRUE, include_formulas = TRUE, format = c("list", "text") )
x |
A |
dashboard |
Optional character scalar. When supplied, sheet-level sections (filters, sorts, chart types, field usage, layout) are scoped to the sheets that belong to this dashboard. |
include_sql |
Logical; include custom SQL blocks in |
include_formulas |
Logical; when |
format |
Either |
format = "list": a named list with elements:
1-row tibble: file name, counts, generation timestamp.
Datasource connection details.
Parameter fields with current values.
Custom SQL blocks, or NULL if include_sql = FALSE.
Tibble from twb_calc_complexity(), optionally
with a formula_pretty column.
Tibble from twb_field_usage().
Worksheet filters (scoped to dashboard if given).
Worksheet sorts (scoped to dashboard if given).
Mark types per worksheet.
Zone positions from twb_dashboard_sheets().
Dashboard actions from twb_dashboard_actions().
format = "text": a single Markdown character(1) with section
headers, compact tables, and fenced formula/SQL blocks.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) brief <- twb_replication_brief(xml) names(brief) brief$metatwb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) brief <- twb_replication_brief(xml) names(brief) brief$meta
Reads per-axis style rules embedded in worksheet XML and returns one row per axis per worksheet.
twb_sheet_axes(x, sheet = NULL)twb_sheet_axes(x, sheet = NULL)
x |
A |
sheet |
Optional character scalar to restrict output to one worksheet. |
A tibble with columns:
Worksheet name.
Axis identifier (e.g., "rows", "cols", or "automatic").
Column reference if axis is field-specific; NA otherwise.
Human-readable field name; NA if not field-specific.
Scale type ("linear", "log", …) if present; NA otherwise.
Logical: TRUE if axis is reversed.
Logical: TRUE if zero is pinned on axis.
xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <style> <style-rule element="axis"> <format attr="reverse" value="false"/> <format attr="scale-include-zero" value="true"/> </style-rule> </style> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_axes(xml)xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <style> <style-rule element="axis"> <format attr="reverse" value="false"/> <format attr="scale-include-zero" value="true"/> </style-rule> </style> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_axes(xml)
Returns one row per filter per worksheet, with full details on filter class, inclusion mode, categorical members, and numeric or date range bounds.
twb_sheet_filters(x, sheet = NULL)twb_sheet_filters(x, sheet = NULL)
x |
A |
sheet |
Optional character scalar to restrict output to one worksheet. |
A tibble with columns:
Worksheet name.
Raw column-reference attribute value.
Human-readable field name.
Datasource name.
Tableau filter class: "categorical", "range",
"relative-date", "date", "set", "top", etc.
"include" or "exclude".
Comma-separated member values for categorical filters; NA otherwise.
Lower bound for range/quantitative filters; NA otherwise.
Upper bound; NA otherwise.
xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <view> <filter class="categorical" column="[ds].[Category]"> <groupfilter function="union"> <groupfilter function="member" member="[Furniture]"/> <groupfilter function="member" member="[Technology]"/> </groupfilter> </filter> </view> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_filters(xml)xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <view> <filter class="categorical" column="[ds].[Category]"> <groupfilter function="union"> <groupfilter function="member" member="[Furniture]"/> <groupfilter function="member" member="[Technology]"/> </groupfilter> </filter> </view> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_filters(xml)
Returns a tidy tibble describing which fields are placed on each visual shelf (rows, cols, color, size, label, detail, tooltip, etc.) for every worksheet in the workbook (or a single named sheet).
twb_sheet_shelves(x, sheet = NULL)twb_sheet_shelves(x, sheet = NULL)
x |
A |
sheet |
Optional character scalar. When supplied only that worksheet is returned; otherwise all worksheets are returned. |
A tibble with columns:
Worksheet name.
Shelf name: "rows", "cols", or an encoding type such as
"color", "size", "label", "detail", "tooltip", "shape",
"text", "path", "angle", "lod", "geometry", etc.
Raw column-reference attribute value.
Field instance name (after stripping datasource prefix).
Human-readable field name.
Datasource name referenced.
Aggregation function ("SUM", "AVG", …) or NA.
xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sales"> <table> <rows>[ds].[Category]</rows> <cols>[ds].[Sales]</cols> <panes> <pane> <mark class="Bar"/> <encodings> <color column="[ds].[Category]"/> </encodings> </pane> </panes> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_shelves(xml)xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sales"> <table> <rows>[ds].[Category]</rows> <cols>[ds].[Sales]</cols> <panes> <pane> <mark class="Bar"/> <encodings> <color column="[ds].[Category]"/> </encodings> </pane> </panes> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_shelves(xml)
Returns one row per sort directive per worksheet.
twb_sheet_sorts(x, sheet = NULL)twb_sheet_sorts(x, sheet = NULL)
x |
A |
sheet |
Optional character scalar to restrict output to one worksheet. |
A tibble with columns:
Worksheet name.
Raw column-reference attribute.
Human-readable field name.
Datasource name.
"ascending" or "descending".
Sort method: "field", "alphabetic", "manual", "data-source-order", etc.
xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <view> <sort class="sum" column="[ds].[Sales]" direction="descending"/> </view> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_sorts(xml)xml <- xml2::read_xml( '<workbook> <worksheets> <worksheet name="Sheet1"> <table> <view> <sort class="sum" column="[ds].[Sales]" direction="descending"/> </view> </table> </worksheet> </worksheets> </workbook>' ) twb_sheet_sorts(xml)
twb_sheet_spec() reduces a worksheet to everything needed to
understand — and rebuild — its visualization in another tool: the mark type,
the fields on the rows and columns shelves (in order), the dimensions and
measures in play, every marks-card encoding (color, size, label, detail,
shape, tooltip, ...), tooltip configuration, and the worksheet's filters,
sorts, and axes.
twb_dashboard_charts() answers "what graphs are on this dashboard?": one
row per worksheet placed on each dashboard, with its mark type, fields,
tooltip summary, and layout position.
twb_sheet_spec(x, sheet = NULL) twb_dashboard_charts(x, dashboard = NULL)twb_sheet_spec(x, sheet = NULL) twb_dashboard_charts(x, dashboard = NULL)
x |
A |
sheet |
Optional character scalar to restrict |
dashboard |
Optional character scalar to restrict
|
twb_sheet_spec() returns a named list (one element per worksheet) of
class twb_sheet_spec. Each spec is a list with:
sheetWorksheet name.
mark_typeDetected mark type, e.g. "bar", "line", "map",
"text". "automatic" when the workbook leaves it to Tableau.
mark_source"explicit" when the workbook names the mark type,
"inferred" for "automatic".
datasourcesCharacter vector of datasources referenced.
rows, cols
Character vectors of clean field names on the rows and columns shelves, in shelf order.
dimensions, measures
Character vectors of the dimension and measure fields used anywhere in the visualization. A pill counts as a measure when it is aggregated; otherwise its declared field role wins.
encodingsTibble with channel, field, aggregation,
used_as ("dimension"/"measure") for every marks-card encoding.
shelvesTibble with shelf ("rows"/"cols"), field,
aggregation, used_as for the row/column pills, in shelf order.
tooltipList with has_tooltip, customized, text, and
fields.
filters, sorts, axes
Tibbles from twb_sheet_filters(),
twb_sheet_sorts(), and twb_sheet_axes().
twb_dashboard_charts() returns a tibble with one row per worksheet placed
on a dashboard: dashboard, sheet, mark_type, mark_source, rows,
cols, dimensions, measures, tooltip_fields (list-columns),
n_tooltip_fields, has_tooltip, n_filters, datasources, and the
layout zone_id, x, y, w, h.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) spec <- twb_sheet_spec(parser) spec twb_dashboard_charts(parser) }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) spec <- twb_sheet_spec(parser) spec twb_dashboard_charts(parser) }
Extracts the (plain-text) tooltip configured for each worksheet. Tableau stores customised tooltips as formatted-text runs; this returns the concatenated text with markup stripped.
twb_tooltips(x, sheet = NULL)twb_tooltips(x, sheet = NULL)
x |
A |
sheet |
Optional character scalar to restrict output to one worksheet. |
A tibble with columns:
Worksheet name.
TRUE if a non-empty customised tooltip is present.
Plain-text tooltip content, or NA.
xml <- xml2::read_xml( '<workbook><worksheets><worksheet name="Sales"> <customized-tooltip><formatted-text> <run>Sales: </run><run><SUM(Sales)></run> </formatted-text></customized-tooltip> </worksheet></worksheets></workbook>' ) twb_tooltips(xml)xml <- xml2::read_xml( '<workbook><worksheets><worksheet name="Sales"> <customized-tooltip><formatted-text> <run>Sales: </run><run><SUM(Sales)></run> </formatted-text></customized-tooltip> </worksheet></worksheets></workbook>' ) twb_tooltips(xml)
Lists every raw field, calculated field, and parameter that is defined in a datasource but referenced nowhere: not on any worksheet shelf, filter, or sort, not in any tooltip, not inside any other calculated-field formula, and not in any dashboard filter zone. When rebuilding a workbook in another tool, these are the fields that can safely be left behind.
twb_unused_fields(x)twb_unused_fields(x)
x |
A |
Matching is deliberately conservative: a field is reported as unused only when none of its name forms (internal name or display caption, in any bracket/derivation wrapping) appears anywhere. A field whose name merely collides with a used field in another datasource is treated as used.
This complements twb_field_usage(), which shows where each used field
appears across worksheets.
A tibble with columns:
Datasource the field belongs to.
"raw", "calculated", or "parameter".
Human-readable field name / caption.
Bracketed internal Tableau name.
Field data type.
"measure" or "dimension".
Whether a raw field is hidden (NA for calculated
fields and parameters).
twb_field_usage() for where used fields appear,
twb_calc_build_order() for rebuilding calculations in dependency order.
twb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # the fixture leaves exactly one raw field, one calc, and one parameter unused twb_unused_fields(xml) # same result through the parser object parser <- TwbParser$new(twb) parser$get_unused_fields() parser$unused_fieldstwb <- system.file("extdata", "rebuild_kit.twb", package = "twbparser") stopifnot(nzchar(twb), file.exists(twb)) xml <- xml2::read_xml(twb) # the fixture leaves exactly one raw field, one calc, and one parameter unused twb_unused_fields(xml) # same result through the parser object parser <- TwbParser$new(twb) parser$get_unused_fields() parser$unused_fields
Create a parser for Tableau .twb / .twbx files. On initialization, the
parser reads the XML and precomputes relationships, joins, fields, calculated
fields, inferred relationships, and datasource details. For .twbx, it also
extracts the largest .twb and records a manifest.
An R6 class generator.
Results are read through active-binding properties (no parentheses),
e.g. parser$summary, parser$overview, parser$datasources. The get_*()
methods return the same data and are useful when you need to pass arguments
(e.g. parser$get_sheet_shelves("My Sheet")) or want an explicit call.
Path to the .twb or .twbx file on disk.
Parsed xml2 document of the workbook.
Original .twbx path if the workbook was packaged.
Directory where the .twbx was extracted.
Tibble of .twbx contents from twbx_list().
Tibble of <relation> nodes from extract_relations().
Tibble of join clauses from extract_joins().
Tibble of modern relationships from extract_relationships().
Tibble of inferred relationship pairs by name and role.
List containing data_sources, parameters, and all_sources.
Tibble of raw fields with table information.
Tibble of calculated fields.
Tibble of custom SQL relations from twb_custom_sql().
Tibble of initial SQL statements from twb_initial_sql().
Tibble of published-datasource references from twb_published_refs().
Result from validate() as list with ok and issues elements.
The workbook report (a twbparser_report); accessing it
prints the summary. Note: this is a property, not a method — use
parser$summary, not parser$summary().
Same as summary: the full structured workbook report.
One-row tibble with counts of datasources, parameters, relationships, fields, dashboards, and filters.
Tibble of workbook pages (worksheets, dashboards, stories).
Tibble summarizing page counts by type.
Tibble of chart/mark information per worksheet.
Tibble of color encodings used across worksheets.
Tibble of dashboards in the workbook.
Tibble summarizing dashboards and their filters.
Tibble of dashboard filter configurations.
Tibble of datasource details (see get_datasources()).
Tibble of parameter fields (see get_parameters()).
Tibble of all sources (see get_datasources_all()).
Tibble of raw fields (see get_fields()).
Tibble of custom SQL (see get_custom_sql()).
Tibble of initial SQL (see get_initial_sql()).
Tibble of published references (see get_published_refs()).
Tibble of .twbx contents (see get_twbx_manifest()).
Tibble of .twbx extract entries (see get_twbx_extracts()).
Tibble of .twbx image entries (see get_twbx_images()).
Tibble of shelf placement (see get_sheet_shelves()).
Tibble of worksheet filters (see get_sheet_filters()).
Tibble of axis configuration (see get_sheet_axes()).
Tibble of sort directives (see get_sheet_sorts()).
Named list of per-worksheet visualization specs (see get_sheet_spec()).
Tibble of worksheets per dashboard (see get_dashboard_sheets()).
Tibble of the zone layout tree (see get_dashboard_layout()).
Tibble of dashboard actions (see get_dashboard_actions()).
Tibble of charts placed on dashboards (see get_dashboard_charts()).
Tibble of calculated-field complexity (see get_calc_complexity()).
Tibble of field usage across worksheets (see get_field_usage()).
Tibble of defined-but-never-used fields (see get_unused_fields()).
Tibble of calculated fields in rebuild order (see get_calc_build_order()).
Tibble of parameter consumption points (see get_parameter_usage()).
Migration-oriented datasource-to-dashboard lineage (see get_lineage()).
Target-tool compatibility matrix (see get_compatibility()).
Target-specific migration readiness assessment
(see get_migration_assessment()).
Last validation result; runs validate() first if it has
never been run.
Properties are cached after first access; most return the same tibbles as
the corresponding get_*() methods.
Create a parser from a .twb or .twbx file.
Return .twbx manifest tibble.
Return .twbx extract entries.
Return .twbx image entries.
Extract files from the .twbx archive to disk.
Return relations tibble.
Return joins tibble.
Return modern relationships tibble.
Return inferred relationship pairs.
Return datasource details tibble.
Return parameters tibble.
Return all sources tibble.
Return raw fields tibble.
Return calculated fields tibble. When pretty = TRUE, includes a
formula_pretty column with line breaks and indentation.
Return custom SQL tibble.
Return initial SQL tibble.
Return published-datasource references tibble.
Return workbook pages tibble.
Return page counts by type.
Return zone/mark composition of one page.
Return chart/mark information per worksheet.
Return color encodings used across worksheets.
Return dashboards tibble.
Return dashboard filter configurations.
Return dashboard summary tibble.
Fields placed on visual shelves for one or all worksheets.
Detailed filter configuration for one or all worksheets.
Axis configuration for one or all worksheets.
Sort directives for one or all worksheets.
Full visualization spec for one or all worksheets (mark type, shelves, dimensions/measures, encodings, tooltips, filters, sorts, axes).
Worksheets embedded in one or all dashboards.
Full zone layout with container hierarchy.
Dashboard and workbook actions.
One row per worksheet placed on a dashboard: mark type, fields, tooltip summary, and layout position.
Dashboard page size and sizing mode.
Formatting rules (fonts, colours, number formats, ...);
scope is one of "worksheet", "dashboard", or "workbook".
Plain-text worksheet tooltips.
Calculated field complexity classifications.
Field usage matrix across worksheets.
Fields defined but never used anywhere in the workbook.
Calculated fields topologically sorted for rebuilding.
Where each parameter is consumed (formulas, shelves, filters).
Return migration-oriented datasource-to-dashboard lineage.
Return a target-specific migration readiness assessment.
Return a target-tool compatibility matrix.
Full replication brief for the workbook or a single dashboard.
Return the full structured workbook report.
Return the one-row overview tibble.
Validate relationships. Stops execution if error = TRUE.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb)) { parser <- TwbParser$new(twb) parser$overview parser$get_calculated_fields() }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb)) { parser <- TwbParser$new(twb) parser$overview parser$get_calculated_fields() }
Extract specific files from a .twbx
twbx_extract_files( twbx_path, files = NULL, pattern = NULL, types = NULL, exdir = NULL )twbx_extract_files( twbx_path, files = NULL, pattern = NULL, types = NULL, exdir = NULL )
twbx_path |
Path to a |
files |
Vector of archive paths to extract (optional). |
pattern |
Perl regex to match archive paths (optional). |
types |
Subset by |
exdir |
Output directory (defaults to temp). |
Tibble with name, type, and out_path of extracted files.
twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") files <- twbx_extract_files(twbx, types = c("workbook")) head(files)twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") files <- twbx_extract_files(twbx, types = c("workbook")) head(files)
List contents of a Tableau .twbx
twbx_list(twbx_path)twbx_list(twbx_path)
twbx_path |
Path to a |
Tibble with columns: name, size_bytes, modified, type.
twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") twbx_list(twbx)twbx <- system.file("extdata", "test_for_zip.twbx", package = "twbparser") twbx_list(twbx)
Checks that relationship endpoints reference known datasource tables and that
the predicate fields appear somewhere in the workbook (calculated, raw, or
parameter fields), using a lenient token match (e.g., INT([GEOID]) = GEOID).
validate_relationships(parser, strict = FALSE)validate_relationships(parser, strict = FALSE)
parser |
A |
strict |
Deprecated and ignored. Kept for backward compatibility with twbparser 0.5.0, where it was reserved for future table-scoped checks. |
A list with:
TRUE if no issues; FALSE otherwise.
A named list of tibbles. Possible elements:
unknown_tables: endpoints not found among known tables.
unknown_fields: predicate fields not found in the field pool.
twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) res <- validate_relationships(parser) if (!res$ok) print(res$issues) }twb <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser") if (nzchar(twb) && file.exists(twb)) { parser <- TwbParser$new(twb) res <- validate_relationships(parser) if (!res$ok) print(res$issues) }