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.

twbparser-intro

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 ready

Introduction

twbparser 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.

Parse a Tableau Workbook

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>

Extracting Datasources and Parameters

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 × 0

Fields and calculated fields

Parameters 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>

Page insights

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                    0

Inspect 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

twb_charts(parser)
#> # A tibble: 1 × 2
#>   worksheet mark_types
#>   <chr>     <chr>     
#> 1 Sheet 1   ""
twb_colors(parser)
#> # A tibble: 0 × 4
#> # ℹ 4 variables: kind <chr>, detail <chr>, scope <chr>, label <chr>

Worksheet intelligence

Each of the four functions below accepts an optional sheet argument to restrict output to a single worksheet.

Shelves — what fields are on rows, cols, and encodings?

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

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.

Axis configuration

axes <- twb_sheet_axes(parser)
head(axes)
#> # A tibble: 0 × 7
#> # ℹ 7 variables: sheet <chr>, axis <chr>, field_ref <chr>, field_clean <chr>,
#> #   scale_type <chr>, reversed <lgl>, include_zero <lgl>

Sort directives

sorts <- twb_sheet_sorts(parser)
head(sorts)
#> # A tibble: 0 × 6
#> # ℹ 6 variables: sheet <chr>, field_ref <chr>, field_clean <chr>,
#> #   datasource <chr>, sort_order <chr>, sort_by <chr>

Visualization spec — everything needed to rebuild a sheet

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: 0

twb_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.

Rebuild kit — what do you actually need to recreate?

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 Ratio

twb_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().

Dashboard intelligence

Charts on a dashboard

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.)

Sheet positions

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.

Zone layout tree

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

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.

Relationships and Joins

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>

Working with TWBX Files (if applicable)

parser$get_twbx_manifest()
parser$get_twbx_extracts()
parser$get_twbx_images()

Validation of Relationships

v <- parser$validate()
if (isTRUE(v$ok)) {
cat("Relationships validated successfully.\n")
} else {
print(v$issues)
}
#> Relationships validated successfully.

Batch export

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"

Summary

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.