| Title: | Framework for Clinical Tables, Figures, and Listings |
|---|---|
| Description: | Library provides framework for generation of clinical TFLs. The purpose is to provide functionality to prepare metadata that describes TFL and pass this metadata together with data to the C++ rendering engine to generate final DOCX documents with styles and deterministic pagination. Bundled third-party components include vendored FreeType, HarfBuzz, minizip, and nlohmann/json code plus Liberation fonts under their respective compatible licenses; see LICENSE for redistribution details. |
| Authors: | Igor Aleschenkov [aut, cre, cph], Vladimir Larchenko [aut, cph] |
| Maintainer: | Igor Aleschenkov <[email protected]> |
| License: | GPL-3 + file LICENSE |
| Version: | 0.11.7 |
| Built: | 2026-06-19 17:44:12 UTC |
| Source: | https://github.com/crow16384/ksTFL |
Add body text (e.g., when no data to display)
add_body_text( spec = NULL, text = NULL, id = NULL, styleRef = NULL, order = NULL )add_body_text( spec = NULL, text = NULL, id = NULL, styleRef = NULL, order = NULL )
spec |
Spec object (dispatches on class) |
text |
Character vector of body text lines |
id |
Body text identifier (auto-generated if NULL) |
styleRef |
Character vector of style names or result of |
order |
Order of body text group (auto-assigned if NULL) |
Generic function to add body text. Dispatches to class-specific methods, allowing different spec classes to implement their own body text handling.
Multiple calls add multiple text groups. Calling with the same ID merges with last-win strategy.
Updated spec object
## Not run: # Text-only spec with body text spec <- create_text() |> set_document(hasData = FALSE) |> add_body_text("No data available for the specified criteria.") # Table spec with body text as fallback when no data rows spec <- create_table(empty_df) |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported.", styleRef = f_combine("b", "fc_red")) ## End(Not run)## Not run: # Text-only spec with body text spec <- create_text() |> set_document(hasData = FALSE) |> add_body_text("No data available for the specified criteria.") # Table spec with body text as fallback when no data rows spec <- create_table(empty_df) |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported.", styleRef = f_combine("b", "fc_red")) ## End(Not run)
Default method for add_body_text
## Default S3 method: add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)## Default S3 method: add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)
spec |
Spec object |
text |
Character vector of body text lines |
id |
Body text identifier |
styleRef |
Character vector of style names or result of |
order |
Order of body text group |
Error if no method found
When adding body text to TFL options (global settings), automatically removes any existing default body text entries (__default_NNN) and starts adding new ones from __default_002 onwards.
## S3 method for class 'TFL_options' add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)## S3 method for class 'TFL_options' add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)
spec |
TFL_options object |
text |
Character vector of body text lines |
id |
Body text identifier (auto-generated as __default_NNN if NULL) |
styleRef |
Character vector of style names or result of |
order |
Order of body text group (auto-assigned if NULL) |
Updated options object
When adding body text to a spec that has default body text entries (IDs starting with _default), they are automatically removed to avoid mixing defaults with user-defined content.
## S3 method for class 'TFL_spec' add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)## S3 method for class 'TFL_spec' add_body_text(spec, text = NULL, id = NULL, styleRef = NULL, order = NULL)
spec |
TFL_spec object |
text |
Character vector of body text lines |
id |
Body text identifier (auto-generated if NULL) |
styleRef |
Character vector of style names or result of |
order |
Order of body text group (auto-assigned if NULL) |
Updated spec object
Add a footnote to the specification. Multiple calls add multiple footnote groups. Calling with the same ID merges with last-win strategy.
add_footnote(spec, text, id = NULL, styleRef = NULL, order = NULL)add_footnote(spec, text, id = NULL, styleRef = NULL, order = NULL)
spec |
TFL spec object |
text |
Character vector of footnote text lines |
id |
Footnote identifier (auto-generated if NULL) |
styleRef |
Character vector of style names or result of |
order |
Order of footnote group (auto-assigned if NULL) |
Updated spec object
## Not run: spec <- create_table(mtcars) |> add_footnote("Data source: Clinical database lock 2025-12-01") |> add_footnote("Missing values displayed as 'N/A'", styleRef = f_combine("footnote_style", "font_courier_new")) # Multiple footnote lines in one group spec <- create_table(mtcars) |> add_footnote(c("a. Treatment group A", "b. Treatment group B")) ## End(Not run)## Not run: spec <- create_table(mtcars) |> add_footnote("Data source: Clinical database lock 2025-12-01") |> add_footnote("Missing values displayed as 'N/A'", styleRef = f_combine("footnote_style", "font_courier_new")) # Multiple footnote lines in one group spec <- create_table(mtcars) |> add_footnote(c("a. Treatment group A", "b. Treatment group B")) ## End(Not run)
Generic function to add header rows. Dispatches to class-specific methods, allowing headers to be added to both spec objects and global options.
add_header(spec = NULL, ..., level = NULL)add_header(spec = NULL, ..., level = NULL)
spec |
Spec object (dispatches on class) |
... |
Up to 3 character strings (left, center, right)
|
level |
Optional numeric index. If provided, replaces header at that row. If NULL, appends next row. |
Each call adds a new header row. Per schema, headers are arrays of arrays (each call = one row).
Updated spec object
## Not run: # Add to a spec object spec <- create_text() |> add_header("Study ABC-123", "CONFIDENTIAL", "Page {PAGE}") |> add_header("Protocol v2.0", "", paste("Date:", format(Sys.Date(), "%Y-%m-%d"))) # Add to global options options <- tfl_get_options() options <- add_header(options, "Study ABC-123", "CONFIDENTIAL", "Page {PAGE}") ## End(Not run)## Not run: # Add to a spec object spec <- create_text() |> add_header("Study ABC-123", "CONFIDENTIAL", "Page {PAGE}") |> add_header("Protocol v2.0", "", paste("Date:", format(Sys.Date(), "%Y-%m-%d"))) # Add to global options options <- tfl_get_options() options <- add_header(options, "Study ABC-123", "CONFIDENTIAL", "Page {PAGE}") ## End(Not run)
Default method for add_header
## Default S3 method: add_header(spec, ...)## Default S3 method: add_header(spec, ...)
spec |
Spec object |
... |
Header parts
|
Error if no method found
Adds a header row to the global TFL options, which can be used as defaults for all spec objects.
## S3 method for class 'TFL_options' add_header(spec, ..., level = NULL)## S3 method for class 'TFL_options' add_header(spec, ..., level = NULL)
spec |
TFL_options object |
... |
Up to 3 character strings (left, center, right)
|
level |
Optional numeric index. If provided, replaces header at that row. If NULL, appends next row. |
Updated options object
Add a header row for TFL_spec
## S3 method for class 'TFL_spec' add_header(spec, ..., level = NULL)## S3 method for class 'TFL_spec' add_header(spec, ..., level = NULL)
spec |
TFL_spec object |
... |
Up to 3 character strings (left, center, right)
|
level |
Optional numeric index. If provided, replaces header at that row. If NULL, appends next row. |
Updated spec object
Define a spanning header that covers multiple columns. Can be used to create
multi-level headers by specifying different stubOrder values.
add_span_header( spec, cols, label, stubOrder = NULL, id = NULL, labelStyleRef = NULL )add_span_header( spec, cols, label, stubOrder = NULL, id = NULL, labelStyleRef = NULL )
spec |
TFL spec object |
cols |
Columns to span using tidyselect syntax. Accepts:
|
label |
Spanning header label |
stubOrder |
Order of stub header (auto-generated if NULL). Used to create multi-level headers: lower numbers appear above higher numbers. Multiple stubs at the same order are allowed if their column sets do not overlap. |
id |
Stub column identifier (auto-generated if NULL) |
labelStyleRef |
List of style names to be applied. Provided styles will be merged with last-win strategy for report |
Stubs at the same stubOrder cannot share columns (to avoid ambiguous headers).
However, stubs at different stubOrder values can overlap freely.
This allows hierarchical header structures:
stubOrder = 1: first-level grouping above the column headers
stubOrder = 2: next-level grouping above the first-level etc..
Multiple calls with the same stubOrder are allowed as long as their column sets
do not overlap. This enables building complex header structures incrementally.
Updated spec object
## Not run: data <- data.frame( id = 1:10, age = rnorm(10, 45, 10), sex = sample(c("M", "F"), 10, TRUE), weight = rnorm(10, 70, 10), height = rnorm(10, 170, 10) ) # Example 1: Single-level spanning header spec <- create_table(data) |> add_span_header( cols = c(age, sex), # Using tidyselect (unquoted column names) label = "Demographics", labelStyleRef = c("stub_label_style", "bold") ) # Example 2: Two-level header hierarchy spec <- create_table(data) |> add_span_header(cols = c(age, sex, weight, height), label = "All Measurements", stubOrder = 0) |> add_span_header(cols = c(age, sex), label = "Demographics", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Physical", stubOrder = 1) # Example 3: Three-level header hierarchy spec <- create_table(data) |> add_span_header(cols = starts_with("a") | starts_with("w") | starts_with("h"), label = "Main Data", stubOrder = 0) |> add_span_header(cols = c(age, sex), label = "Demographics", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Physical", stubOrder = 1) |> add_span_header(cols = age, label = "Age Details", stubOrder = 2) # Example 4: Using tidyselect helpers spec <- create_table(data) |> add_span_header(cols = contains("age"), label = "Age-related", stubOrder = 0) |> add_span_header(cols = matches("^w"), label = "Weight", stubOrder = 0) # Example 5: Negation to exclude columns spec <- create_table(data) |> add_span_header(cols = -id, label = "Measurements", stubOrder = 0) # Example 6: Multiple non-overlapping stubs at same level spec <- create_table(data) |> add_span_header(cols = c(age, sex), label = "Group1", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Group2", stubOrder = 1) # OK: no overlap ## End(Not run)## Not run: data <- data.frame( id = 1:10, age = rnorm(10, 45, 10), sex = sample(c("M", "F"), 10, TRUE), weight = rnorm(10, 70, 10), height = rnorm(10, 170, 10) ) # Example 1: Single-level spanning header spec <- create_table(data) |> add_span_header( cols = c(age, sex), # Using tidyselect (unquoted column names) label = "Demographics", labelStyleRef = c("stub_label_style", "bold") ) # Example 2: Two-level header hierarchy spec <- create_table(data) |> add_span_header(cols = c(age, sex, weight, height), label = "All Measurements", stubOrder = 0) |> add_span_header(cols = c(age, sex), label = "Demographics", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Physical", stubOrder = 1) # Example 3: Three-level header hierarchy spec <- create_table(data) |> add_span_header(cols = starts_with("a") | starts_with("w") | starts_with("h"), label = "Main Data", stubOrder = 0) |> add_span_header(cols = c(age, sex), label = "Demographics", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Physical", stubOrder = 1) |> add_span_header(cols = age, label = "Age Details", stubOrder = 2) # Example 4: Using tidyselect helpers spec <- create_table(data) |> add_span_header(cols = contains("age"), label = "Age-related", stubOrder = 0) |> add_span_header(cols = matches("^w"), label = "Weight", stubOrder = 0) # Example 5: Negation to exclude columns spec <- create_table(data) |> add_span_header(cols = -id, label = "Measurements", stubOrder = 0) # Example 6: Multiple non-overlapping stubs at same level spec <- create_table(data) |> add_span_header(cols = c(age, sex), label = "Group1", stubOrder = 1) |> add_span_header(cols = c(weight, height), label = "Group2", stubOrder = 1) # OK: no overlap ## End(Not run)
Generic function to add or update style definitions. Dispatches to class-specific methods, allowing different spec classes to implement their own style handling.
add_style(spec, id, ...)add_style(spec, id, ...)
spec |
Spec object (dispatches on class) |
id |
Style identifier (auto-generated if NULL) |
... |
Style modifiers created with s_* functions
|
Define styling for various document elements. Multiple calls to the same modifier function will merge with last-win strategy.
Available modifiers inside this function:
s_font - Font properties
s_paragraph - Paragraph formatting
s_table_style - Table cell styling
Updated spec object
## Not run: spec <- create_text() |> add_style(id = "header", s_font(font_name = "Arial", font_size = "14pt", bold = TRUE), s_paragraph(alignment = "center"), s_table_style(background_color = "#D9D9D9") ) |> # Multiple calls merge with last-win add_style(id = "header", s_font(color = "#FF0000") # Adds color, keeps other font properties ) ## End(Not run)## Not run: spec <- create_text() |> add_style(id = "header", s_font(font_name = "Arial", font_size = "14pt", bold = TRUE), s_paragraph(alignment = "center"), s_table_style(background_color = "#D9D9D9") ) |> # Multiple calls merge with last-win add_style(id = "header", s_font(color = "#FF0000") # Adds color, keeps other font properties ) ## End(Not run)
Default method for add_style
## Default S3 method: add_style(spec, id = NULL, ...)## Default S3 method: add_style(spec, id = NULL, ...)
spec |
Spec object |
id |
Style identifier |
... |
Style modifiers
|
Error if no method found
Add or update a style definition for TFL_options
## S3 method for class 'TFL_options' add_style(spec, id = NULL, ...)## S3 method for class 'TFL_options' add_style(spec, id = NULL, ...)
spec |
TFL_options style branch object |
id |
Style identifier (name) |
... |
Style modifiers created with s_* functions
|
Updated spec object
Add or update a style definition for TFL_spec
## S3 method for class 'TFL_spec' add_style(spec, id, ...)## S3 method for class 'TFL_spec' add_style(spec, id, ...)
spec |
TFL_spec object |
id |
Style identifier (auto-generated if NULL) |
... |
Style modifiers created with s_* functions
|
Updated spec object
Add a subtitle to the specification. Multiple calls add multiple subtitle groups. Calling with the same ID merges with last-win strategy.
add_subtitle( spec, text, id = NULL, styleRef = NULL, order = NULL, toclevel = NULL )add_subtitle( spec, text, id = NULL, styleRef = NULL, order = NULL, toclevel = NULL )
spec |
TFL spec object. |
text |
Character vector of subtitle text lines. May contain |
id |
Subtitle identifier (auto-generated if |
styleRef |
Character vector of style names to apply. Styles are merged with last-win strategy. |
order |
Integer ordering key (auto-assigned if |
toclevel |
Optional integer 1–9. When set, this subtitle is marked as a Table of Contents entry at the given level. Static subtitles (no Dynamic subtitles (containing In both cases, multi-line subtitles are concatenated with a space and inline
styling tags are stripped for the TOC entry text. Use together with
|
Updated spec object.
## Not run: # Static subtitle — one TOC entry for the whole report spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> add_subtitle("Safety Analysis Set", toclevel = 2) |> add_subtitle("Data Cutoff: 2025-12-14") # Dynamic subtitle — one TOC entry per group value (e.g. one per visit) spec <- create_table(advs) |> add_title("Table 2: Vital Signs by Visit and Parameter", toclevel = 1) |> add_subtitle("#ByGroup1 - #ByGroup2", toclevel = 2) # Generate the TOC page report <- create_report(spec) save_report(report, docFileName = "tables.docx", insertTOC = TRUE) # Open tables.docx in Word, click the TOC placeholder, press F9 to update. ## End(Not run)## Not run: # Static subtitle — one TOC entry for the whole report spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> add_subtitle("Safety Analysis Set", toclevel = 2) |> add_subtitle("Data Cutoff: 2025-12-14") # Dynamic subtitle — one TOC entry per group value (e.g. one per visit) spec <- create_table(advs) |> add_title("Table 2: Vital Signs by Visit and Parameter", toclevel = 1) |> add_subtitle("#ByGroup1 - #ByGroup2", toclevel = 2) # Generate the TOC page report <- create_report(spec) save_report(report, docFileName = "tables.docx", insertTOC = TRUE) # Open tables.docx in Word, click the TOC placeholder, press F9 to update. ## End(Not run)
Add a title to the specification. Multiple calls add multiple title groups. Calling with the same ID merges with last-win strategy.
add_title( spec, text, id = NULL, styleRef = NULL, order = NULL, toclevel = NULL )add_title( spec, text, id = NULL, styleRef = NULL, order = NULL, toclevel = NULL )
spec |
TFL spec object. |
text |
Character vector of title text lines. Multiple elements are rendered as separate lines within the same title paragraph. |
id |
Title identifier (auto-generated if |
styleRef |
Character vector of style names to apply. Styles are merged with last-win strategy. |
order |
Integer ordering key (auto-assigned if |
toclevel |
Optional integer 1–9. When set, the first page occurrence
of this title is marked as a Table of Contents entry at the given level.
Multi-line titles are concatenated with a space for the TOC entry text;
inline styling tags (e.g. To generate a TOC page, set |
Updated spec object.
## Not run: # Basic multi-line title (no TOC) spec <- create_table(adsl) |> add_title(c("Study ABC-123", "Table 1: Demographics")) |> add_title("Full Analysis Set", styleRef = "subtitle_style") # Title marked for TOC at level 1 — renderer will emit a TC field on the first page spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) # Full TOC workflow across a multi-spec report t1 <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> set_document(hasData = TRUE) t2 <- create_table(advs) |> add_title("Table 2: Vital Signs", toclevel = 1) |> set_document(hasData = TRUE) report <- create_report(t1, t2) save_report(report, docFileName = "tables.docx", insertTOC = TRUE) # Open tables.docx in Word, click the TOC placeholder, press F9 to update. ## End(Not run)## Not run: # Basic multi-line title (no TOC) spec <- create_table(adsl) |> add_title(c("Study ABC-123", "Table 1: Demographics")) |> add_title("Full Analysis Set", styleRef = "subtitle_style") # Title marked for TOC at level 1 — renderer will emit a TC field on the first page spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) # Full TOC workflow across a multi-spec report t1 <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> set_document(hasData = TRUE) t2 <- create_table(advs) |> add_title("Table 2: Vital Signs", toclevel = 1) |> set_document(hasData = TRUE) report <- create_report(t1, t2) save_report(report, docFileName = "tables.docx", insertTOC = TRUE) # Open tables.docx in Word, click the TOC placeholder, press F9 to update. ## End(Not run)
Declares an additional row to be inserted above or below rows matching
the parent compute_cols() condition. Content can optionally be copied from a
specified column; if omitted, creates an empty separator row.
c_addrow(pos, value_from = NULL, styleRef = NULL)c_addrow(pos, value_from = NULL, styleRef = NULL)
pos |
Character. Position for insertion: "above" or "below". |
value_from |
Character or unquoted column name. Optional source column for the inserted row's content. If NULL or missing, creates an empty separator row. |
styleRef |
Character vector or result of |
Must be called inside compute_cols().
Behavior:
Multiple c_addrow() calls in one compute_cols() accumulate
Order of appearance is preserved
Coexists with other actions on same row
If value_from is provided, must exist in spec columns (data_env reference)
If value_from is NULL or missing, creates an empty separator row
Stackable Actions:
Actions within a single compute_cols() call execute sequentially in the order
specified. This means c_addrow() can see values modified by earlier c_glue()
actions, allowing you to build compound cell values (e.g., "PARAM: VISIT") before
using them in inserted rows. Multiple c_glue() and c_addrow() calls can be
interleaved as needed.
Quosure structure (internal use within compute_cols())
compute_cols() for conditional row actions, c_style(), c_merge() for other action types
## Not run: compute_cols(spec, lastOf(treatment), c_addrow(pos = "below", value_from = "treatment")) compute_cols(spec, firstOf(visit), c_addrow(pos = "above")) # Stackable: addrow sees glued value compute_cols(spec, PARAM == "ALT", c_glue(PARAM, "after", glue_col = VISIT, separator = ": "), c_addrow("above", value_from = PARAM) # Uses "ALT: Week 2" ) ## End(Not run)## Not run: compute_cols(spec, lastOf(treatment), c_addrow(pos = "below", value_from = "treatment")) compute_cols(spec, firstOf(visit), c_addrow(pos = "above")) # Stackable: addrow sees glued value compute_cols(spec, PARAM == "ALT", c_glue(PARAM, "after", glue_col = VISIT, separator = ": "), c_addrow("above", value_from = PARAM) # Uses "ALT: Week 2" ) ## End(Not run)
Declares a clear action that blanks the display text of specified cells in
rows matching the parent compute_cols() condition. The cells are rendered
empty without affecting their column structure, width, or styling.
c_clear(cols)c_clear(cols)
cols |
Tidyselect expression for the target columns to blank
(e.g., |
Must be called inside compute_cols().
Behavior:
Sets the rendered cell text to "" for matching rows.
Processed before c_merge() and c_glue() in the rendering chain,
so the cleared state participates in subsequent actions. In particular:
combining c_clear() + c_glue() on the same column effectively
replaces the original cell content with the glued value.
Compatible with c_style(): styling is independent of text content.
When c_merge() targets a cleared leader cell, the merged span
renders as a blank merged cell.
Quosure-style marker (internal use within compute_cols())
compute_cols(), c_style(), c_merge(), c_glue()
## Not run: # Blank label column in total rows spec <- compute_cols(spec, is_total, c_clear(label)) # Clear then replace with a value from another column (full replacement) spec <- compute_cols(spec, condition, c_clear(display_col), c_glue(display_col, "after", glue_col = replacement_col)) ## End(Not run)## Not run: # Blank label column in total rows spec <- compute_cols(spec, is_total, c_clear(label)) # Clear then replace with a value from another column (full replacement) spec <- compute_cols(spec, condition, c_clear(display_col), c_glue(display_col, "after", glue_col = replacement_col)) ## End(Not run)
Declares a glue action to concatenate a value — from a data column or a
literal string — to the display text of specified cells in rows matching
the parent compute_cols() condition.
c_glue(cols, position, glue_col = NULL, text = NULL, separator = NULL)c_glue(cols, position, glue_col = NULL, text = NULL, separator = NULL)
cols |
Tidyselect expression for the target columns
(e.g., |
position |
Character. Concatenation side: |
glue_col |
Optional. Unquoted column name whose formatted value is
concatenated onto the target cells. The column may be hidden (not in the
visible column list). Mutually exclusive with |
text |
Optional. A single literal character string to concatenate onto
the target cells. Mutually exclusive with |
separator |
Character string inserted between the existing cell text and
the glued value when both sides are non-empty. Defaults to |
Must be called inside compute_cols().
Constraints:
Exactly one of glue_col or text must be provided.
cols resolves only visible report columns via tidyselect.
glue_col can reference any data column, including hidden ones.
glue_col must not overlap with cols.
Behavior:
When the glue value (from glue_col or text) is empty or NA,
the action is silently skipped for that row/cell.
When a target cell was suppressed by deduplication (dedupe = TRUE
on that column), the glue is silently skipped to preserve the visual
suppression of repeated values.
When a target cell is suppressed by a concurrent c_merge() action
(i.e., it is a non-leader merged cell), the glue is silently skipped.
The merge leader cell is glued normally when c_glue() targets a
column involved in c_merge() as the first column.
Multiple c_glue() calls on the same column accumulate in call order.
Interaction with other actions:
c_style(): Fully compatible — styling and text modification are independent.
c_merge(): Compatible. Glue is processed after merge in the renderer.
Non-leader (suppressed) merge cells are skipped; the merge-leader cell is
glued normally.
c_addrow(): Stackable — when used together in the same compute_cols(),
c_addrow() sees glued values. This allows building compound cell values
(e.g., "PARAM: VISIT") before using them in inserted rows.
c_pageBreak(): Fully compatible.
Stackable Actions:
Actions within a single compute_cols() call execute sequentially in the order
specified. This means c_glue() modifications are visible to subsequent c_addrow()
actions in the same call, enabling complex multi-step transformations.
Quosure-style marker (internal use within compute_cols())
compute_cols(), c_style(), c_merge(), c_addrow()
## Not run: # Append a unit from a hidden column (e.g. unit_col is not in spec cols) spec <- compute_cols(spec, !is.na(value), c_glue(value, "after", glue_col = unit, separator = " ")) # Prepend a literal marker to a label column spec <- compute_cols(spec, is_total, c_glue(label, "before", text = ">> ")) # Combine with c_style() — independent operations spec <- compute_cols(spec, firstOf(group), c_glue(label, "before", text = "> "), c_style(label, styleRef = "bold")) # Stackable with c_addrow() — addrow sees glued values spec <- compute_cols(spec, PARAM == "ALT", c_glue(PARAM, "after", glue_col = VISIT, separator = ": "), c_addrow("above", value_from = PARAM) # Uses "ALT: Week 2" ) ## End(Not run)## Not run: # Append a unit from a hidden column (e.g. unit_col is not in spec cols) spec <- compute_cols(spec, !is.na(value), c_glue(value, "after", glue_col = unit, separator = " ")) # Prepend a literal marker to a label column spec <- compute_cols(spec, is_total, c_glue(label, "before", text = ">> ")) # Combine with c_style() — independent operations spec <- compute_cols(spec, firstOf(group), c_glue(label, "before", text = "> "), c_style(label, styleRef = "bold")) # Stackable with c_addrow() — addrow sees glued values spec <- compute_cols(spec, PARAM == "ALT", c_glue(PARAM, "after", glue_col = VISIT, separator = ": "), c_addrow("above", value_from = PARAM) # Uses "ALT: Week 2" ) ## End(Not run)
Declares adjacent columns to be merged in rows matching the parent
compute_cols() condition. Merged columns appear as a single spanned cell.
c_merge(cols, styleRef = NULL)c_merge(cols, styleRef = NULL)
cols |
Tidyselect expression for column selection. Must resolve to at least 2 columns that are consecutive in the report column order. |
styleRef |
Character vector or result of |
Must be called inside compute_cols(). Columns must be adjacent in the
final report column order.
Quosure structure (internal use within compute_cols())
compute_cols() for conditional row actions, c_style(), c_addrow() for other action types
Validation:
Immediate: columns exist and are consecutive (error if not)
Deferred: overlapping merge ranges from multiple compute_cols() calls
(warning if resolvable, error if ambiguous)
Behavior:
Multiple merge actions in one row: all applied if non-overlapping
Overlapping merges from different compute_cols() blocks: raises warning/error
## Not run: spec <- create_table(mtcars) |> add_style("group_header", s_table_style(background_color = "#D9D9D9")) # Merge multiple columns for group header spec <- compute_cols(spec, group == "A", c_merge(c(col1, col2, col3), styleRef = "group_header")) # Merge without style spec <- compute_cols(spec, group == "B", c_merge(c(disp, hp))) ## End(Not run)## Not run: spec <- create_table(mtcars) |> add_style("group_header", s_table_style(background_color = "#D9D9D9")) # Merge multiple columns for group header spec <- compute_cols(spec, group == "A", c_merge(c(col1, col2, col3), styleRef = "group_header")) # Merge without style spec <- compute_cols(spec, group == "B", c_merge(c(disp, hp))) ## End(Not run)
Used inside compute_cols() to signal the renderer to start a new page
at every row matching the condition. Takes no arguments.
c_pageBreak()c_pageBreak()
Action marker (internal use within compute_cols())
compute_cols(), c_style(), c_addrow(), c_merge()
## Not run: data <- data.frame( group = c("A", "A", "B", "B", "C"), value = c(1, 2, 3, 4, 5) ) # Force a new page at the start of each group spec <- create_table(data) |> compute_cols(firstOf(group), c_pageBreak()) ## End(Not run)## Not run: data <- data.frame( group = c("A", "A", "B", "B", "C"), value = c(1, 2, 3, 4, 5) ) # Force a new page at the start of each group spec <- create_table(data) |> compute_cols(firstOf(group), c_pageBreak()) ## End(Not run)
Declares a style or combination of styles to be applied to specified columns
in rows matching the parent compute_cols() condition.
c_style(cols, styleRef)c_style(cols, styleRef)
cols |
Tidyselect expression for column selection
(e.g., |
styleRef |
Character. Name of the style to apply (defined via |
Must be called inside compute_cols(). Columns are resolved using
tidyselect syntax against the table data.
Quosure structure (internal use within compute_cols())
compute_cols() for conditional row actions, c_merge(), c_addrow() for other action types
Behavior:
Same column styled multiple times in one row: last style wins, warning issued
Same column styled from different compute_cols() calls on same row:
automatic style combination (merged via create_report())
Multiple columns in one call: all receive the same style(s)
Style Combination:
Use f_combine("style1", "style2") to apply multiple styles together
During create_report(), combined styles are consolidated into a single hash
Consolidation only happens for new specs (not pre-processed reports)
## Not run: spec <- create_table(mtcars) |> add_style("bold", s_font(bold = TRUE)) |> add_style("red", s_font(color = "red")) # Single style on one column spec <- compute_cols(spec, cyl == 6, c_style(mpg, styleRef = "bold")) # Single style on multiple columns spec <- compute_cols(spec, hp > 100, c_style(c(mpg, wt), styleRef = "red")) # Combined styles on columns spec <- compute_cols(spec, cyl == 8, c_style(mpg, styleRef = f_combine("bold", "red"))) ## End(Not run)## Not run: spec <- create_table(mtcars) |> add_style("bold", s_font(bold = TRUE)) |> add_style("red", s_font(color = "red")) # Single style on one column spec <- compute_cols(spec, cyl == 6, c_style(mpg, styleRef = "bold")) # Single style on multiple columns spec <- compute_cols(spec, hp > 100, c_style(c(mpg, wt), styleRef = "red")) # Combined styles on columns spec <- compute_cols(spec, cyl == 8, c_style(mpg, styleRef = f_combine("bold", "red"))) ## End(Not run)
Removes two categories of stale files from a meta folder:
Obsolete spec JSONs - older versions of a document when
multiple spec JSONs exist for the same doc_file. Only the
most-recent spec per document is kept.
Orphaned data JSONs - data JSON files that are no longer referenced by any surviving spec JSON.
clean_reports( meta_dir = tfl_get_option("meta_directory"), keep_versions = 1L, dry_run = TRUE )clean_reports( meta_dir = tfl_get_option("meta_directory"), keep_versions = 1L, dry_run = TRUE )
meta_dir |
Character string. Path to the meta folder. Defaults to
|
keep_versions |
Integer. Number of most-recent spec versions to keep
per document. Default |
dry_run |
Logical. If |
By default the function runs in dry-run mode and only reports what
would be deleted. Pass dry_run = FALSE to actually delete files.
Invisibly returns a list with elements obsolete_specs,
orphaned_data, and deleted (character vectors of filenames).
## Not run: # Preview what would be removed clean_reports("path/to/meta") # Actually delete, keeping 1 version per document clean_reports("path/to/meta", dry_run = FALSE) # Keep 2 versions per document (latest + one rollback) clean_reports("path/to/meta", keep_versions = 2, dry_run = FALSE) ## End(Not run)## Not run: # Preview what would be removed clean_reports("path/to/meta") # Actually delete, keeping 1 version per document clean_reports("path/to/meta", dry_run = FALSE) # Keep 2 versions per document (latest + one rollback) clean_reports("path/to/meta", keep_versions = 2, dry_run = FALSE) ## End(Not run)
Declares a set of styling, merging, and row insertion actions to be applied
to rows matching a condition. Actions are captured as unevaluated expressions
and evaluated later during create_report(). Supports complex conditions using
data columns and helper functions.
compute_cols(spec, cond, ...)compute_cols(spec, cond, ...)
spec |
A TFL_spec object (must have docType = "Table") |
cond |
An unquoted logical expression to be evaluated in the data environment. Can reference:
Must return a logical vector of length equal to |
... |
Action function calls: |
Execution Timeline:
compute_cols() captures condition and actions (no evaluation)
Appends to spec$.metadata$compute_cols list
During create_report(), conditions are evaluated and matched rows identified
Actions are applied to matching rows (styling, merging, row insertion)
StyleRows are serialized to JSON
Constraints:
Only allowed for docType = "Table"
Multiple compute_cols() calls accumulate on the same spec
Actions on the same row from different compute_cols() blocks are aggregated
Conditions must be deterministic (no NA values allowed)
Action Functions (used inside compute_cols()):
c_style(cols, styleRef): Apply style(s) to columns in matching rows
c_merge(cols, styleRef = NULL): Merge adjacent columns in matching rows
c_addrow(pos, value_from = NULL, styleRef = NULL): Insert row above/below matching rows
c_pageBreak(): Insert a page break at the matching row (no args)
c_glue(cols, position, glue_col = NULL, text = NULL, separator = NULL): Concatenate a data column value or literal text to matching cell text
c_clear(cols): Clear the display text of matching cells (render as blank)
Modified spec object with appended action metadata in spec$.metadata$compute_cols.
Invisibly returns the updated spec to enable piping workflows.
c_style(), c_merge(), c_addrow() for action functions used within compute_cols()
## Not run: spec <- create_table(mtcars) spec <- add_style(spec, id = "bold", s_font(bold = TRUE)) spec <- add_style(spec, id = "red", s_font(color = "red")) spec <- add_style(spec, id = "highlight", s_table_style(background_color = "yellow")) # Style columns in rows where cyl is first occurrence spec <- compute_cols(spec, firstOf(cyl), c_style(c(mpg, hp), styleRef = "bold")) # Style and merge columns in rows with high hp spec <- compute_cols(spec, hp > 200, c_style(hp, styleRef = "red"), c_merge(c(wt, qsec), styleRef = "highlight") ) # Add empty separator row above first occurrence spec <- compute_cols(spec, firstOf(cyl), c_addrow(pos = "above")) # Add row with content from a column spec <- compute_cols(spec, lastOf(cyl), c_addrow(pos = "below", value_from = "mpg")) ## End(Not run)## Not run: spec <- create_table(mtcars) spec <- add_style(spec, id = "bold", s_font(bold = TRUE)) spec <- add_style(spec, id = "red", s_font(color = "red")) spec <- add_style(spec, id = "highlight", s_table_style(background_color = "yellow")) # Style columns in rows where cyl is first occurrence spec <- compute_cols(spec, firstOf(cyl), c_style(c(mpg, hp), styleRef = "bold")) # Style and merge columns in rows with high hp spec <- compute_cols(spec, hp > 200, c_style(hp, styleRef = "red"), c_merge(c(wt, qsec), styleRef = "highlight") ) # Add empty separator row above first occurrence spec <- compute_cols(spec, firstOf(cyl), c_addrow(pos = "above")) # Add row with content from a column spec <- compute_cols(spec, lastOf(cyl), c_addrow(pos = "below", value_from = "mpg")) ## End(Not run)
Create and initialize a TFL specification for embedding a figure. Accepts either a file path to an existing image or a ggplot2 object that is rendered automatically to a temporary SVG file.
create_figure(plot_or_path, dpi = 300L)create_figure(plot_or_path, dpi = 300L)
plot_or_path |
One of:
|
dpi |
Integer. Resolution (dots per inch) when |
When a ggplot2 object is passed:
The plot is rendered via ggplot2::ggsave() to a temporary file in
tempdir().
The temporary file path is stored in spec$.metadata$filePath.
save_report() copies the file (prefixed with dataRef) into
metaPath, where the C++ renderer reads it.
The temporary file persists for the duration of the R session.
The C++ renderer natively supports .png, .jpeg/.jpg, and .svg
formats.
A TFL_spec object with docType = "Figure".
create_table(), create_text(), set_document()
## Not run: ## From file path (existing behaviour) spec <- create_figure("inst/images/example.png") ## From a ggplot2 object library(ggplot2) p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() spec <- create_figure(p) ## Control figure defaults via options tfl_set_options(figureWidth = "8in", figureHeight = "5in", figureDevice = "svg") spec <- create_figure(p, dpi = 150) ## Override per figure spec <- create_figure(p) |> set_document(figureDevice = "jpeg", figureScaleMode = "fitWidth") ## Full pipeline spec <- create_figure(p) |> add_title("Weight vs MPG") |> add_footnote("Source: Motor Trend, 1974.") report <- create_report(spec) write_doc(report, name = "fig01", outDir = "output", metaPath = tempdir()) ## End(Not run)## Not run: ## From file path (existing behaviour) spec <- create_figure("inst/images/example.png") ## From a ggplot2 object library(ggplot2) p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() spec <- create_figure(p) ## Control figure defaults via options tfl_set_options(figureWidth = "8in", figureHeight = "5in", figureDevice = "svg") spec <- create_figure(p, dpi = 150) ## Override per figure spec <- create_figure(p) |> set_document(figureDevice = "jpeg", figureScaleMode = "fitWidth") ## Full pipeline spec <- create_figure(p) |> add_title("Weight vs MPG") |> add_footnote("Source: Motor Trend, 1974.") report <- create_report(spec) write_doc(report, name = "fig01", outDir = "output", metaPath = tempdir()) ## End(Not run)
This function takes multiple TFL specification objects and/or previously created TFL report objects and combines them into a single report object matching the spec_schema_v2 structure. Each spec is keyed by a combination of its variable name and metadata hash (for direct specs) or preserves original keys (for specs from reports).
create_report(...)create_report(...)
... |
One or more objects of class
|
The function performs the following operations:
Flattens all inputs (expands list arguments and extracts specs
from TFL_report objects).
Auto-disambiguates duplicate keys among newly-added specs by
appending a numeric suffix (_2, _3, ...) to the name basis;
duplicate keys originating from TFL_report arguments still
trigger a hard error.
Consolidates styles within newly-added TFL_spec objects only
(specs from TFL_report are already consolidated).
Assigns a global docOrder integer (1, 2, 3, ...) based on final position.
Preserves existing dataRef values and warns if duplicates detected.
Returns a named list keyed by <variable_name>_<hash> or original report keys.
A named list where each element is a TFL_spec object,
keyed by the pattern <variable_name>_<hash> for direct specs, or
original keys for specs extracted from input reports.
Result has class TFL_report.
## Not run: spec1 <- create_table(mtcars) spec2 <- create_text() final_report <- create_report(spec1, spec2) # Combining with a previous report spec3 <- create_figure("path/to/image.png") combined <- create_report(final_report, spec3) # Passing a named list of specs out <- list(t1 = spec1, t2 = spec2) report_from_list <- create_report(out) ## End(Not run)## Not run: spec1 <- create_table(mtcars) spec2 <- create_text() final_report <- create_report(spec1, spec2) # Combining with a previous report spec3 <- create_figure("path/to/image.png") combined <- create_report(final_report, spec3) # Passing a named list of specs out <- list(t1 = spec1, t2 = spec2) report_from_list <- create_report(out) ## End(Not run)
Create and initialize a TFL specification for tabular output. This wrapper
captures the tidyselect cols expression and forwards it to the internal
initializer. Use create_table() when you have a data frame that should be
rendered as a table.
create_table(data = NULL, cols = everything())create_table(data = NULL, cols = everything())
data |
A data frame to build the table from (required). |
cols |
Tidyselect expression indicating which columns from |
Column Width Initialization:
Initial column widths are automatically calculated based on data values and their types and sum to 100%.
To lock specific columns and trigger automatic recalculation of others, use define_cols() with
the colWidth parameter (when autoColWidth = TRUE in the tfl_options, the default).
Example workflow:
Create table: widths auto-distributed
define_cols(id, colWidth="20%"): locks id at 20%, others recalculated to fill 80% keeping initially detected proportions
define_cols(age, colWidth="2cm"): locks age at fixed 2cm width, other relative columns recalculated to fill remaining space
A TFL_spec object with docType = "Table".
create_text(), create_figure(), define_cols(),
add_title(), create_report()
## Not run: ## Basic usage with the built-in `mtcars` dataset spec <- create_table(mtcars) ## Select specific columns using tidyselect spec <- create_table(mtcars, cols = c(cyl, mpg, hp)) ## or using ranges: spec <- create_table(mtcars, cyl:hp) ## or by excluding columns spec <- create_table(mtcars, cols = -c(gear, carb)) ## or simple by names spec <- create_table(mtcars, cols = c("cyl", "mpg", "hp")) ## End(Not run)## Not run: ## Basic usage with the built-in `mtcars` dataset spec <- create_table(mtcars) ## Select specific columns using tidyselect spec <- create_table(mtcars, cols = c(cyl, mpg, hp)) ## or using ranges: spec <- create_table(mtcars, cyl:hp) ## or by excluding columns spec <- create_table(mtcars, cols = -c(gear, carb)) ## or simple by names spec <- create_table(mtcars, cols = c("cyl", "mpg", "hp")) ## End(Not run)
Create and initialize a TFL specification for narrative (text) documents.
This is a user-facing wrapper around the internal .tfl_init() initializer
and provides a clear, intention-revealing name for creating text-only
specifications. Text documents do not accept data and will have
docType = "Text" set on the resulting spec.
create_text()create_text()
A TFL_spec object with docType = "Text".
create_table(), create_figure(), add_body_text()
## Not run: # Create a text-only spec and add narrative content spec <- create_text() |> add_title("Listing of Adverse Events") |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported during the study.") ## End(Not run)## Not run: # Create a text-only spec and add narrative content spec <- create_text() |> add_title("Listing of Adverse Events") |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported during the study.") ## End(Not run)
Modify properties of existing columns. Can modify single column or batch update
multiple columns. All parameters support 1-to-many recycling: provide a single value
to apply to all columns, or a vector matching the length of cols for one-to-one mapping.
Multiple calls merge with last-win strategy.
define_cols( spec, cols, label = NULL, isID = NULL, isVisible = NULL, isGrouping = NULL, isPaging = NULL, labelStyleRef = NULL, isColBreak = NULL, dedupe = NULL, blankAfter = NULL, type = NULL, format = NULL, missings = NULL, colWidth = NULL, valueStyleRef = NULL )define_cols( spec, cols, label = NULL, isID = NULL, isVisible = NULL, isGrouping = NULL, isPaging = NULL, labelStyleRef = NULL, isColBreak = NULL, dedupe = NULL, blankAfter = NULL, type = NULL, format = NULL, missings = NULL, colWidth = NULL, valueStyleRef = NULL )
spec |
TFL spec object (must be initialized with |
cols |
Columns to modify using tidyselect syntax. Accepts:
|
label |
Column label (length 1 or length of cols; |
isID |
Whether column is identifier (length 1 or length of cols; |
isVisible |
Whether column is visible in report output (length 1 or length of cols;
|
isGrouping |
Whether column defines groups (length 1 or length of cols; |
isPaging |
Whether column defines pages (length 1 or length of cols; |
labelStyleRef |
List of style names to be applied. Provided styles will be merged with last-win strategy for report.
Can be: single string (recycled), character vector from |
isColBreak |
Whether column triggers page break (length 1 or length of cols; |
dedupe |
Whether to deduplicate values (length 1 or length of cols; |
blankAfter |
Whether to add blank after value change (length 1 or length of cols; |
type |
Data type for column format: "string" or "numeric" (length 1 or length of cols;
|
format |
Format string for numeric data (sprintf style), e.g. "%.1f" (length 1 or length of cols;
|
missings |
How to display missing values in columns (length 1 or length of cols;
|
colWidth |
Column width, e.g. "2in", "5cm", "20%" (length 1 or length of cols;
|
valueStyleRef |
Style names to apply to cell values. Provided styles will be merged with last-win strategy for report.
Use |
Column Width Management:
Widths are managed through a LOCKED/UNLOCKED/VISIBLE partitioning system:
VISIBLE columns: included in width calculations (isVisible != FALSE)
LOCKED columns: exact width specified via colWidth parameter (any unit: %, cm, in, mm, pt)
UNLOCKED columns: automatically recalculated to fill available space
INVISIBLE columns: hidden from output (isVisible = FALSE), assigned width "0.0cm", excluded from calculations
When colWidth is specified (or visibility changes), columns are marked as LOCKED and remaining
UNLOCKED columns are automatically recalculated (if autoColWidth = TRUE, the default):
Only VISIBLE UNLOCKED columns participate in recalculation
Locked columns (any unit) maintain their exact specified width
Unlocked visible columns normalize proportionally to fill remaining available space
All visible columns' widths sum to 100% with 1 decimal place precision
Invisible columns stay at "0.0cm" and don't affect other widths
To disable auto-recalculation, use tfl_set_options(autoColWidth = FALSE).
Invisible Column Behavior:
isVisible = FALSE automatically sets colWidth = "0.0cm"
Cannot set colWidth on invisible columns (raises error)
Invisible columns are excluded from width recalculation entirely
Shown with "hidden" flag in spec preview
Updated spec object
## Not run: data <- data.frame(id = 1:10, age = rnorm(10, 45, 10), group = rep(c("A", "B"), 5)) # Single column with format spec <- create_table(data) |> define_cols("age", label = "Age (years)", type = "numeric", format = "%.1f", colWidth = "10%" ) # Batch update with single value spec <- create_table(data) |> define_cols(c("id", "age", "group"), isVisible = TRUE # Applied to all three ) # Batch update with mapped values spec <- create_table(data) |> define_cols(c("id", "age"), label = c("Subject ID", "Age (years)"), # One-to-one mapping isID = c(TRUE, FALSE) ) # Batch format update with mixed recycling spec <- create_table(data) |> define_cols(c("id", "age"), type = "numeric", # Single value recycled to both columns colWidth = c("10%", "15%") # Different widths for each column ) # Multiple calls merge spec <- create_table(data) |> define_cols("age", label = "Age", type = "numeric", format = "%.0f" ) |> define_cols("age", label = "Age (years)", # Overrides previous label colWidth = "15%" # Merges with format, keeping type and format ) # Apply style references - single value recycled to all columns spec <- create_table(data) |> define_cols(c("age", "id"), labelStyleRef = f_combine("label_style", "emphasis") ) # Apply different styles combinations to different columns spec <- create_table(data) |> define_cols(c("id", "age", "group"), labelStyleRef = c( f_combine("id_label", "key"), f_combine("numeric_label", "emphasis"), f_combine("categorical_label") ) ) # Column width auto-recalculation (when autoColWidth = TRUE, the default): # Initial widths are automatically distributed (e.g., id=33.3%, age=33.3%, group=33.4%) spec <- create_table(data) |> define_cols("id", colWidth = "20%") # Lock id at 20% # Result: id=20%, age and group auto-recalculate to fill remaining 80% # # Multiple colWidth calls preserve previous locks: spec <- create_table(data) |> define_cols("id", colWidth = "20%") |> define_cols("age", colWidth = "15%") # Result: id=20% (locked), age=15% (locked), group=65% (fills remaining) # Disable auto-recalculation to manage widths manually: tfl_set_options(autoColWidth = FALSE) # Turn off auto-recalculation spec <- create_table(data) |> define_cols(c("id", "age", "group"), colWidth = c("25%", "30%", "45%")) # Widths stay exactly as specified, no automatic recalculation tfl_set_options(autoColWidth = TRUE) # Re-enable (restore default) # Using tidyselect helpers spec <- create_table(data) |> define_cols(starts_with("age"), label = "Age-related metric", type = "numeric", format = "%.1f" ) # Using negation with tidyselect spec <- create_table(data) |> define_cols(-id, # Exclude id column isVisible = TRUE ) # Using column range spec <- create_table(data) |> define_cols(age:group, # All columns from age to group labelStyleRef = "emphasis" ) # Hide column from output while keeping data for conditional logic spec <- create_table(data) |> define_cols("age", isVisible = FALSE # Automatically sets width to "0.0cm" ) # Result: age column hidden, other columns recalculated to sum to 100% ## End(Not run)## Not run: data <- data.frame(id = 1:10, age = rnorm(10, 45, 10), group = rep(c("A", "B"), 5)) # Single column with format spec <- create_table(data) |> define_cols("age", label = "Age (years)", type = "numeric", format = "%.1f", colWidth = "10%" ) # Batch update with single value spec <- create_table(data) |> define_cols(c("id", "age", "group"), isVisible = TRUE # Applied to all three ) # Batch update with mapped values spec <- create_table(data) |> define_cols(c("id", "age"), label = c("Subject ID", "Age (years)"), # One-to-one mapping isID = c(TRUE, FALSE) ) # Batch format update with mixed recycling spec <- create_table(data) |> define_cols(c("id", "age"), type = "numeric", # Single value recycled to both columns colWidth = c("10%", "15%") # Different widths for each column ) # Multiple calls merge spec <- create_table(data) |> define_cols("age", label = "Age", type = "numeric", format = "%.0f" ) |> define_cols("age", label = "Age (years)", # Overrides previous label colWidth = "15%" # Merges with format, keeping type and format ) # Apply style references - single value recycled to all columns spec <- create_table(data) |> define_cols(c("age", "id"), labelStyleRef = f_combine("label_style", "emphasis") ) # Apply different styles combinations to different columns spec <- create_table(data) |> define_cols(c("id", "age", "group"), labelStyleRef = c( f_combine("id_label", "key"), f_combine("numeric_label", "emphasis"), f_combine("categorical_label") ) ) # Column width auto-recalculation (when autoColWidth = TRUE, the default): # Initial widths are automatically distributed (e.g., id=33.3%, age=33.3%, group=33.4%) spec <- create_table(data) |> define_cols("id", colWidth = "20%") # Lock id at 20% # Result: id=20%, age and group auto-recalculate to fill remaining 80% # # Multiple colWidth calls preserve previous locks: spec <- create_table(data) |> define_cols("id", colWidth = "20%") |> define_cols("age", colWidth = "15%") # Result: id=20% (locked), age=15% (locked), group=65% (fills remaining) # Disable auto-recalculation to manage widths manually: tfl_set_options(autoColWidth = FALSE) # Turn off auto-recalculation spec <- create_table(data) |> define_cols(c("id", "age", "group"), colWidth = c("25%", "30%", "45%")) # Widths stay exactly as specified, no automatic recalculation tfl_set_options(autoColWidth = TRUE) # Re-enable (restore default) # Using tidyselect helpers spec <- create_table(data) |> define_cols(starts_with("age"), label = "Age-related metric", type = "numeric", format = "%.1f" ) # Using negation with tidyselect spec <- create_table(data) |> define_cols(-id, # Exclude id column isVisible = TRUE ) # Using column range spec <- create_table(data) |> define_cols(age:group, # All columns from age to group labelStyleRef = "emphasis" ) # Hide column from output while keeping data for conditional logic spec <- create_table(data) |> define_cols("age", isVisible = FALSE # Automatically sets width to "0.0cm" ) # Result: age column hidden, other columns recalculated to sum to 100% ## End(Not run)
Helper function to group multiple style names together for explicit application
to columns or elements. Useful when using define_cols or other
functions with multiple columns and you want to either:
Recycle the same group of styles to all columns:
labelStyleRef = f_combine("style1", "style2")
Create explicit one-to-one mappings:
labelStyleRef = c(f_combine("s1", "s2"), f_combine("s3"), "style4")
f_combine(...)f_combine(...)
... |
Character strings representing style names to combine
|
Character vector with class "tfl_style_combine" containing all provided style names.
This special class signals to style resolution functions that these styles should be
applied together as a group (merged with last-win strategy during create_report()).
## Not run: # Combine styles for recycling to all columns styles <- f_combine("label_style", "emphasis", "bold") # Use in define_cols for one-to-one mapping spec <- create_table(data) |> define_cols(c("id", "age"), labelStyleRef = c( f_combine("id_label", "key"), f_combine("numeric_label") ) ) ## End(Not run)## Not run: # Combine styles for recycling to all columns styles <- f_combine("label_style", "emphasis", "bold") # Use in define_cols for one-to-one mapping spec <- create_table(data) |> define_cols(c("id", "age"), labelStyleRef = c( f_combine("id_label", "key"), f_combine("numeric_label") ) ) ## End(Not run)
Scans a meta folder produced by save_report and returns a
summary data frame with one row per spec JSON file. Uses _index.json
when available (fast); falls back to scanning every JSON file otherwise.
list_reports( meta_dir = tfl_get_option("meta_directory"), sort_by = c("datetime", "doc_file", "spec_file") )list_reports( meta_dir = tfl_get_option("meta_directory"), sort_by = c("datetime", "doc_file", "spec_file") )
meta_dir |
Character string. Path to the meta folder. Defaults to
|
sort_by |
Character string. Column to sort by: |
A data frame with columns:
Hash-named spec JSON filename.
Target DOCX filename stored at save time.
ISO-8601 timestamp of when save_report() was called.
Number of TFL specs inside the JSON.
Logical - TRUE for the most-recent entry per
doc_file; older entries are FALSE (obsolete candidates).
Character vector of data JSON base-names referenced by
this spec (without .json extension).
When no spec JSONs are found in meta_dir, returns
invisible(empty_data_frame) and prints an informational message.
## Not run: df <- list_reports("path/to/meta") print(df[df$is_latest, c("doc_file", "datetime", "spec_file")]) ## End(Not run)## Not run: df <- list_reports("path/to/meta") print(df[df$is_latest, c("doc_file", "datetime", "spec_file")]) ## End(Not run)
This function can only be used inside p_page.
p_margins( top = NULL, bottom = NULL, left = NULL, right = NULL, header = NULL, footer = NULL )p_margins( top = NULL, bottom = NULL, left = NULL, right = NULL, header = NULL, footer = NULL )
top |
Top margin, e.g. "25mm" |
bottom |
Bottom margin, e.g. "25mm" |
left |
Left margin, e.g. "20mm" |
right |
Right margin, e.g. "20mm" |
header |
Header margin, e.g. "12mm" |
footer |
Footer margin, e.g. "12mm" |
A margins specification object
## Not run: spec <- create_text() |> set_page_style( page = p_page( size = "A4", orientation = "landscape", margins = p_margins( top = "25mm", bottom = "25mm", left = "20mm", right = "20mm", header = "12mm", footer = "12mm" ) ) ) ## End(Not run)## Not run: spec <- create_text() |> set_page_style( page = p_page( size = "A4", orientation = "landscape", margins = p_margins( top = "25mm", bottom = "25mm", left = "20mm", right = "20mm", header = "12mm", footer = "12mm" ) ) ) ## End(Not run)
This function can only be used inside set_page_style.
p_page(size = NULL, orientation = NULL, margins = NULL)p_page(size = NULL, orientation = NULL, margins = NULL)
size |
Page size: "A4", "A3", "Letter", "Legal", "Executive" |
orientation |
Page orientation: "portrait" or "landscape" |
margins |
Margins object created with |
A page specification object
## Not run: spec <- create_text() |> set_page_style( docTemplate = "CRO Example_default", page = p_page( size = "A4", orientation = "landscape", margins = p_margins( top = "25mm", bottom = "25mm", left = "20mm", right = "20mm", header = "12mm", footer = "12mm" ) ) ) ## End(Not run)## Not run: spec <- create_text() |> set_page_style( docTemplate = "CRO Example_default", page = p_page( size = "A4", orientation = "landscape", margins = p_margins( top = "25mm", bottom = "25mm", left = "20mm", right = "20mm", header = "12mm", footer = "12mm" ) ) ) ## End(Not run)
Provides a comprehensive, human-readable overview of a TFL specification object with formatted tables, colors, and legends. Shows document metadata, columns with types and formats, titles, headers, footers, and sample data.
## S3 method for class 'TFL_spec' print( x, layout = c("full", "compact"), width = getOption("width", 80L), colors = TRUE, ... )## S3 method for class 'TFL_spec' print( x, layout = c("full", "compact"), width = getOption("width", 80L), colors = TRUE, ... )
x |
A |
layout |
Display mode as a character string:
|
width |
Integer. Terminal width for text wrapping (default: from |
colors |
Logical. If |
... |
Additional arguments passed to print methods (ignored). |
The full layout displays:
Document type and data availability
Summary counts (columns, titles, headers, footers, etc.)
Page settings (size, orientation)
Headers and footers content
Titles, subtitles, and footnotes
Column metadata table (Name, Label, Type, Format, Missings, Width, Flags, Styles)
Flag legend explaining special column properties
Body text content
Sample data (first 3 rows)
Flags Legend:
* = ID column (primary identifier)
x = Hidden column (not visible in output)
# = Grouping column (used for grouping rows)
> = Page break (trigger page break)
v = Column break (trigger column break)
d = Deduplicate (remove duplicate values)
_ = Blank after (insert blank row after value change)
The spec object (invisibly). This allows print to be called on a spec object for side effects while preserving the spec in piped workflows.
## Not run: data <- data.frame(id = 1:10, age = rnorm(10, 45, 10), group = rep(c("A", "B"), 5)) spec <- create_table(data) |> add_title("Motor Trend Study") |> add_subtitle("Vehicle Performance Analysis") |> add_header("ABC Research", "Confidential", "2024") |> add_footnote("Source: mtcars dataset") # Print with full details (calls print.TFL_spec) print(spec) # Compact view print(spec, layout = "compact") # Without colors print(spec, colors = FALSE) ## End(Not run)## Not run: data <- data.frame(id = 1:10, age = rnorm(10, 45, 10), group = rep(c("A", "B"), 5)) spec <- create_table(data) |> add_title("Motor Trend Study") |> add_subtitle("Vehicle Performance Analysis") |> add_header("ABC Research", "Confidential", "2024") |> add_footnote("Source: mtcars dataset") # Print with full details (calls print.TFL_spec) print(spec) # Compact view print(spec, layout = "compact") # Without colors print(spec, colors = FALSE) ## End(Not run)
Re-renders a DOCX document entirely from JSON files stored in the meta folder - no R spec objects or data frames required. Useful for reproducing outputs after code changes or on a different machine.
replay_report( spec_json, meta_dir = tfl_get_option("meta_directory"), output_path = NULL, template_json = NULL, overrideTemplate = NULL, insertTOC = NULL, tocTitle = NULL, verbose = FALSE )replay_report( spec_json, meta_dir = tfl_get_option("meta_directory"), output_path = NULL, template_json = NULL, overrideTemplate = NULL, insertTOC = NULL, tocTitle = NULL, verbose = FALSE )
spec_json |
Character string or character vector. Either:
Multiple entries are allowed for merging several documents into one. |
meta_dir |
Character string or character vector. Path(s) to the meta
folder(s). Defaults to
Required when any |
output_path |
Character string. Override the output DOCX path. If
|
template_json |
Character string. Override the template JSON path.
If |
overrideTemplate |
Character string. A bundled template name
(e.g. |
insertTOC |
Logical. Insert a Table of Contents. |
tocTitle |
Character string. TOC heading text. |
verbose |
Logical. Print C++ pipeline diagnostics. Default |
When a single spec_json is provided the function behaves exactly
as before.
When a character vector of length > 1 is given, the specs from every
document are merged into one combined JSON and rendered into a single
DOCX file. output_path is required in this case.
Invisibly returns the path to the rendered DOCX file.
## Not run: # By doc name (uses latest spec) replay_report("test_01.docx", meta_dir = "path/to/meta") # By spec hash (exact version) replay_report("abc123def456.json", meta_dir = "path/to/meta") # Override output location replay_report("test_01.docx", meta_dir = "path/to/meta", output_path = "~/Desktop/test_01_replay.docx") # Merge two documents from the same meta folder replay_report( c("tables_01.docx", "listings_01.docx"), meta_dir = "path/to/meta", output_path = "output/combined.docx" ) # Merge documents from different meta folders replay_report( c("path/to/meta_a/abc123.json", "path/to/meta_b/def456.json"), output_path = "output/combined.docx" ) ## End(Not run)## Not run: # By doc name (uses latest spec) replay_report("test_01.docx", meta_dir = "path/to/meta") # By spec hash (exact version) replay_report("abc123def456.json", meta_dir = "path/to/meta") # Override output location replay_report("test_01.docx", meta_dir = "path/to/meta", output_path = "~/Desktop/test_01_replay.docx") # Merge two documents from the same meta folder replay_report( c("tables_01.docx", "listings_01.docx"), meta_dir = "path/to/meta", output_path = "output/combined.docx" ) # Merge documents from different meta folders replay_report( c("path/to/meta_a/abc123.json", "path/to/meta_b/def456.json"), output_path = "output/combined.docx" ) ## End(Not run)
Opens an interactive Shiny application for selecting, reordering, and replaying multiple saved reports into a single combined DOCX document. Reports can be loaded from one or more meta folders, reordered via drag-and-drop, and rendered with optional TOC settings.
run_replay_app(meta_dir = NULL, ...)run_replay_app(meta_dir = NULL, ...)
meta_dir |
Character string (optional). Default meta folder path
to pre-populate in the app. If |
... |
Additional arguments passed to |
This function requires the shiny, sortable, and
shinyFiles packages.
Invisibly returns the result of shiny::runApp().
list_reports(), replay_report(), clean_reports()
## Not run: run_replay_app() run_replay_app(meta_dir = "path/to/meta") ## End(Not run)## Not run: run_replay_app() run_replay_app(meta_dir = "path/to/meta") ## End(Not run)
Opens an interactive Shiny application for creating and editing ksTFL
styles templates that conform to styles_schema_v2.json. Templates can be
loaded from the bundled inst/templates/ directory or uploaded from disk,
then edited and downloaded as JSON for use with set_page_style() /
write_doc().
run_styles_editor(...)run_styles_editor(...)
... |
Additional arguments passed to |
This function requires the shiny package to be installed.
Invisibly returns the result of shiny::runApp().
tfl_list_templates(), set_page_style()
## Not run: run_styles_editor() run_styles_editor(launch.browser = TRUE) ## End(Not run)## Not run: run_styles_editor() run_styles_editor(launch.browser = TRUE) ## End(Not run)
This function can only be used inside s_borders.
s_border(color = NULL, width = NULL, line_style = NULL)s_border(color = NULL, width = NULL, line_style = NULL)
color |
Border color as hex (e.g., "#000000") or color name (e.g., "black", "red") |
width |
Border width, e.g. "1pt" |
line_style |
Line style: "single", "double", "dashed", "dotted", "thick", "none" |
A border specification object
## Not run: # Cell-level borders (inside s_table_style) spec <- create_text() |> add_style("my_style", s_table_style( borders = s_borders( bottom = s_border(color = "#000000", width = "2pt", line_style = "single") ) ) ) # Paragraph-level borders (inside s_paragraph) spec <- create_table(mtcars) |> add_style("para_underline", s_paragraph( borders = s_borders( bottom = s_border(width = "1pt") ) ) ) ## End(Not run)## Not run: # Cell-level borders (inside s_table_style) spec <- create_text() |> add_style("my_style", s_table_style( borders = s_borders( bottom = s_border(color = "#000000", width = "2pt", line_style = "single") ) ) ) # Paragraph-level borders (inside s_paragraph) spec <- create_table(mtcars) |> add_style("para_underline", s_paragraph( borders = s_borders( bottom = s_border(width = "1pt") ) ) ) ## End(Not run)
This function can be used inside s_table_style (cell-level borders)
or s_paragraph (paragraph-level borders).
s_borders(top = NULL, bottom = NULL, left = NULL, right = NULL)s_borders(top = NULL, bottom = NULL, left = NULL, right = NULL)
top |
Top border created with |
bottom |
Bottom border created with |
left |
Left border created with |
right |
Right border created with |
A borders specification object
## Not run: # Cell-level borders spec <- create_text() |> add_style("my_style", s_table_style( borders = s_borders( top = s_border(width = "1pt"), bottom = s_border(width = "2pt", line_style = "double") ) ) ) # Paragraph-level borders (border follows the text, not the cell edge) spec <- create_table(mtcars) |> add_style("span_underline", s_paragraph( alignment = "center", borders = s_borders( bottom = s_border(color = "#4472C4", width = "1pt") ) ) ) ## End(Not run)## Not run: # Cell-level borders spec <- create_text() |> add_style("my_style", s_table_style( borders = s_borders( top = s_border(width = "1pt"), bottom = s_border(width = "2pt", line_style = "double") ) ) ) # Paragraph-level borders (border follows the text, not the cell edge) spec <- create_table(mtcars) |> add_style("span_underline", s_paragraph( alignment = "center", borders = s_borders( bottom = s_border(color = "#4472C4", width = "1pt") ) ) ) ## End(Not run)
This function can only be used inside add_style.
s_font( font_name = NULL, font_size = NULL, bold = NULL, italic = NULL, underline = NULL, strikethrough = NULL, color = NULL, highlight = NULL )s_font( font_name = NULL, font_size = NULL, bold = NULL, italic = NULL, underline = NULL, strikethrough = NULL, color = NULL, highlight = NULL )
font_name |
Font family name. One of: "Arial", "Courier New", "Times New Roman", "Georgia", "Verdana", "Trebuchet MS", "Liberation Sans" |
font_size |
Font size with units, e.g. "12pt" |
bold |
Logical, whether text is bold |
italic |
Logical, whether text is italic |
underline |
Logical, whether text is underlined |
strikethrough |
Logical, whether text has strikethrough |
color |
Text color as hex (e.g., "#000000") or color name (e.g., "red", "blue") |
highlight |
Background highlight color as hex (e.g., "#FFFF00") or color name (e.g., "yellow") |
A font specification object (for internal use)
add_style() for applying styles, s_paragraph(), s_table_style() for other style components
## Not run: spec <- create_text() |> add_style("my_style", s_font(font_name = "Arial", font_size = "12pt", bold = TRUE) ) ## End(Not run)## Not run: spec <- create_text() |> add_style("my_style", s_font(font_name = "Arial", font_size = "12pt", bold = TRUE) ) ## End(Not run)
This function can only be used inside s_paragraph.
s_indents(left = NULL, right = NULL, first_line = NULL)s_indents(left = NULL, right = NULL, first_line = NULL)
left |
Left indent, e.g. "10mm" |
right |
Right indent, e.g. "10mm" |
first_line |
First line indent (negative for hanging), e.g. "-5mm" |
An indents specification object
## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( indents = s_indents(left = "10mm", first_line = "-5mm") ) ) ## End(Not run)## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( indents = s_indents(left = "10mm", first_line = "-5mm") ) ) ## End(Not run)
This function can only be used inside add_style.
s_paragraph( alignment = NULL, spacing = NULL, indents = NULL, word_style = NULL, borders = NULL )s_paragraph( alignment = NULL, spacing = NULL, indents = NULL, word_style = NULL, borders = NULL )
alignment |
Text alignment: "left", "right", "center", "justify", "distributed" |
spacing |
Spacing object created with |
indents |
Indents object created with |
word_style |
Base Word style to inherit from |
borders |
Borders object created with |
A paragraph specification object
add_style() for applying styles, s_spacing(), s_indents(), s_borders() for nested components,
s_font(), s_table_style() for other style components
## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( alignment = "center", spacing = s_spacing(before = "12pt", after = "6pt"), word_style = "Normal" ) ) # Paragraph with a bottom border (applied to the text, not the cell) spec <- create_table(mtcars) |> add_style("para_border", s_paragraph( alignment = "center", borders = s_borders( bottom = s_border(color = "#000000", width = "0.5pt", line_style = "single") ) ) ) ## End(Not run)## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( alignment = "center", spacing = s_spacing(before = "12pt", after = "6pt"), word_style = "Normal" ) ) # Paragraph with a bottom border (applied to the text, not the cell) spec <- create_table(mtcars) |> add_style("para_border", s_paragraph( alignment = "center", borders = s_borders( bottom = s_border(color = "#000000", width = "0.5pt", line_style = "single") ) ) ) ## End(Not run)
This function can only be used inside s_paragraph.
s_spacing(before = NULL, after = NULL, line_spacing = NULL)s_spacing(before = NULL, after = NULL, line_spacing = NULL)
before |
Space before paragraph, e.g. "6pt" |
after |
Space after paragraph, e.g. "6pt" |
line_spacing |
Line spacing multiplier, minimum 1 |
A spacing specification object
## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( alignment = "center", spacing = s_spacing(before = "12pt", after = "6pt") ) ) ## End(Not run)## Not run: spec <- create_text() |> add_style("my_style", s_paragraph( alignment = "center", spacing = s_spacing(before = "12pt", after = "6pt") ) ) ## End(Not run)
This function can only be used inside add_style.
s_table_style( background_color = NULL, row_height = NULL, topEmptyLine = NULL, bottomEmptyLine = NULL, vertical_alignment = NULL, text_orientation = NULL, borders = NULL )s_table_style( background_color = NULL, row_height = NULL, topEmptyLine = NULL, bottomEmptyLine = NULL, vertical_alignment = NULL, text_orientation = NULL, borders = NULL )
background_color |
Cell background color as hex code or color name |
row_height |
Row height, e.g. "15mm" or "auto" |
topEmptyLine |
Empty spacer row height after header, e.g. "6pt"; NULL disables it |
bottomEmptyLine |
Empty spacer row height before bottom border, e.g. "6pt"; NULL disables it |
vertical_alignment |
Vertical alignment: "top", "center", "bottom" |
text_orientation |
Text orientation: "horizontal", "vertical_90", "vertical_270" |
borders |
Borders object created with |
A table style specification object
add_style() for applying styles, s_borders(), s_border() for border components,
s_font(), s_paragraph() for other style components
## Not run: spec <- create_text() |> add_style("header_style", s_table_style( background_color = "#D9D9D9", vertical_alignment = "center", borders = s_borders( bottom = s_border(color = "#000000", width = "2pt") ) ) ) ## End(Not run)## Not run: spec <- create_text() |> add_style("header_style", s_table_style( background_color = "#D9D9D9", vertical_alignment = "center", borders = s_borders( bottom = s_border(color = "#000000", width = "2pt") ) ) ) ## End(Not run)
Serializes a TFL_report object to JSON format along with associated data files (for tables) or figure files (for figures). Validates the report structure, processes each specification by its docType, and writes all outputs to disk.
save_report( report, docFileName, outDir = NULL, metaPath = NULL, prettify = FALSE, insertTOC = NULL, tocTitle = NULL )save_report( report, docFileName, outDir = NULL, metaPath = NULL, prettify = FALSE, insertTOC = NULL, tocTitle = NULL )
report |
A TFL_report object (output from |
docFileName |
Character string. Name of the rendered document file that will be
created by the C++ renderer (e.g., "report.docx"). This value is stored in the
|
outDir |
Character string. Output directory where the C++ renderer will save
the rendered document. This path is stored in the |
metaPath |
Character string. Directory where this function will save the JSON spec
and associated data files. If not provided, a temporary directory is created.
Default: |
prettify |
Logical. If TRUE, format JSON output with indentation and line breaks for readability. Default: FALSE (compact format) |
insertTOC |
Logical. When |
tocTitle |
Character. Heading text placed above the TOC field on the TOC page.
Defaults to the |
The function performs the following steps:
Validates input is a TFL_report object
Serializes the report using serialize_spec() to validate against schema
Processes each specification by docType:
Text: Drops .metadata (no additional files needed)
Table: Extracts data, filters to included columns, saves as JSON
Figure: Copies image file with original extension preserved
Creates _metadata section with outDir and docFileName
Serializes the complete fixed object to JSON
Returns information about saved files
Error Conditions:
Report class is not TFL_report
Table/Figure spec has hasData=TRUE but no actual data available
dataRef has multiple entries (currently only single file references supported)
File I/O errors when writing JSON or copying files
Invisibly returns a list with:
spec_file: Name of the saved spec JSON file (hash-based filename)
datetime: Timestamp when the report was saved (ISO 8601 format)
metaPath: Directory where files were saved
## Not run: spec1 <- create_table(mtcars) spec2 <- create_text() report <- create_report(spec1, spec2) # Save with explicit parameters result <- save_report( report, docFileName = "report.docx", outDir = "/output/path", metaPath = "/meta/path" ) # Save with defaults (uses tempdir and tfl_options) result <- save_report(report, docFileName = "report.docx") cat("Spec saved as:", result$spec_file, "\n") cat("Saved to:", result$metaPath, "\n") # Generate a report with an auto-populated TOC page t1 <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> set_document(hasData = TRUE) t2 <- create_table(advs) |> add_title("Table 2: Vital Signs by Visit", toclevel = 1) |> add_subtitle("#ByGroup1", toclevel = 2) |> set_document(hasData = TRUE) report <- create_report(t1, t2) save_report( report, docFileName = "tables.docx", outDir = "output/", insertTOC = TRUE, tocTitle = "List of Tables" ) # Open tables.docx in Word, click the TOC placeholder, press F9 to populate it. ## End(Not run)## Not run: spec1 <- create_table(mtcars) spec2 <- create_text() report <- create_report(spec1, spec2) # Save with explicit parameters result <- save_report( report, docFileName = "report.docx", outDir = "/output/path", metaPath = "/meta/path" ) # Save with defaults (uses tempdir and tfl_options) result <- save_report(report, docFileName = "report.docx") cat("Spec saved as:", result$spec_file, "\n") cat("Saved to:", result$metaPath, "\n") # Generate a report with an auto-populated TOC page t1 <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) |> set_document(hasData = TRUE) t2 <- create_table(advs) |> add_title("Table 2: Vital Signs by Visit", toclevel = 1) |> add_subtitle("#ByGroup1", toclevel = 2) |> set_document(hasData = TRUE) report <- create_report(t1, t2) save_report( report, docFileName = "tables.docx", outDir = "output/", insertTOC = TRUE, tocTitle = "List of Tables" ) # Open tables.docx in Word, click the TOC placeholder, press F9 to populate it. ## End(Not run)
Define document-level properties. Multiple calls merge with last-win strategy.
Document type (docType) is set automatically by create_table(),
create_figure(), or create_text() and cannot be changed here. Global
document order (docOrder) is assigned by create_report().
set_document( spec, isContinues = NULL, continuousSection = NULL, contentWidth = NULL, footnotePlace = NULL, hasData = NULL, topEmptyLine = NULL, bottomEmptyLine = NULL, docTemplate = NULL, figureWidth = NULL, figureHeight = NULL, figureDevice = NULL, figureScaleMode = NULL )set_document( spec, isContinues = NULL, continuousSection = NULL, contentWidth = NULL, footnotePlace = NULL, hasData = NULL, topEmptyLine = NULL, bottomEmptyLine = NULL, docTemplate = NULL, figureWidth = NULL, figureHeight = NULL, figureDevice = NULL, figureScaleMode = NULL )
spec |
TFL spec object |
isContinues |
Logical. When |
continuousSection |
Logical. When |
contentWidth |
Width of content, e.g. |
footnotePlace |
Character; controls where footnotes are rendered.
One of |
hasData |
Logical. Whether this spec has data to render. Set to |
topEmptyLine |
Empty spacer row height after table header (table-level),
e.g. |
bottomEmptyLine |
Empty spacer row height before table bottom border
(table-level), e.g. |
docTemplate |
Character. Template to use for rendering. Accepts either:
|
figureWidth |
Figure width with units, e.g. |
figureHeight |
Figure height with units. Same syntax as |
figureDevice |
Character. Image format for ggplot2 rendering.
One of |
figureScaleMode |
Character. How the figure is scaled in the DOCX.
One of |
Updated spec object
## Not run: # Table spec with data spec <- create_table(mtcars) |> set_document(hasData = TRUE) # Text spec for narrative-only output spec <- create_text() |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported.") # Figure spec with custom sizing spec <- create_figure("plot.png") |> set_document( figureWidth = "7in", figureHeight = "5in", figureScaleMode = "fitWidth" ) # Footnotes placed on last page only spec <- create_table(mtcars) |> set_document(hasData = TRUE, footnotePlace = "last_page") |> add_footnote("Source: Motor Trend, 1974.") # Use a bundled template (see tfl_list_templates() for available names) spec <- create_table(mtcars) |> set_document(hasData = TRUE, docTemplate = "Navy_Pro") ## End(Not run)## Not run: # Table spec with data spec <- create_table(mtcars) |> set_document(hasData = TRUE) # Text spec for narrative-only output spec <- create_text() |> set_document(hasData = FALSE) |> add_body_text("No adverse events were reported.") # Figure spec with custom sizing spec <- create_figure("plot.png") |> set_document( figureWidth = "7in", figureHeight = "5in", figureScaleMode = "fitWidth" ) # Footnotes placed on last page only spec <- create_table(mtcars) |> set_document(hasData = TRUE, footnotePlace = "last_page") |> add_footnote("Source: Motor Trend, 1974.") # Use a bundled template (see tfl_list_templates() for available names) spec <- create_table(mtcars) |> set_document(hasData = TRUE, docTemplate = "Navy_Pro") ## End(Not run)
Set document-level style configuration. Multiple calls merge with last-win strategy.
set_page_style(spec, docTemplate = NULL, page = NULL) ## S3 method for class 'TFL_spec' set_page_style(spec, docTemplate = NULL, page = NULL) ## S3 method for class 'TFL_options' set_page_style(spec, docTemplate = NULL, page = NULL)set_page_style(spec, docTemplate = NULL, page = NULL) ## S3 method for class 'TFL_spec' set_page_style(spec, docTemplate = NULL, page = NULL) ## S3 method for class 'TFL_options' set_page_style(spec, docTemplate = NULL, page = NULL)
spec |
TFL spec object |
docTemplate |
Character. Template to use for rendering. Accepts either:
When |
page |
Page settings object created with |
Updated spec object
## Not run: # Use a predefined bundled template spec <- create_text() |> set_page_style( docTemplate = "Navy_Pro", page = p_page(size = "A4", orientation = "landscape") ) # Use an external template file spec <- create_text() |> set_page_style(docTemplate = "/path/to/my_template.json") ## End(Not run)## Not run: # Use a predefined bundled template spec <- create_text() |> set_page_style( docTemplate = "Navy_Pro", page = p_page(size = "A4", orientation = "landscape") ) # Use an external template file spec <- create_text() |> set_page_style(docTemplate = "/path/to/my_template.json") ## End(Not run)
Prints the font resolution report from the most recent scan without
re-scanning. Use tfl_rescan_fonts() to perform a fresh scan.
tfl_font_status()tfl_font_status()
Invisibly returns the cached font scan report.
tfl_rescan_fonts() to re-run the scan.
## Not run: # Check which fonts are resolved and which use fallbacks tfl_font_status() ## End(Not run)## Not run: # Check which fonts are resolved and which use fallbacks tfl_font_status() ## End(Not run)
Fetch a single named option from the active ksTFL settings. This is a
convenience wrapper around tfl_get_options() that returns one element or
throws a friendly error if the option does not exist.
tfl_get_option(name)tfl_get_option(name)
name |
Character(1). Name of the option to fetch. Common options:
|
The value associated with name (type depends on the option).
## Not run: # Get the current page settings tfl_get_option("page") # Check whether TOC generation is enabled tfl_get_option("insertTOC") tfl_get_option("tocTitle") ## End(Not run)## Not run: # Get the current page settings tfl_get_option("page") # Check whether TOC generation is enabled tfl_get_option("insertTOC") tfl_get_option("tocTitle") ## End(Not run)
Returns the current session settings for ksTFL as a named list. These are the effective values used when building specs and rendering documents.
tfl_get_options()tfl_get_options()
The returned object is the internal settings list stored in the package
environment. Modifying the returned object will not change package state;
use tfl_set_options() to update settings for the current session.
A named list representing the current ksTFL options.
## Not run: # Inspect all current settings tfl_get_options() ## End(Not run)## Not run: # Inspect all current settings tfl_get_options() ## End(Not run)
Returns the names of all template JSON files bundled with the package in
inst/templates/. These names can be passed directly to
set_page_style(docTemplate = ...) or tfl_set_options(docTemplate = ...).
tfl_list_templates()tfl_list_templates()
A character vector of template names (without the .json extension),
sorted alphabetically.
## Not run: tfl_list_templates() ## End(Not run)## Not run: tfl_list_templates() ## End(Not run)
Iterates over every atom in the internal .const_options_styles registry
and prints a coloured, grouped summary using cli.
tfl_style_atoms_catalog() is a convenience alias for tfl_print_style_atoms().
tfl_print_style_atoms() tfl_style_atoms_catalog()tfl_print_style_atoms() tfl_style_atoms_catalog()
Invisible NULL.
## Not run: # Print the full catalog of built-in style atoms tfl_print_style_atoms() # Same output via the alias tfl_style_atoms_catalog() ## End(Not run)## Not run: # Print the full catalog of built-in style atoms tfl_print_style_atoms() # Same output via the alias tfl_style_atoms_catalog() ## End(Not run)
Re-runs the font discovery process using the current value of
getOption("ksTFL.font_dirs"). This is useful after installing
new fonts or after changing the ksTFL.font_dirs option.
tfl_rescan_fonts()tfl_rescan_fonts()
To point ksTFL at a custom TTF folder, set the ksTFL.font_dirs
option before or during your session, then call tfl_rescan_fonts():
options(ksTFL.font_dirs = "/path/to/your/fonts") tfl_rescan_fonts()
Multiple directories are supported:
options(ksTFL.font_dirs = c("/path/to/fonts1", "/path/to/fonts2"))
tfl_rescan_fonts()
The package's own bundled fonts directory is always scanned automatically;
ksTFL.font_dirs only adds extra directories on top of that.
To make the setting persistent across sessions, add the options()
call to your ‘~/.Rprofile’.
Invisibly returns the font scan report (a list with
resolutions and dirs_scanned).
tfl_font_status() to print the cached report without rescanning.
## Not run: # Rescan after installing new fonts tfl_rescan_fonts() # Point to a custom font directory, then rescan options(ksTFL.font_dirs = c("/usr/share/fonts/custom")) tfl_rescan_fonts() ## End(Not run)## Not run: # Rescan after installing new fonts tfl_rescan_fonts() # Point to a custom font directory, then rescan options(ksTFL.font_dirs = c("/usr/share/fonts/custom")) tfl_rescan_fonts() ## End(Not run)
Restores all ksTFL session options (headers, footers, body text, styles,
page settings, column width behavior, etc.) to their original package
defaults. Useful at the start of a new reporting session or after
experimenting with tfl_set_options().
tfl_reset_options()tfl_reset_options()
The default options list, returned invisibly.
tfl_set_options(), tfl_get_options(), tfl_get_option()
## Not run: # Set some session defaults tfl_set_options( add_header("Study ABC", "Phase II", "CONFIDENTIAL"), add_footer("Company", "Page {PAGE}", "2025") ) # ... build tables ... # Reset everything back to package defaults tfl_reset_options() tfl_get_options() # Confirm reset ## End(Not run)## Not run: # Set some session defaults tfl_set_options( add_header("Study ABC", "Phase II", "CONFIDENTIAL"), add_footer("Company", "Page {PAGE}", "2025") ) # ... build tables ... # Reset everything back to package defaults tfl_reset_options() tfl_get_options() # Confirm reset ## End(Not run)
Update ksTFL session options. This function accepts:
Named scalar options (e.g. contentWidth = "95%", missings = ".").
Settings objects produced by helper constructors such as add_header(), add_footer(), add_body_text(), or page objects from p_page().
A mixture of both named values and settings objects.
tfl_set_options( ..., docTemplate = NULL, footnotePlace = NULL, isContinues = NULL, contentWidth = NULL, missings = NULL, figureWidth = NULL, figureHeight = NULL, figureDevice = NULL, figureScaleMode = NULL, autoColWidth = NULL, minColWidth = NULL, insertTOC = NULL, tocTitle = NULL, output_directory = NULL, meta_directory = NULL )tfl_set_options( ..., docTemplate = NULL, footnotePlace = NULL, isContinues = NULL, contentWidth = NULL, missings = NULL, figureWidth = NULL, figureHeight = NULL, figureDevice = NULL, figureScaleMode = NULL, autoColWidth = NULL, minColWidth = NULL, insertTOC = NULL, tocTitle = NULL, output_directory = NULL, meta_directory = NULL )
... |
Named arguments OR settings objects returned from helper constructors.
|
docTemplate |
Character; name of a predefined bundled template (e.g. |
footnotePlace |
Character; controls where footnotes are rendered.
One of |
isContinues |
Logical; override continuation behavior. |
contentWidth |
Character; width for content area (e.g. "100%", "95%"). |
missings |
Character; default representation for missing values (e.g. "", ".", "NA", "—"). Default is an empty string (""). |
figureWidth |
Character; default width for figure output (e.g. |
figureHeight |
Character; default height for figure output (e.g. |
figureDevice |
Character; graphics device used for figure rendering
(e.g. |
figureScaleMode |
Character; how figures are scaled into the page content area.
Typically |
autoColWidth |
Logical; enable automatic column width recalculation when user sets |
minColWidth |
Numeric; minimum relative column width (%) for unlocked columns during recalculation. Default 0.5. Used to validate that relative widths don't squeeze columns below acceptable minimum. |
insertTOC |
Logical; when |
tocTitle |
Character; heading text placed above the TOC field on the TOC page.
Default |
output_directory |
Character; path to default output directory of rendered document. |
meta_directory |
Character; path to default directory for intermediate metadata (JSON specs, data, and asset files) created during rendering. |
The function tries to intelligently route each supplied object into the appropriate internal settings slot (headers, footers, styles, bodyText, page).
The updated settings list, returned invisibly. Use tfl_get_options() to inspect.
## Not run: # Set a named option tfl_set_options(contentWidth = "95%", missings = ".") # Set a predefined bundled template tfl_set_options(docTemplate = "Navy_Pro") # Set an external template file tfl_set_options(docTemplate = "/path/to/my_template.json") # Update page style via helper tfl_set_options( set_page_style(page= p_page( size = "Letter", orientation = "portrait", margins = p_margins(top = "1in", bottom = "1in", left = "0.75in", right = "0.75in") ))) # Add default header and footer via helpers tfl_set_options( add_header(c("Left Header", "Center Header", "Right Header")), add_footer(c("Left Footer", "Center Footer", "Right Footer")) ) # Add default body text via helper tfl_set_options( add_body_text("This is the default body text for all text specs.") ) # Control automatic column width recalculation # Enable auto-recalculation (default): tfl_set_options(autoColWidth = TRUE) spec <- create_table(data) |> define_cols("id", colWidth = "20%") # Locks id, others auto-adjust # Disable auto-recalculation for manual width management: tfl_set_options(autoColWidth = FALSE) spec <- create_table(data) |> define_cols(c("id", "age"), colWidth = c("20%", "30%")) # Exact widths, no auto-adjust # Enable TOC page for all reports in the session tfl_set_options(insertTOC = TRUE, tocTitle = "List of Tables") # Then mark individual titles/subtitles with toclevel: spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) # save_report() will now prepend a TOC page automatically. # In Word: click the TOC placeholder and press F9 to populate it. ## End(Not run)## Not run: # Set a named option tfl_set_options(contentWidth = "95%", missings = ".") # Set a predefined bundled template tfl_set_options(docTemplate = "Navy_Pro") # Set an external template file tfl_set_options(docTemplate = "/path/to/my_template.json") # Update page style via helper tfl_set_options( set_page_style(page= p_page( size = "Letter", orientation = "portrait", margins = p_margins(top = "1in", bottom = "1in", left = "0.75in", right = "0.75in") ))) # Add default header and footer via helpers tfl_set_options( add_header(c("Left Header", "Center Header", "Right Header")), add_footer(c("Left Footer", "Center Footer", "Right Footer")) ) # Add default body text via helper tfl_set_options( add_body_text("This is the default body text for all text specs.") ) # Control automatic column width recalculation # Enable auto-recalculation (default): tfl_set_options(autoColWidth = TRUE) spec <- create_table(data) |> define_cols("id", colWidth = "20%") # Locks id, others auto-adjust # Disable auto-recalculation for manual width management: tfl_set_options(autoColWidth = FALSE) spec <- create_table(data) |> define_cols(c("id", "age"), colWidth = c("20%", "30%")) # Exact widths, no auto-adjust # Enable TOC page for all reports in the session tfl_set_options(insertTOC = TRUE, tocTitle = "List of Tables") # Then mark individual titles/subtitles with toclevel: spec <- create_table(adsl) |> add_title("Table 1: Demographics", toclevel = 1) # save_report() will now prepend a TOC page automatically. # In Word: click the TOC placeholder and press F9 to populate it. ## End(Not run)
Two addins that open the HTML TFL Specification Preview in the RStudio Viewer pane.
tfl_spec_preview_selection() tfl_spec_preview_prompt()tfl_spec_preview_selection() tfl_spec_preview_prompt()
tfl_spec_preview_selection()Evaluates the currently selected
text in the source editor and, if the result is a TFL_spec object,
opens the HTML preview.
tfl_spec_preview_prompt()Prompts for the name of an object
in .GlobalEnv and, if it is a TFL_spec, opens the HTML preview.
Both functions require RStudio (rstudioapi::isAvailable()).
Renders a comprehensive HTML overview of a TFL specification and displays it in the RStudio Viewer pane. Requires RStudio and the htmltools package.
view_tfl_spec(spec)view_tfl_spec(spec)
spec |
A |
TRUE invisibly on success, FALSE invisibly if the viewer could
not be opened (e.g. not running inside RStudio or htmltools is
missing).
Convenience wrapper around save_report() and the internal DOCX renderer that saves a
TFL_report object to JSON (plus any required data/figure files) and
immediately renders it to a DOCX file in a single call.
write_doc( report, name, outDir = tfl_get_option("output_directory"), metaPath = tfl_get_option("meta_directory") %||% tempdir(), prettify = FALSE, toc = tfl_get_option("insertTOC"), tocTitle = tfl_get_option("tocTitle"), overrideTemplate = NULL, font_dirs = NULL, fallback_font = NULL, verbose = FALSE )write_doc( report, name, outDir = tfl_get_option("output_directory"), metaPath = tfl_get_option("meta_directory") %||% tempdir(), prettify = FALSE, toc = tfl_get_option("insertTOC"), tocTitle = tfl_get_option("tocTitle"), overrideTemplate = NULL, font_dirs = NULL, fallback_font = NULL, verbose = FALSE )
report |
A |
name |
Character(1). Base file name (without extension) for the output
DOCX document. The |
outDir |
Character(1). Directory where the final DOCX file will be
written. Defaults to |
metaPath |
Character(1). Directory where the intermediate specification
JSON and associated data/figure files will be stored. Defaults to
|
prettify |
Logical. When |
toc |
Logical. When |
tocTitle |
Character(1). Heading placed above the TOC field on the TOC
page. Defaults to |
overrideTemplate |
Optional character string. Global template override used by the internal renderer for all specs. Accepts either:
If |
font_dirs |
Optional character vector of additional directories to search for fonts during rendering. |
fallback_font |
Optional character string. Path to a fallback font file
used by the renderer. If |
verbose |
Logical. If |
This mirrors the helper used in the example inst/examples/init.R script
(previously called save_and_render()), but is provided as a public,
documented API function named write_doc().
Invisibly returns the full path to the generated .docx file.
create_report(), save_report(), replay_report(),
tfl_set_options(), tfl_get_option()
## Not run: # Basic end-to-end workflow ---------------------------------------------- library(ksTFL) # Create a simple table spec tbl <- create_table(mtcars) |> add_title("Table 1: Motor Trend Car Road Tests") |> set_document(hasData = TRUE) # Combine into a report rpt <- create_report(tbl) # Write DOCX to the default output directory (getwd() by default) doc_path <- write_doc( report = rpt, name = "mtcars_demo" ) cat("DOCX written to:", doc_path, "\n") # Custom output and meta directories, with TOC --------------------------- tfl_set_options( output_directory = "output", insertTOC = TRUE, tocTitle = "List of Tables" ) rpt2 <- create_report(tbl) write_doc( report = rpt2, name = "mtcars_with_toc", outDir = "output", metaPath = file.path(tempdir(), "ksTFL_meta"), prettify = TRUE, toc = TRUE ) ## End(Not run)## Not run: # Basic end-to-end workflow ---------------------------------------------- library(ksTFL) # Create a simple table spec tbl <- create_table(mtcars) |> add_title("Table 1: Motor Trend Car Road Tests") |> set_document(hasData = TRUE) # Combine into a report rpt <- create_report(tbl) # Write DOCX to the default output directory (getwd() by default) doc_path <- write_doc( report = rpt, name = "mtcars_demo" ) cat("DOCX written to:", doc_path, "\n") # Custom output and meta directories, with TOC --------------------------- tfl_set_options( output_directory = "output", insertTOC = TRUE, tocTitle = "List of Tables" ) rpt2 <- create_report(tbl) write_doc( report = rpt2, name = "mtcars_with_toc", outDir = "output", metaPath = file.path(tempdir(), "ksTFL_meta"), prettify = TRUE, toc = TRUE ) ## End(Not run)