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:

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:

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

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
Table 5.1: colorize demo

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
Table 5.2: Cell text rotation demo

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
Table 5.3: Inner and outer borders demo

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:

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
Table 5.4: vline and vline demo

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.

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

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

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:

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

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

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