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:
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 |
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 |
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 |
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 |
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 |
# 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 |
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 |
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 |
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 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:
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 <- rotate(ft, rotation = "tbrl", align = "top", part = "header")
ft <- theme_vanilla(ft)
ft <- autofit(ft)
# as autofit do not handle rotation, you will have
# to change manually header cells'height.
ft <- height(ft, height = 1, part = "header")
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 |
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 |
Borders properties can be defined with functions:
hline()
: set bottom borders of one or all parts of a flextable.hline_top()
: set top border of one or all parts of a flextable.hline_bottom()
: set bottom border of one or all parts of a flextable.vline()
: set right borders of one or all parts of a flextable.vline_left()
: set left border of one or all parts of a flextable.vline_right()
: set right border of one or all parts of a flextable.# remove all defined borders
myft <- border_remove( myft )
big_b <- fp_border(color="gray70", width = 2)
std_b <- fp_border(color="white")
myft <- vline( myft, border = std_b, part = "all" )
myft <- vline_left( myft, border = big_b, part = "all" )
myft <- vline_right( myft, border = big_b, part = "all" )
myft <- hline( myft, border = std_b )
myft <- hline_bottom( myft, border = big_b )
myft <- hline_top( myft, border = big_b, 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 |
Or when borders design is simple with:
border_outer()
: apply a border to outer cells of one or all parts of a flextable.border_inner()
: apply a border to inner cells of one or all parts of a flextable.std_b2 <- fp_border(color="white", style = "dashed")
# remove all defined borders
myft <- border_remove( myft )
myft <- border_outer( myft, border = big_b, part = "all" )
myft <- border_inner_h( myft, border = std_b, part = "all" )
myft <- border_inner_v( myft, border = std_b2, 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 |
Conditional formatting can be made by using the selector arguments.
myft <- color(myft, i = ~ Sepal.Length < 5 & Petal.Length > 1.3,
j = ~ Petal.Width + Species,
color="red")
myft <- bg(myft, j = 1, bg = "#D3C994", part = "header")
myft <- italic(myft, i = ~ Sepal.Length > 5)
myft <- bold(myft, i = 4, j = "Sepal.Length")
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 |
i
and j
arguments can be also standard R vectors:
row_id <- with(head(iris), Sepal.Length < 5 & Petal.Length > 1.3 )
col_id <- c("Petal.Width", "Species")
myft <- color(myft, i = row_id, j = col_id, color="red")
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 |
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:
fp_text
fp_par
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 |
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 |
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.
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.
colformat_num()
with arguments digits
and big.mark
colformat_int()
with arguments big.mark
colformat_char()
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 |
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.
ft <- flextable(head(mtcars, n = 10 ),
col_keys = c("gear", "mpg", "qsec"))
ft <- set_formatter(ft,
mpg = function(x) sprintf("%.04f", x),
gear = function(x) sprintf("%.0f gears", x)
)
ft <- theme_booktabs(ft)
ft <- autofit(ft)
ft
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 |
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):
myft <- compose(
myft, j = "mpg",
value = as_paragraph(
"mpg value is ",
as_chunk(sprintf("%.01f", mpg), props = fp_text(color = "red", bold = TRUE) ) )
)
myft <- autofit(myft)
myft
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 |
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 |
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 |