A flextable is made of parts, an header, a body and a footer. 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

Shortcuts functions

There are simple functions to modify formatting properties of flextable objects: bg, bold, border, color, padding, fontsize, italic, align, …

They are illustrated in the examples below.

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

bold

myft <- flextable(head(iris)) 
myft <- bold(myft, part = "header") # bold header
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

Font size

myft <- fontsize(myft, part = "header", size = 12) 
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

change font color

myft <- color(myft, color = "#E4C994")
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

Italic

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

change background color

# light gray as background color for header
myft <-  bg(myft, bg = "#E4C994", part = "header")
# dark gray as background color for body
myft <-  bg(myft, bg = "#333333", part = "body")
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

Text alignment

myft <- align( myft, align = "center", part = "all" )
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

add padding

myft <- padding( myft, padding = 3, part = "all" )
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

change font

myft <- font(myft, j = "Species", fontname = "Times")
myft <- fontsize(myft, j = "Species", size = 14)
myft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

4.700

3.200

1.300

0.200

setosa

4.600

3.100

1.500

0.200

setosa

5.000

3.600

1.400

0.200

setosa

5.400

3.900

1.700

0.400

setosa

Text rotation

Text rotation is possible in flextable objects but will only work correctly with Word and PowerPoint outputs (html output is not always correct). This is achieved by using function rotate().

Argument rotation is mandatory and expects one of these values:

  • “lrtb”, left to right top to bottom
  • “tbrl”, top to bottom right to left
  • “btlr”, bottom to top left to right

Argument align is used for cell content vertical alignment, it should be one of these values: “top”, “bottom” or “center”.

ft <- flextable(head(iris))
# ft <- theme_box(ft)
ft <- rotate(ft, rotation = "tbrl", align = "center", part = "header")
ft <- align(ft, align = "right", part = "header")
ft <- align(ft, align = "center", part = "body")
ft <- autofit(ft)

# as autofit do not handle rotation, you will have
# to change manually header cells'height.
ft <- height(ft, height = 1.1, part = "header")

rotated_flextable

Borders

Borders properties can be defined with function border() but the function requires careful settings to avoid overlapping borders.

If no special formatting is needed, best is to use border_outer(), border_inner_h() and border_inner_v().

library(officer)
big_border = fp_border(color="orange", width = 2)
border_v = fp_border(color="gray")
border_h = fp_border(color="gray")

dat <- iris[c(1:2, 51:52, 101:102),]
ft <- flextable(dat)
ft <- border_remove(x = ft)
ft <- border_outer(ft, part="all", border = big_border )
ft <- border_inner_h(ft, part="all", border = border_h )
ft <- border_inner_v(ft, part="all", border = border_v )
ft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

7.000

3.200

4.700

1.400

versicolor

6.400

3.200

4.500

1.500

versicolor

6.300

3.300

6.000

2.500

virginica

5.800

2.700

5.100

1.900

virginica

When more control over borders formatting is necessary, the following functions can be used to add vertical or horizontal lines as borders:

dat <- iris[c(1:2, 51:52, 101:102),]
ft <- flextable(dat)
ft <- border_remove( ft )

big_b <- fp_border(color="gray70", width = 3)
std_b <- fp_border(color="orange", style = "dashed")

ft <- vline( ft, border = std_b, part = "all" )
ft <- vline_left( ft, border = big_b, part = "all" )
ft <- vline_right( ft, border = big_b, part = "all" )
ft <- hline( ft, border = std_b )
ft <- hline_bottom( ft, border = big_b )
ft <- hline_top( ft, border = big_b, part = "all" )
ft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

7.000

3.200

4.700

1.400

versicolor

6.400

3.200

4.500

1.500

versicolor

6.300

3.300

6.000

2.500

virginica

5.800

2.700

5.100

1.900

virginica

Conditional formatting

Conditional formatting can be made by using the selector arguments.

dat <- iris[c(1:2, 51:52, 101:102),]
ft <- flextable(dat)
ft <- fontsize(ft, size = 14, part = "all")
ft <- color(ft, i = ~ Sepal.Length < 5 & Petal.Length > 1.3, 
        j = ~ Petal.Width + Species, 
        color="red")
ft <- italic(ft, i = ~ Sepal.Length > 5)
ft <- bold(ft, i = 4, j = "Sepal.Length")
ft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

7.000

3.200

4.700

1.400

versicolor

6.400

3.200

4.500

1.500

versicolor

6.300

3.300

6.000

2.500

virginica

5.800

2.700

5.100

1.900

virginica

i and j arguments can be also standard R vectors:

row_id <- with(dat, Sepal.Length < 5 & Petal.Length > 1.3 )
col_id <- c("Petal.Width", "Species")

ft <- color(ft, i = row_id, j = col_id, color="red") 

ft

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

5.100

3.500

1.400

0.200

setosa

4.900

3.000

1.400

0.200

setosa

7.000

3.200

4.700

1.400

versicolor

6.400

3.200

4.500

1.500

versicolor

6.300

3.300

6.000

2.500

virginica

5.800

2.700

5.100

1.900

virginica

Function style

The style function lets you style a selection of the flextable with several formatting properties.

It main advantage is to let specify a set of formatting properties for a selection.

Package officer needs to be loaded, it provides the following formatting properties:

  • for text: fp_text
  • for paragraphs: fp_par
  • for cells: fp_cell and fp_border
library(officer)
def_cell <- fp_cell(border = fp_border(color="#00C9C9"))
def_par <- fp_par(text.align = "center")
def_text <- fp_text(color="#999999", italic = TRUE)
def_text_header <- update(color="black", def_text, bold = TRUE)

ft <- flextable(head(mtcars, n = 10 ))
ft <- style( ft, pr_c = def_cell, pr_p = def_par, pr_t = def_text, part = "all")  
ft

mpg

cyl

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.000

6.000

160.000

110.000

3.900

2.620

16.460

0.000

1.000

4.000

4.000

21.000

6.000

160.000

110.000

3.900

2.875

17.020

0.000

1.000

4.000

4.000

22.800

4.000

108.000

93.000

3.850

2.320

18.610

1.000

1.000

4.000

1.000

21.400

6.000

258.000

110.000

3.080

3.215

19.440

1.000

0.000

3.000

1.000

18.700

8.000

360.000

175.000

3.150

3.440

17.020

0.000

0.000

3.000

2.000

18.100

6.000

225.000

105.000

2.760

3.460

20.220

1.000

0.000

3.000

1.000

14.300

8.000

360.000

245.000

3.210

3.570

15.840

0.000

0.000

3.000

4.000

24.400

4.000

146.700

62.000

3.690

3.190

20.000

1.000

0.000

4.000

2.000

22.800

4.000

140.800

95.000

3.920

3.150

22.900

1.000

0.000

4.000

2.000

19.200

6.000

167.600

123.000

3.920

3.440

18.300

1.000

0.000

4.000

4.000


ft <- style( ft, pr_t = def_text_header, part = "header")  
ft

mpg

cyl

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.000

6.000

160.000

110.000

3.900

2.620

16.460

0.000

1.000

4.000

4.000

21.000

6.000

160.000

110.000

3.900

2.875

17.020

0.000

1.000

4.000

4.000

22.800

4.000

108.000

93.000

3.850

2.320

18.610

1.000

1.000

4.000

1.000

21.400

6.000

258.000

110.000

3.080

3.215

19.440

1.000

0.000

3.000

1.000

18.700

8.000

360.000

175.000

3.150

3.440

17.020

0.000

0.000

3.000

2.000

18.100

6.000

225.000

105.000

2.760

3.460

20.220

1.000

0.000

3.000

1.000

14.300

8.000

360.000

245.000

3.210

3.570

15.840

0.000

0.000

3.000

4.000

24.400

4.000

146.700

62.000

3.690

3.190

20.000

1.000

0.000

4.000

2.000

22.800

4.000

140.800

95.000

3.920

3.150

22.900

1.000

0.000

4.000

2.000

19.200

6.000

167.600

123.000

3.920

3.440

18.300

1.000

0.000

4.000

4.000

Content format functions

By default, the displayed content of each cell will be the result of a simple formatting. The content can also be comoosed as the result of a concatenation of several chunks.

There are formatter functions to define how columns content will be display (e.g. to define the number of decimal). This is a column-wise operation.

User can also have more control over displayed content by using function compose. The function enable to define the elements composing the paragraph and their respective formats. It can also be used to mix text chunks and images.

Column-wise functions

Theses are high level functions that should satisfy most of the usual needs. They can be used to define the formatting of one or more columns.

Each accept a prefix and suffix argument that can be used to add a currency symbol for example. Also they all have na_str argument (defaut to ""), the string to use when data are not available.

dat <- head(mtcars, n = 10)
dat[3:7, 1] <- NA
dat[, 2] <- dat[, 6] * 1000000

ft <- flextable(dat)
num_keys <- c("mpg", "disp", "drat", "wt", "qsec")
int_keys <- c("cyl", "hp", "vs", "am", "gear", "carb")

ft <- colformat_num(x = ft, col_keys = num_keys, big.mark = ",", digits = 2, na_str = "missing")
ft <- colformat_int(x = ft, col_keys = int_keys, big.mark = ",")
autofit(ft)

mpg

cyl

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.00

2,620,000

160.00

110

3.90

2.62

16.46

0

1

4

4

21.00

2,875,000

160.00

110

3.90

2.88

17.02

0

1

4

4

missing

2,320,000

108.00

93

3.85

2.32

18.61

1

1

4

1

missing

3,215,000

258.00

110

3.08

3.21

19.44

1

0

3

1

missing

3,440,000

360.00

175

3.15

3.44

17.02

0

0

3

2

missing

3,460,000

225.00

105

2.76

3.46

20.22

1

0

3

1

missing

3,570,000

360.00

245

3.21

3.57

15.84

0

0

3

4

24.40

3,190,000

146.70

62

3.69

3.19

20.00

1

0

4

2

22.80

3,150,000

140.80

95

3.92

3.15

22.90

1

0

4

2

19.20

3,440,000

167.60

123

3.92

3.44

18.30

1

0

4

4

set_formatter function

It is possible to define the functions that will be used to format the data.frame values into strings. set_formatter set column formatter functions.

gear

mpg

qsec

4 gears

21.0000

16.460

4 gears

21.0000

17.020

4 gears

22.8000

18.610

3 gears

21.4000

19.440

3 gears

18.7000

17.020

3 gears

18.1000

20.220

3 gears

14.3000

15.840

4 gears

24.4000

20.000

4 gears

22.8000

22.900

4 gears

19.2000

18.300

compose function

flextable content can be defined with function compose.

It lets user control the formated content at the cell level of the table. It is possible to define a content for a row subset and a column as well as on the whole column. One can mix images and text (but not with PowerPoint because PowerPoint can not do it).

Below the starting point of next illustrations:

myft <- flextable( head(mtcars), 
  col_keys = c("am", "separator", "gear", "mpg", "drat", "qsec" ))
myft <- bold(myft, part = "header")
myft <- border(myft, border = fp_border( width = 0), 
  border.top = fp_border(), border.bottom = fp_border(), 
  part = "all")
myft <- align(myft, align = "right", part = "all" )
myft <- border(myft, j = ~ separator, border = fp_border(width=0), part = "all")
myft <- width(myft, j = ~ separator, width = .1)
myft

am

gear

mpg

drat

qsec

1.000

4.000

21.000

3.900

16.460

1.000

4.000

21.000

3.900

17.020

1.000

4.000

22.800

3.850

18.610

0.000

3.000

21.400

3.080

19.440

0.000

3.000

18.700

3.150

17.020

0.000

3.000

18.100

2.760

20.220

The function requires a call to as_paragraph which will concatenate text or images chunks as a paragraph.

The following example shows how to control the format of displayed values and how to associate them with specific text formatting properties (bold red text):

am

gear

mpg

drat

qsec

1.000

4.000

mpg value is 21.0

3.900

16.460

1.000

4.000

mpg value is 21.0

3.900

17.020

1.000

4.000

mpg value is 22.8

3.850

18.610

0.000

3.000

mpg value is 21.4

3.080

19.440

0.000

3.000

mpg value is 18.7

3.150

17.020

0.000

3.000

mpg value is 18.1

2.760

20.220

With that system, it’s easy to concatenate multiple values:

myft <- compose( 
  myft, j = "mpg", 
  value = as_paragraph(
    "mpg value is ", 
    as_chunk(sprintf("%.01f", mpg), props = fp_text(color = "red", bold = TRUE) ), 
    " with ",
    as_chunk(sprintf("# %.0f", carb), props = fp_text(color = "gray", italic = TRUE) )
    )
  )

myft <- autofit(myft)
myft

am

gear

mpg

drat

qsec

1.000

4.000

mpg value is 21.0 with # 4

3.900

16.460

1.000

4.000

mpg value is 21.0 with # 4

3.900

17.020

1.000

4.000

mpg value is 22.8 with # 1

3.850

18.610

0.000

3.000

mpg value is 21.4 with # 1

3.080

19.440

0.000

3.000

mpg value is 18.7 with # 2

3.150

17.020

0.000

3.000

mpg value is 18.1 with # 1

2.760

20.220

Or to define specific title headers:

myft <- compose( 
  myft, j = "mpg", part = "header",
  value = as_paragraph(
    "Miles/(US) gallon ", 
    as_chunk("* with num of carb.", props = fp_text(color = "gray", vertical.align = "superscript") )
    )
  )

myft <- autofit(myft)
myft

am

gear

Miles/(US) gallon * with num of carb.

drat

qsec

1.000

4.000

mpg value is 21.0 with # 4

3.900

16.460

1.000

4.000

mpg value is 21.0 with # 4

3.900

17.020

1.000

4.000

mpg value is 22.8 with # 1

3.850

18.610

0.000

3.000

mpg value is 21.4 with # 1

3.080

19.440

0.000

3.000

mpg value is 18.7 with # 2

3.150

17.020

0.000

3.000

mpg value is 18.1 with # 1

2.760

20.220

Images

Function compose supports images insertion. Use function as_image in as_paragraph call:

img.file <- file.path( R.home("doc"), "html", "logo.jpg" )

myft <- compose( myft, i = ~ qsec > 18, j = "qsec", 
  value = as_paragraph(as_image( src = img.file, width = .20, height = .15))
)
myft <- autofit(myft)
myft

am

gear

Miles/(US) gallon * with num of carb.

drat

qsec

1.000

4.000

mpg value is 21.0 with # 4

3.900

16.460

1.000

4.000

mpg value is 21.0 with # 4

3.900

17.020

1.000

4.000

mpg value is 22.8 with # 1

3.850

0.000

3.000

mpg value is 21.4 with # 1

3.080

0.000

3.000

mpg value is 18.7 with # 2

3.150

17.020

0.000

3.000

mpg value is 18.1 with # 1

2.760

minibar

Function compose supports mini barplots insertion. Use function minibar in as_paragraph call:

myft <- flextable( head(iris, n = 10 ))

myft <- compose( myft, j = 1,
  value = as_paragraph(
    minibar(value = Sepal.Length, max = max(Sepal.Length))
  ),
  part = "body")

autofit(myft)

Sepal.Length

Sepal.Width

Petal.Length

Petal.Width

Species

3.500

1.400

0.200

setosa

3.000

1.400

0.200

setosa

3.200

1.300

0.200

setosa

3.100

1.500

0.200

setosa

3.600

1.400

0.200

setosa

3.900

1.700

0.400

setosa

3.400

1.400

0.300

setosa

3.400

1.500

0.200

setosa

2.900

1.400

0.200

setosa

3.100

1.500

0.100

setosa