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).
Value
A tibble with columns:
- build_order
Integer creation sequence (
NAfor cyclic fields).- datasource
Datasource the field belongs to.
- name
Human-readable field name / caption.
- tableau_internal_name
Bracketed internal Tableau name.
- formula
Raw formula string.
- depends_on
Comma-separated names of the calculated fields this formula directly depends on (
NAwhen none).- n_calc_deps
Integer count of direct calc-on-calc dependencies.
- is_cyclic
Logical;
TRUEwhen the field is part of a dependency cycle and could not be ordered.
Details
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.
See also
twb_calc_complexity() for complexity classification,
twb_unused_fields() for calculations nothing references.
Examples
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)
#> 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>
parser <- TwbParser$new(twb)
#> TWB loaded: rebuild_kit.twb
#> TWB parsed and ready
parser$get_calc_build_order()
#> 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>
parser$calc_build_order
#> 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>
