Chapter 5 Define visual properties
dat <- data.frame(
wool = c("A", "B"),
L = c(44.56, 28.22),
M = c(24, 28.77),
H = c(24.56, 18.78)
)
5.1 Format specific parts
A flextable is made of parts, an ‘header’, a ‘body’ and a ‘footer’ (see
3.1). To specify which part formatting instructions
should affect, use argument part
. Possible values are:
- “header”: the header part of the table
- “footer”: the footer part of the table
- “body”: the body part of the table
- “all”: the body and the header parts of the table only.
Formatting functions also support selectors to specify where in parts the formatting should happen.
5.2 Formatting functions
The function style()
lets you style a selection of the flextable with several
formatting properties. The function will apply formatting properties for text,
paragraphs and table cells. It can be used to make the code less verbose.
Its main use is to specify a set of formatting properties for a selection.
The following formatting properties can be used as arguments:
- for text:
officer::fp_text()
andflextable::fp_text_default()
, - for paragraphs:
officer::fp_par()
, - for cells:
officer::fp_cell()
,officer::fp_border()
andflextable::fp_border_default()
.
flextable(dat) %>%
style(i = 1,
pr_t = fp_text_default(
italic = TRUE,
color = "red")) %>%
style(i = 2, j = 3:4,
pr_t = fp_text_default(
shading.color = "yellow"),
pr_p = fp_par(
text.align = "center", padding = 1))
wool |
L |
M |
H |
---|---|---|---|
A |
44.56 |
24.00 |
24.56 |
B |
28.22 |
28.77 |
18.78 |
There are also simple/sugar functions to modify one formatting property:
- text can be formatted with functions
bold()
,italic()
,color()
,fontsize()
,font()
,highlight()
flextable(dat) %>%
fontsize(i = ~ wool %in% "A", size = 10) %>%
font(part = "all", fontname = "Inconsolata") %>%
color(part = "header", color = "#e22323", j = c("L", "M", "H")) %>%
bold(part = "header", j = c("L", "M")) %>%
italic(part = "all", j = "wool") %>%
highlight(i = ~ L < 30, color = "wheat", j = c("M", "H"))
wool |
L |
M |
H |
---|---|---|---|
A |
44.56 |
24.00 |
24.56 |
B |
28.22 |
28.77 |
18.78 |
- paragraphs with functions
line_spacing()
,padding()
andalign()
.
ft <- flextable(dat) %>%
align(align = "center", part = "all") %>%
line_spacing(space = 2, part = "all") %>%
padding(padding = 6, part = "header")
ft
wool |
L |
M |
H |
---|---|---|---|
A |
44.56 |
24.00 |
24.56 |
B |
28.22 |
28.77 |
18.78 |
Note that padding is ignored when output is PDF (see 4.3.3).
ft %>%
bg(bg = "black", part = "all") %>%
color(color = "white", part = "all") %>%
merge_at(i = 1:2, j = 1) %>%
valign(i = 1, valign = "bottom")
wool |
L |
M |
H |
---|---|---|---|
A |
44.56 |
24.00 |
24.56 |
28.22 |
28.77 |
18.78 |
Background colors, font colors and highlight colors can be modified with
a vector or with a function that returns a
character vector of colors (as with ‘ggplot2’ - see scales::col_numeric
).
myft <- as.data.frame(matrix(runif(5*5), ncol = 5)) %>%
flextable() %>%
colformat_double() %>% autofit() %>%
align(align = "center", part = "all") %>%
bg(bg = "black", part = "header") %>%
color(color = "white", part = "all") %>%
bg(bg = scales::col_numeric(palette = "viridis", domain = c(0, 1)))
myft
V1 |
V2 |
V3 |
V4 |
V5 |
---|---|---|---|---|
0.61 |
0.56 |
0.43 |
0.68 |
0.39 |
0.21 |
0.69 |
0.74 |
0.69 |
0.59 |
0.32 |
0.56 |
0.37 |
0.09 |
0.84 |
0.91 |
0.34 |
0.49 |
0.38 |
0.52 |
0.32 |
0.23 |
0.80 |
0.41 |
0.43 |
Cell text rotation is another option that can be used - it is
recommanded to use it with hrule(rule = "exact")
when
output is Word or PowerPoint because of a limitation of ‘office’.
myft <- myft %>%
rotate(rotation = "tbrl", part = "header", align = "center") %>%
height(height = 1, unit = "cm", part = "header") %>%
hrule(rule = "exact", part = "header") %>%
align(align = "right", part = "header")
myft
V1 |
V2 |
V3 |
V4 |
V5 |
---|---|---|---|---|
0.61 |
0.56 |
0.43 |
0.68 |
0.39 |
0.21 |
0.69 |
0.74 |
0.69 |
0.59 |
0.32 |
0.56 |
0.37 |
0.09 |
0.84 |
0.91 |
0.34 |
0.49 |
0.38 |
0.52 |
0.32 |
0.23 |
0.80 |
0.41 |
0.43 |
5.3 Borders
5.3.1 Inner and outer borders
If no conditional formatting is needed, use border_outer()
,
border_inner_h()
and border_inner_v()
. These are the most easy
functions and they satisfy most the use cases.
library(officer)
big_border = fp_border(color="red", width = 2)
small_border = fp_border(color="gray", width = 1)
myft <- flextable(head(airquality))
myft <- border_remove(x = myft)
myft <- border_outer(myft, part="all", border = big_border )
myft <- border_inner_h(myft, part="all", border = small_border )
myft <- border_inner_v(myft, part="all", border = small_border )
myft
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
---|---|---|---|---|---|
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
5.3.2 Add lines
When more control over borders formatting is necessary, the following functions can be used to add vertical or horizontal lines as borders:
-
hline()
: set bottom borders (inner horizontal) -
vline()
: set right borders (inner vertical) -
hline_top()
: set the top border (outer horizontal) -
hline_bottom()
: set the bottom border (outer horizontal) -
vline_left()
: set the left border (outer vertical) -
vline_right()
: set the right border (outer vertical)
myft2 <- border_remove( myft )
myft2 <- vline( myft2, border = small_border, part = "all" )
myft2 <- vline_left( myft2, border = big_border, part = "all" )
myft2 <- vline_right( myft2, border = big_border, part = "all" )
myft2 <- hline( myft2, border = small_border)
myft2 <- hline_bottom( myft2, border = big_border )
myft2 <- hline_top( myft2, border = big_border, part = "all" )
myft2
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
---|---|---|---|---|---|
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
These functions also support the row selector i
and the column selector j
.
5.3.3 Surround cells
To highlight specific cells with borders, use function surround()
.
myft <- flextable(head(airquality))
surround(
x = myft, i = 2, j = c(2, 4, 6),
border = fp_border_default(
color = "red", width = 1.5),
part = "body")
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
---|---|---|---|---|---|
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
5.4 Theme functions
A set of theme functions are made available.
Theme functions are not like ‘ggplot2’ themes. They are applied to the existing table immediately. If you add a row in the footer, the new row is not formatted with the theme. The theme function applies the theme only to existing elements when the function is called.
That is why theme functions should be applied after all elements of the table have been added (mainly additionnal header or footer rows).
If you want to automatically apply a theme function to each flextable,
you can use the theme_fun
argument of set_flextable_defaults()
; be
aware that this theme function is applied as the last instruction when
calling flextable()
- so if you add headers or footers to the array,
they will not be formatted with the theme.
You can also use the post_process_html
argument
of set_flextable_defaults()
(or post_process_pdf
,
post_process_docx
, post_process_pptx
) to specify a theme
to be applied systematically before the flextable()
is printed.
Don’t forget to make sure your theme doesn’t
override any formatting done before the print statement.
ft <- flextable(head(airquality))
ft <- add_header_row(ft, top = TRUE,
values = c("measures", "time"),
colwidths = c(4, 2))
ft <- align(ft, i = 1, align = "center", part = "header")
ft <- width(ft, width = .75)
5.4.1 Available themes
-
theme_booktabs()
is the default theme. It adds borders, left align text columns and right align non textual columns.
theme_booktabs(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
-
theme_alafoli()
provides a light gray aspect:
theme_alafoli(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
-
theme_vader()
provides a dark aspect:
theme_vader(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
-
theme_box()
is not nice but useful when creating a table if you want to make sure the layout you define is exactly as expected:
theme_box(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
-
theme_vanilla()
looks liketheme_booktabs()
but have horizontal thin lines separating the rows:
theme_vanilla(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
-
theme_zebra()
let you create zebra tables -
theme_tron_legacy()
andtheme_tron()
are dark themes.
5.4.2 Define your own theme
You can define easily your theme by creating a function.
my_theme <- function(x, ...) {
x <- colformat_double(x, big.mark = "'", decimal.mark = ",", digits = 1)
x <- set_table_properties(x, layout = "fixed")
x <- border_remove(x)
std_border <- fp_border(width = 1, color = "orange")
x <- border_outer(x, part="all", border = std_border )
x <- border_inner_h(x, border = std_border, part="all")
x <- border_inner_v(x, border = std_border, part="all")
autofit(x)
}
my_theme(ft)
measures |
time |
||||
---|---|---|---|---|---|
Ozone |
Solar.R |
Wind |
Temp |
Month |
Day |
41 |
190 |
7,4 |
67 |
5 |
1 |
36 |
118 |
8,0 |
72 |
5 |
2 |
12 |
149 |
12,6 |
74 |
5 |
3 |
18 |
313 |
11,5 |
62 |
5 |
4 |
<na> |
<na> |
14,3 |
56 |
5 |
5 |
28 |
<na> |
14,9 |
66 |
5 |
6 |