FlexTable is a set of tools to customize tables, their formats and their contents. Formatting can be done on cells, paragraphs and text. It also lets you to insert headers and footers rows with eventually merged cells.

Table model

Below a representation of the table model implemented with FlexTable.

Grouped header 1.1

Grouped header 2.1

Grouped header 2.2

header_1

header_2

header_3

header_…

header_p

data[1,1]

data[1,2]

data[1,…]

data[1,…]

data[1,p]

data[2,1]

data[2,2]

data[2,…]

data[2,…]

data[2,p]

data[n,1]

data[n,2]

data[n,…]

data[n,…]

data[n,p]

Grouped footer 1.1

Grouped footer 1.2

Grouped footer 2.1

Header rows

Header rows are the gray part of the table. A FlexTable can contain contain several header rows, it can also contain no header rows.

Body content

Body content is the blue part of the table.

  • It can be formatted (texts, paragraphs and cells)
  • Content can be added (from a vector, a data.frame or a matrix).
  • Cells can be merged horizontally or vertically.

Footer rows

Footer rows are the light-blue part of the table. A FlexTable can contain contain several footer rows, it can also contain no footer rows.

Usage

FlexTable require either argument data, a data.frame object or a matrix, either argument numrow and numcol.

When data is provided:

  • To add row.names, use add.rownames = TRUE. Remember that it increments the number of columns of your table.
  • To add data column names as headers, use header.columns = TRUE.

Default format properties can also be specified:

  • body.cell.props: cellProperties object to apply to body cells.
  • body.par.props: parProperties object to apply to body cells.
  • body.text.props: textProperties object to apply to body cells.
  • header.cell.props: cellProperties object to apply to header and footer cells.
  • header.par.props: parProperties object to apply to header and footer cells.
  • header.text.props: textProperties object to apply to header and footer cells.

Below an example. The following dataset will be used:

# library( dplyr )
# 
# data(esoph)
# 
# data_full = esoph %>% 
#   group_by( agegp, alcgp ) %>% 
#   summarize( n = n(),
#   ncases = sum( ncases, na.rm = T ), 
#   ncontrols = sum( ncases, na.rm = T ) )
data_full <- structure(list(agegp = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 6L, 6L,
6L), .Label = c("25-34", "35-44", "45-54", "55-64", "65-74",
"75+"), class = c("ordered", "factor")), alcgp = structure(c(1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c("0-39g/day", "40-79",
"80-119", "120+"), class = c("ordered", "factor")), n = c(4L,
4L, 3L, 4L, 4L, 4L, 4L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L,
3L, 4L, 4L, 3L, 4L, 2L, 2L), ncases = c(0, 0, 0, 1, 1, 4, 0,
4, 1, 20, 12, 13, 12, 22, 24, 18, 11, 25, 13, 6, 4, 4, 2, 3),
    ncontrols = c(0, 0, 0, 1, 1, 4, 0, 4, 1, 20, 12, 13, 12,
    22, 24, 18, 11, 25, 13, 6, 4, 4, 2, 3)), .Names = c("agegp",
"alcgp", "n", "ncases", "ncontrols"), row.names = c(NA, -24L), class = c("data.frame"), drop = TRUE)

data = as.data.frame( head(data_full) )
knitr::kable( data ) 
agegp alcgp n ncases ncontrols
25-34 0-39g/day 4 0 0
25-34 40-79 4 0 0
25-34 80-119 3 0 0
25-34 120+ 4 1 1
35-44 0-39g/day 4 1 1
35-44 40-79 4 4 4

Below a first FlexTable:

FlexTable(data)

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

There are also two shortcut functions to quickly produce FlexTable objects: vanilla.tableand light.table.

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Printing

If R session is interactive, the FlexTable is rendered in an HTML page and loaded into a WWW browser. Within RStudio FlexTable is rendered in the viewer.

Set Layout

Columns widths

FlexTables have their columns autosized to the minimum width. Use setFlexTableWidths to specify each columns widths in inches.

MyFTable <- vanilla.table(data)
MyFTable <- setFlexTableWidths( MyFTable, widths = c(1, 1, rep(0.5, 3) ) )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Header Rows

Add header rows with function addHeaderRow. As we want to add specific header rows, header.columns needs to be set to FALSE.

MyFTable = FlexTable( data = data, header.columns= FALSE )
# add first header row
MyFTable = addHeaderRow( MyFTable, text.properties = textBold(),
  value = c('Factors', 'Summary statistics'), colspan = c(2, 3) )
# add second header row
MyFTable = addHeaderRow( MyFTable, value = names( data ),
  text.properties = textBold() )
MyFTable

Factors

Summary statistics

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Merging data cell

Functions spanFlexTableRows and spanFlexTableColumns are merging cells of a FlexTable object.

There is a special argument runs. It specifies to merge cells that have identical values along runs values.

The following code show usage of this parameter:

MyFTable = FlexTable(data)
MyFTable = spanFlexTableRows( MyFTable, j = 'agegp', runs = as.character( data$agegp ) )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

40-79

4

0

0

80-119

3

0

0

120+

4

1

1

35-44

0-39g/day

4

1

1

40-79

4

4

4

If argument runs is not what you need, there are arguments from and to that let you specify which cells are to be span.

MyFTable = FlexTable(data)
MyFTable = spanFlexTableColumns( MyFTable, i = 2, from = 2, to = 5 )
MyFTable = spanFlexTableRows( MyFTable, j = 2, from = 3, to = 6 )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

25-34

80-119

3

0

0

25-34

4

1

1

35-44

4

1

1

35-44

4

4

4

Rotate headers text of FlexTable

When creating a table, you sometimes have a long table header like “Number of R users by country” and the data in the corresponding column is like “2”, “123”, … That’s an unpleasant mismatch of width. It’s not a problem for two columns, but if you had 10 columns, a better use of space would be to rotate the headers so that the column width can be much narrower.

FlexTable let you manage rotated headers text. It can be specified either with the FlexTable function either whit the addHeaderRow function.

It requires usage of argument text.direction within cellProperties associated with headers. This argument accept one of the following options:

  • lrtb: default value, horizontal text
  • tbrl: 90 degree text rotation
  • btlr: 270 degree text rotation

Method 1

# define a cell properties object with text rotation 
header_cells_props <- cellProperties(
  text.direction = "btlr", background.color = "#00557F", padding = 3 )

header_text_props <- textProperties(
  color = "white", font.size = 11, font.weight = "bold" )

MyFTable <- FlexTable( data = iris[46:55,],
    header.cell.props = header_cells_props, header.text.props = header_text_props,
    body.text.props = textProperties( font.size = 10 ) ) %>%
  setFlexTableWidths( widths = c(.5, .5, .5, .5, .8 ))
MyFTable[] = parCenter()

doc <- pptx( title = "title" ) %>% 
  addSlide( slide.layout = "Title and Content" ) %>% 
  addFlexTable( MyFTable )
filename <- "header_rot.pptx" # the document to produce
writeDoc( doc, file = filename )

Method 2

parprop <- parProperties(padding = 2)
cellprop <- cellProperties( text.direction = "btlr" )
MyFTable <- FlexTable( data = iris[46:55, ], header.columns = FALSE ) %>% 
  addHeaderRow( value = c("Sepal", "Petal", ""), colspan = c( 2, 2, 1),
                par.properties = parprop ) %>% 
  addHeaderRow( value=c("Length", "Width", "Length", "Width", "Species"),
    par.properties = parprop, cell.properties = cellprop )

doc <- docx(  ) %>% 
  addFlexTable( MyFTable )
filename <- "header_rot.docx" # the document to produce
writeDoc( doc, file = filename )

Format table

Change cell background color

MyFTable <- FlexTable(data)
# change background colors of some cells in the table body
MyFTable <- setFlexTableBackgroundColors(MyFTable, j = 4,
  colors = ifelse(data$ncases < 5, '#DDDDDD', 'orange'))
# change background colors of a cell in the table header
MyFTable <- setFlexTableBackgroundColors(MyFTable, i = 1, j = 1,
  colors = '#8888F0', to = 'header')
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Set columns or rows background colors

Modify rows or columns backgroud colors with setRowsColors and setColumnsColors.

MyFTable = FlexTable( data = data )
MyFTable = setRowsColors( MyFTable, i=3:4, colors = '#666633' )
MyFTable = setColumnsColors( MyFTable, j=3, colors = '#990033' )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Zebra striped tables

Modify rows or columns backgroud colors with setRowsColors and setColumnsColors.

MyFTable = vanilla.table( data = data )
MyFTable = setZebraStyle( MyFTable, odd = '#eeeeee', even = 'white' )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Format cell text values

MyFTable = FlexTable(data)
# format body content
MyFTable[, 4:5] = textProperties( color = '#2BBBD8' )
# format header content
MyFTable[, 4:5, to = 'header'] = textProperties( color = '#2BBBD8', font.weight = 'bold' )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Format cells

MyFTable = FlexTable(data)
# format body content
MyFTable[3:4, 'n'] = cellProperties( background.color = 'red' )
# format header content
MyFTable[, 'n', to = 'header'] = cellProperties( background.color = 'orange' )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Format paragraphs

MyFTable = FlexTable(data)
MyFTable <- setFlexTableWidths( MyFTable, widths = c(1, 1, rep(0.5, 3) ) )
MyFTable[,c('agegp', 'alcgp')] = parRight()
MyFTable[,c('agegp', 'alcgp'), to = 'header'] = parRight()
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Change borders

border_ <- borderProperties( style = 'dashed' )
MyFTable[,'alcgp', side = 'bottom'] <- border_
MyFTable[,'alcgp', to = 'header', side = 'bottom'] <- chprop(border_, color = "red")
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Conditional formatting example

# the default cellProperties
myCellProps = cellProperties( )

MyFTable = FlexTable( data = data,
                      header.text.props = textBold(),
                      header.cell.props = myCellProps,
                      body.cell.props= myCellProps )

# modify the default cellProperties and apply
# it to cells of columns 4 to 8 where n < 20
MyFTable[ data$ncases < 1, 3:5] = chprop( myCellProps, background.color = '#666633')
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

apply chrprop to FlexTable

tp <- textProperties( color = '#2BBBD8', font.weight = 'bold' )
MyFTable <- FlexTable( data = data, header.text.props = textBold(),
  header.cell.props = myCellProps, body.cell.props= myCellProps )
MyFTable <- chprop( MyFTable, i = data$ncases < 1, j = 3:5, value = tp )
MyFTable <- chprop( MyFTable, i = data$ncases < 1, j = 3:5, value = parCenter() )
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4

0

0

25-34

40-79

4

0

0

25-34

80-119

3

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

Annotations

You can add content with the substract operator.

Function has an argument text.properties to specify text formatting properties:

MyFTable[data$ncases < 1, 'n',
  text.properties = textBold( vertical.align = 'superscript')] = '(1)'
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

0-39g/day

4(1)

0

0

25-34

40-79

4(1)

0

0

25-34

80-119

3(1)

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4

And an argument newpar to let create new paragraphs into cells.

MyFTable[1, 1, text.properties = textBold(color = 'red'), newpar = TRUE] = 'newpar usage'
MyFTable

agegp

alcgp

n

ncases

ncontrols

25-34

newpar usage

0-39g/day

4(1)

0

0

25-34

40-79

4(1)

0

0

25-34

80-119

3(1)

0

0

25-34

120+

4

1

1

35-44

0-39g/day

4

1

1

35-44

40-79

4

4

4