Specifies borders for up to four sides (top, bottom, left, right). Each
side is either NULL (no border) or a border side.
Usage
rtf_border(
all = NULL,
top = NULL,
bottom = NULL,
left = NULL,
right = NULL,
inside_h = NULL,
inside_v = NULL
)
rtf_border_none()
rtf_border_top(style = "single", width = 15L, color = NULL)
rtf_border_bottom(style = "single", width = 15L, color = NULL)
rtf_border_box(style = "single", width = 15L, color = NULL)Arguments
- all
Shorthand for
top,bottom,leftandrightat once. A side named explicitly wins over it.- top, bottom, left, right
The selection's four outer edges. A side takes a value from either of two families –
TRUE/FALSE, or a style name – orNULLto leave it unset. See Writing a side below.- inside_h, inside_v
The rules drawn between the selection's rows (
inside_h) and between its cells (inside_v). Same values as the edges;NULL(default) means no rule there.- style, width, color
Line style, weight in twips and colour, as in
rtf_border_line().
Functions
rtf_border_none(): Deprecated. Writertf_border().rtf_border_top(): Deprecated. Writertf_border(top = TRUE).rtf_border_bottom(): Deprecated. Writertf_border(bottom = TRUE).rtf_border_box(): Deprecated. Writertf_border(all = TRUE).
What a border applies to
An rtf_border describes a selection, and where it applies is decided
by where you attach it – the same way Word's border dialog acts on whatever
is selected:
rtftable(border = ) | the whole table |
style_zone(header = , body = , ...) | that kind of row |
col_cell(border = ), cell_styles | one cell |
rtf_header(border = ) / rtf_footer(border = ) | that block |
There is one rule, with no special cases:
top/bottom/left/rightare the selection's outer edges.inside_h/inside_vare the rules inside it, and an absent one means no rule there.
Writing a side
Every side takes a value from one of two families. Stay inside one family within a call and it reads evenly:
logical rtf_border(top = TRUE, bottom = FALSE)
style name rtf_border(top = "single", bottom = "none")
The two agree: TRUE is a rule in this call's style / width / color,
and FALSE is "none" – an explicit no line, which erases a rule the
selection would otherwise inherit. The style names are "single",
"double", "thick", "dash", "dot" and "none".
Both are shorthands for the third spelling, an rtf_border_line(), which is
what a side actually holds. Reach for it when a line needs a weight or a
colour of its own – and since each side carries its own, one call is always
enough:
rtf_border(all = "double") # four edges alike
rtf_border(top = rtf_border_line(color = "#C9372C"), # ... or all four
bottom = rtf_border_line("double", 30L)) # differentFALSE and "none" are always interchangeable.
So an edge never means something different depending on which other
arguments are present. On a row containing a spanning cell, inside_v
lands on cell boundaries rather than column boundaries: nothing is drawn
inside a merged cell. A single cell has no inside, so both are ignored
there.
Building versus layering
A side is in one of three states, and all three matter:
- unset (
NULL) nothing is said about it, so it inherits whatever the enclosing selection supplies.
- erased (
FALSE/"none") an explicit no line, which overrides an inherited rule.
- a rule (
TRUE/ a style name) drawn in this call's
style,widthandcolor.
A call to rtf_border() says everything about the border it returns: every
side not named is unset. Adding to a border already in place is the job of
the place it is attached to – style_zone(), style_header() and
style_body() all merge side by side, so a second call adds to the first
rather than replacing it:
tbl |>
style_zone(header = rtf_border(top = rtf_border_line(color = "#C9372C"))) |>
style_zone(header = rtf_border(bottom = TRUE)) # the top rule survivesA later layer can change a side or erase it with FALSE; a side left NULL
says nothing and leaves what was there alone.
One distinction worth keeping straight: rtf_border(all = FALSE) says
"explicitly no rule anywhere", which erases what a border would otherwise
inherit, while rtf_border() says nothing at all and inherits.
Writing borders before and after 0.5.0
Two things changed at 0.5.0. rtf_table_border() is deprecated, so a
border is aimed with rtftable(border = ) or style_zone() instead; and an
edge now always means the outer edge of the selection, so the rules
inside it have to be asked for by name. Each case below, s being an
a border side:
## rules above and below the column header (unchanged in meaning)
was: rtftable(df, border = rtf_table_border(
header = rtf_border(top = s, bottom = s)))
now: rtftable(df, border = "none") |>
style_zone(header = rtf_border(top = s, bottom = s))
## a rule under the last data row (unchanged)
was: rtf_table_border(last_row = rtf_border(bottom = s))
now: style_zone(last_row = rtf_border(bottom = s))
## a rule under EVERY data row (bottom -> inside_h)
was: rtf_table_border(body = rtf_border(bottom = s))
now: style_zone(body = rtf_border(inside_h = s))
## a vertical rule at every column boundary (left/right -> inside_v)
was: rtf_table_border(body = rtf_border(left = s, right = s))
now: style_zone(body = rtf_border(left = s, right = s, inside_v = s))
## a grid around every data cell
was: rtf_table_border(body = rtf_border(all = TRUE))
now: style_zone(body = rtf_border(top = s, bottom = s, left = s,
right = s, inside_h = s, inside_v = s))
## an outer frame only, no rules inside (was not expressible)
now: rtftable(df, border = rtf_border(top = s, bottom = s,
left = s, right = s))
## frame plus a rule under every row -- the listing look
was: four style_header() / style_body() calls on the edge columns
now: rtftable(df, border = rtf_border(top = TRUE, bottom = TRUE,
left = TRUE, right = TRUE,
inside_h = TRUE))
At 0.6.0 the remaining constructors folded in here too, so a side is written as a value rather than built:
rtf_border_none() -> rtf_border()
rtf_border_top() -> rtf_border(top = TRUE)
rtf_border_bottom() -> rtf_border(bottom = TRUE)
rtf_border_box() -> rtf_border(all = TRUE)
rtf_border_with(b, bottom = x) -> layer at the attach point
rtf_border_tfl() -> border = "tfl", rtf_table_style_tfl()
All of them still work and warn once per session; they are removed in 0.9.0, the first CRAN release.
border = "tfl" and rtf_border_tfl() are unaffected, as is any border on
a single cell (col_cell(), cell_styles): a cell has no inside, so its
four edges never meant anything else.
The old and new readings are spelled identically, so rtfreporter warns once
per session when it meets a border that would have rendered differently
before. Naming inside_h / inside_v says which you mean and silences it
– use "none" for "no rule there".
Examples
rtf_border(top = TRUE, bottom = TRUE) # top + bottom
#> <rtf_border>
#> top : single, 15 twips
#> bottom : single, 15 twips
#> left : none
#> right : none
rtf_border(bottom = rtf_border_line(color = "#003366")) # blue underline
#> <rtf_border>
#> top : none
#> bottom : single, 15 twips, color=#003366
#> left : none
#> right : none
# A whole table: frame plus a rule under every row, no vertical rules.
s <- TRUE
rtf_border(top = s, bottom = s, left = s, right = s, inside_h = s)
#> <rtf_border>
#> top : single, 15 twips
#> bottom : single, 15 twips
#> left : single, 15 twips
#> right : single, 15 twips
#> inside_h: single, 15 twips
# A rule between the cells but no outer edges.
rtf_border(inside_v = TRUE)
#> <rtf_border>
#> top : none
#> bottom : none
#> left : none
#> right : none
#> inside_v: single, 15 twips
# Either family, but one at a time: these two agree.
identical(rtf_border(top = TRUE, bottom = FALSE),
rtf_border(top = "single", bottom = "none"))
#> [1] TRUE
# A weight or a colour of its own needs the side value.
rtf_border(top = rtf_border_line("double", 30L, "#003366"),
bottom = rtf_border_line(color = "#C9372C"))
#> <rtf_border>
#> top : double, 30 twips, color=#003366
#> bottom : single, 15 twips, color=#C9372C
#> left : none
#> right : none