The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
library(twbparser)
ok <- FALSE
twb_path <- system.file("extdata", "test_for_wenjie.twb", package = "twbparser")
if (nzchar(twb_path) && file.exists(twb_path)) {
parser <- TwbParser$new(twb_path)
ok <- TRUE
} else {
cat("> Demo .twb not found in installed package. Skipping executable examples.\n")
}
#> TWB loaded: test_for_wenjie.twb
#> TWB parsed and readytwbparser parses Tableau .twb and
.twbx workbooks and exposes datasources, relationships,
joins, fields, calculated fields, and TWBX assets. It also provides
page-centric insights — dashboards, worksheets, stories, their
composition, filter positions, chart types, and colors/palettes — as
well as per-worksheet shelf/filter/axis/sort details and per-dashboard
zone layout and actions. This vignette demonstrates common use
cases.
parser$summary
#> TWB PARSER SUMMARY
#> ------------------
#> File: test_for_wenjie.twb
#> Datasources: 2
#> Parameters: 0
#> Worksheets: 1
#> Dashboards: 0
#> Stories: 0
#> Relationships: 1
#> Calculated fields: 1
#> Raw fields: 55
#> Worksheet filters: 0
#> Dashboard filters: 0
#> Custom SQL blocks: 0
#> Initial SQL blocks: 0
#>
#> Datasources
#> -----------
#> # A tibble: 2 × 4
#> datasource_name connection_type field_count
#> <chr> <chr> <int>
#> 1 Municipal_Boundaries_of_NJ (1) ogrdirect 0
#> 2 federated.0grgaor1pd01yy1f0yr380of1ags federated 110
#> location
#> <chr>
#> 1 Shapefile: Municipal_Boundaries_of_NJ (1).zip
#> 2 Federated: <unknown>
#>
#> Pages
#> -----
#> # A tibble: 1 × 6
#> page_type name mark_types n_filters n_legends n_parameter_controls
#> <chr> <chr> <chr> <int> <int> <int>
#> 1 worksheet Sheet 1 "" 0 0 0
#>
#> Worksheet Shelves
#> -----------------
#> # A tibble: 1 × 3
#> sheet shelves
#> <chr> <chr>
#> 1 Sheet 1 color, cols, geometry, lod, rows
#> fields
#> <chr>
#> 1 Calculation_2139209847776120832, Longitude (generated), Geometry, counts, Lat…
#>
#> Worksheet Filters
#> -----------------
#> No worksheet filters found.
#>
#> Dashboard Filters
#> -----------------
#> No dashboard filters found.
#>
#> Calculated Fields
#> -----------------
#> 1. no data
#> Datasource: federated.0grgaor1pd01yy1f0yr380of1ags
#> Type: string dimension
#> Calculation: raw
#> Table calc: FALSE
#> Dependencies: 1
#> Formula:
#> if ISNULL([counts])
#> THEN "missing"
#> ELSE "available"
#> END
#>
#>
#> SQL
#> ---
#> No custom or initial SQL found.
parser$overview
#> # A tibble: 1 × 9
#> file datasources parameters relationships calculated_fields raw_fields
#> <chr> <int> <int> <int> <int> <int>
#> 1 test_for_we… 2 0 1 1 55
#> # ℹ 3 more variables: inferred_relationships <int>, dashboards <int>,
#> # total_filters <int>datasources <- parser$get_datasources()
parameters <- parser$get_parameters()
print(head(datasources))
#> # A tibble: 2 × 10
#> datasource primary_table connection_id connection_caption connection_class
#> <chr> <chr> <chr> <chr> <chr>
#> 1 Municipal_Bou… [Municipal_B… ogrdirect.07… Municipal_Boundar… ogrdirect
#> 2 Sheet1 [Sheet1$] excel-direct… test_county excel-direct
#> # ℹ 5 more variables: connection_target <chr>, datasource_name <chr>,
#> # field_count <int>, connection_type <chr>, location <chr>
print(head(parameters))
#> # A tibble: 0 × 0Parameters are excluded by default from calculated fields; opt-in via
include_parameters = TRUE.
head(parser$get_fields())
#> # A tibble: 6 × 10
#> datasource name caption datatype role semantic_role table table_clean
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 federated.0grgao… OBJE… <NA> integer <NA> <NA> <NA> <NA>
#> 2 federated.0grgao… MUN <NA> string <NA> <NA> <NA> <NA>
#> 3 federated.0grgao… COUN… <NA> string <NA> <NA> <NA> <NA>
#> 4 federated.0grgao… MUN_… <NA> string <NA> <NA> <NA> <NA>
#> 5 federated.0grgao… MUN_… <NA> string <NA> <NA> <NA> <NA>
#> 6 federated.0grgao… NAME <NA> string <NA> <NA> <NA> <NA>
#> # ℹ 2 more variables: field_clean <chr>, is_parameter <lgl>
head(parser$get_calculated_fields(pretty = TRUE, wrap = 120))
#> # A tibble: 1 × 9
#> datasource name datatype role is_table_calc calc_class formula_pretty
#> <chr> <chr> <chr> <chr> <lgl> <chr> <chr>
#> 1 federated.0grgao… no d… string dime… FALSE tableau "if ISNULL([c…
#> # ℹ 2 more variables: tableau_internal_name <chr>, table_clean <chr>List all pages and summarize each page
twb_pages(parser)
#> # A tibble: 1 × 2
#> page_type name
#> <chr> <chr>
#> 1 worksheet Sheet 1
twb_pages_summary(parser)
#> # A tibble: 1 × 6
#> page_type name mark_types n_filters n_legends n_parameter_controls
#> <chr> <chr> <chr> <int> <int> <int>
#> 1 worksheet Sheet 1 "" 0 0 0Inspect what a specific page contains
pg <- twb_pages(parser)
nm <- if (nrow(pg)) pg$name[[1]] else NA_character_
if (!is.na(nm)) {
parser$get_page_composition(nm)
}
#> # A tibble: 1 × 11
#> page_type page_name component_type zone_id target field presentation x
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <int>
#> 1 worksheet Sheet 1 mark_type <NA> <NA> <NA> <NA> NA
#> # ℹ 3 more variables: y <int>, w <int>, h <int>Filters and their positions across dashboards
twb_dashboard_filters(parser)
#> # A tibble: 0 × 9
#> # ℹ 9 variables: dashboard <chr>, zone_id <chr>, zone_type <chr>, field <chr>,
#> # presentation <chr>, x <int>, y <int>, w <int>, h <int>Chart (mark) types per worksheet and colors/palettes
Each of the four functions below accepts an optional
sheet argument to restrict output to a single
worksheet.
shelves <- twb_sheet_shelves(parser)
head(shelves)
#> # A tibble: 6 × 7
#> sheet shelf field_ref field_instance field_clean datasource aggregation
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Sheet 1 color [federated… none:Calculat… Calculatio… federated… <NA>
#> 2 Sheet 1 cols [federated… Longitude (ge… Longitude … federated… <NA>
#> 3 Sheet 1 geometry [federated… clct:Geometry… Geometry federated… <NA>
#> 4 Sheet 1 lod [federated… clct:Geometry… Geometry federated… <NA>
#> 5 Sheet 1 lod [federated… none:counts:qk counts federated… <NA>
#> 6 Sheet 1 rows [federated… Latitude (gen… Latitude (… federated… <NA>The shelf column distinguishes "rows",
"cols", "color", "size",
"label", "detail", and
"tooltip".
filters <- twb_sheet_filters(parser)
head(filters)
#> # A tibble: 0 × 9
#> # ℹ 9 variables: sheet <chr>, field_ref <chr>, field_clean <chr>,
#> # datasource <chr>, filter_class <chr>, include_mode <chr>, members <chr>,
#> # range_min <chr>, range_max <chr>Categorical filters include a comma-separated members
column; range filters populate range_min /
range_max.
spec <- twb_sheet_spec(parser, sheet = "Sheet 1")
spec
#> Sheet: Sheet 1
#> Mark type: map
#> Datasources: federated.0grgaor1pd01yy1f0yr380of1ags
#> Rows (1): Latitude (generated)
#> Cols (1): Longitude (generated)
#> Dimensions (5): Latitude (generated), Longitude (generated), Calculation_2139209847776120832, Geometry, counts
#> Measures: (none)
#> Encodings: color -> Calculation_2139209847776120832; geometry -> Geometry; lod -> Geometry; lod -> counts
#> Tooltips:none
#> Filters: 0 Sorts: 0 Axes: 0twb_sheet_spec() returns one spec per worksheet: the
mark type, the rows/columns shelves in order, the dimensions and
measures in play, every marks-card encoding, the tooltip configuration,
and the sheet’s filters, sorts, and axes — the full blueprint for
rebuilding the visualization in another tool.
parser$sheet_spec exposes the same specs as a property.
Three helpers answer the questions that come up when rebuilding a
workbook in another tool. They are demonstrated on the bundled
rebuild_kit.twb fixture, which contains chained
calculations, a circular pair, parameters, and deliberately unused
fields.
kit_ok <- FALSE
kit_path <- system.file("extdata", "rebuild_kit.twb", package = "twbparser")
if (nzchar(kit_path) && file.exists(kit_path)) {
kit <- TwbParser$new(kit_path)
kit_ok <- TRUE
}
#> TWB loaded: rebuild_kit.twb
#> TWB parsed and ready# Fields defined but never used anywhere: the safe-to-drop list
twb_unused_fields(kit)
#> # A tibble: 3 × 7
#> datasource field_type name tableau_internal_name datatype role is_hidden
#> <chr> <chr> <chr> <chr> <chr> <chr> <lgl>
#> 1 sales-data calculated Unused C… [Calculation_0003] real meas… NA
#> 2 sales-data parameter Unused P… [Parameter 2] string dime… NA
#> 3 sales-data raw Unused F… [Unused Field] string dime… FALSE# Calculations in creation order — "Adjusted Ratio" comes after "Profit Ratio";
# the Cycle A/B pair is flagged instead of silently misordered
twb_calc_build_order(kit)
#> Warning: Circular dependencies detected among calculated fields: Cycle A, Cycle
#> B. `build_order` is NA for these fields; break the cycle before rebuilding.
#> # A tibble: 5 × 8
#> build_order datasource name tableau_internal_name formula depends_on
#> <int> <chr> <chr> <chr> <chr> <chr>
#> 1 1 sales-data Profit Ratio [Calculation_0001] [Profi… <NA>
#> 2 2 sales-data Unused Calc [Calculation_0003] [Sales… <NA>
#> 3 3 sales-data Adjusted Ratio [Calculation_0002] [Profi… Profit Ra…
#> 4 NA sales-data Cycle A [Calculation_0004] [Cycle… Cycle B
#> 5 NA sales-data Cycle B [Calculation_0005] [Cycle… Cycle A
#> # ℹ 2 more variables: n_calc_deps <int>, is_cyclic <lgl># Where each parameter value flows: formulas, shelves, filters, dashboards
twb_parameter_usage(kit)
#> # A tibble: 2 × 6
#> parameter datasource datatype current_value context location
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Top N sales-data integer 5 filter Profit Detail
#> 2 Top N sales-data integer 5 formula Adjusted Ratiotwb_unused_fields() covers raw fields, calculated
fields, and parameters; twb_calc_build_order()
warns and marks build_order = NA for fields caught in a
dependency cycle; parameters with no usages are found via
twb_unused_fields() rather than appearing empty in
twb_parameter_usage().
charts <- twb_dashboard_charts(parser)
head(charts)
#> # A tibble: 0 × 18
#> # ℹ 18 variables: dashboard <chr>, sheet <chr>, mark_type <chr>,
#> # mark_source <chr>, rows <list>, cols <list>, dimensions <list>,
#> # measures <list>, tooltip_fields <list>, n_tooltip_fields <int>,
#> # has_tooltip <lgl>, n_filters <int>, datasources <list>, zone_id <chr>,
#> # x <int>, y <int>, w <int>, h <int>One row per worksheet placed on each dashboard: mark type, fields
(rows, cols, dimensions,
measures as list-columns), tooltip summary, and layout
position. (The bundled demo workbook has no dashboards, so this is empty
here.)
db_sheets <- twb_dashboard_sheets(parser)
head(db_sheets)
#> # A tibble: 0 × 7
#> # ℹ 7 variables: dashboard <chr>, sheet <chr>, zone_id <chr>, x <int>, y <int>,
#> # w <int>, h <int>x, y, w, h are
pixel coordinates within the dashboard canvas.
layout <- twb_dashboard_layout(parser)
head(layout)
#> # A tibble: 0 × 10
#> # ℹ 10 variables: dashboard <chr>, zone_id <chr>, parent_zone_id <chr>,
#> # component_type <chr>, target <chr>, layout_type <chr>, x <int>, y <int>,
#> # w <int>, h <int>parent_zone_id links child zones to their container;
root zones have NA. component_type is one of
"worksheet", "filter",
"container", "legend",
"parameter_control", "text",
"image", or "blank".
actions <- twb_dashboard_actions(parser)
head(actions)
#> # A tibble: 0 × 6
#> # ℹ 6 variables: action_name <chr>, action_type <chr>, source_sheets <chr>,
#> # target_sheet <chr>, run_on <chr>, url <chr>action_type is "filter",
"url", "highlight", or
"parameter". source_sheets is a
comma-separated list; url is populated for URL actions.
relations <- parser$get_relationships()
head(relations)
#> # A tibble: 1 × 8
#> relationship_type left_table right_table left_field operator right_field
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Relationship Sheet1 Municipal_Bounda… County = COUNTY
#> # ℹ 2 more variables: left_is_calc <lgl>, right_is_calc <lgl>For non-interactive use, parse_twb() parses the workbook
and writes a structured report to disk — a human-readable
report.txt, one CSV per key table, a plain-text replication
brief, and the field dependency graph as GraphML:
out <- parse_twb(parser$path,
output_dir = file.path(tempdir(), "twbparser-vignette"),
overwrite = TRUE, quiet = TRUE)
list.files(out)
#> [1] "calc_build_order.csv" "calculated_fields.csv"
#> [3] "custom_sql.csv" "dashboards.csv"
#> [5] "datasources.csv" "dependency_graph.graphml"
#> [7] "fields.csv" "joins.csv"
#> [9] "overview.csv" "pages.csv"
#> [11] "parameter_usage.csv" "parameters.csv"
#> [13] "relationships.csv" "replication_brief.txt"
#> [15] "report.txt" "sheet_specs.txt"
#> [17] "unused_fields.csv"This vignette overviewed how to use the twbparser
package for detailed inspection and extraction of Tableau workbook
internals to assist in analysis, replication, or integration
workflows.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.