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")
myftSepal.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)
myftSepal.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")
ftSepal.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" )
myftSepal.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" )
myftSepal.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")
myftSepal.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")
myftSepal.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_textfp_parfp_cell and fp_borderlibrary(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")
ftmpg | 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.markcolformat_int() with arguments big.markcolformat_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)
ftgear | 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)
myftam | 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)
myftam | 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)
myftam | 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)
myftam | 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)
myftam | 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 |