# Table layout

`flextable` layout can be managed with few functions.

    library(flextable)
    library(officer)

## Cell merging

### vertical merging

`merge_v()` will merge adjacent duplicated cells for each column of the selection.

    select_columns <- c("Species", "Petal.Length", "Petal.Width")
    myft <- regulartable(iris[46:55,], col_keys = select_columns)
    myft <- merge_v(myft, ~ Species + Petal.Width )
    myft

Species | Petal.Length | Petal.Width
setosa | 1.400 | 0.300
1.600 | 0.200
1.400
1.500
1.400
versicolor | 4.700 | 1.400
4.500 | 1.500
4.900
4.000 | 1.300
4.600 | 1.500

### horizontal merging

`merge_h()` will merge adjacent duplicated cells for each row of the selection.

    select_columns <- c("Species", "Petal.Length", "Petal.Width")
    myft <- regulartable(head(mtcars, n = 10 ) )
    myft <- merge_h(myft)
    # and add borders
    myft <- border(myft, border = fp_border(), part = "all")
    myft

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
21.000 | 6.000 | 160.000 | 110.000 | 3.900 | 2.875 | 17.020 | 0.000 | 1.000 | 4.000
22.800 | 4.000 | 108.000 | 93.000 | 3.850 | 2.320 | 18.610 | 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 | 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 | 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

### general merging function

`merge_h()` will merge cells for a given continuous selection of rows and cells.

    select_columns <- c("Species", "Petal.Length", "Petal.Width")
    myft <- regulartable(head(mtcars, n = 6 ) )
    myft <- merge_at( myft, i = 1:3, j = 1:3)
    myft <- border(myft, border = fp_border(), part = "all")
    myft

mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb
21.000 | 110.000 | 3.900 | 2.620 | 16.460 | 0.000 | 1.000 | 4.000 | 4.000
110.000 | 3.900 | 2.875 | 17.020 | 0.000 | 1.000 | 4.000 | 4.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

### delete merging informations

If you want to get rid of all merging (i.e. for development purposes), use `merge_none()`:

    merge_none(myft)

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

## Manage headers and footers

For illustration, we will mainly work with headers but same can be apply with footers (use functions `add_footer()` or `set_header_df()` instead).

### col_keys

Parameter `col_keys` define the variables to display and their order.

    data <- iris[c(1:3, 51:53, 101:104),]

    myft <- regulartable(data, col_keys = c("Species", "Sepal.Length", "Petal.Length") )
    myft

Species | Sepal.Length | Petal.Length
setosa | 5.100 | 1.400
setosa | 4.900 | 1.400
setosa | 4.700 | 1.300
versicolor | 7.000 | 4.700
versicolor | 6.400 | 4.500
versicolor | 6.900 | 4.900
virginica | 6.300 | 6.000
virginica | 5.800 | 5.100
virginica | 7.100 | 5.900
virginica | 6.300 | 5.600

If parameter `col_keys` has variables that are not existing in the dataset, they will be considered as blank columns and can be used as separators (in fact they can be use as you want, there is only no mapping of data associated).

    myft <- regulartable(
      data = data,
      col_keys = c("Species", "col_1", "Sepal.Length", "Petal.Length") )
    myft <- theme_vanilla(myft)
    myft <- autofit(myft)
    myft <- empty_blanks(myft)
    myft

Species |  | Sepal.Length | Petal.Length
setosa |  | 5.100 | 1.400
setosa |  | 4.900 | 1.400
setosa |  | 4.700 | 1.300
versicolor |  | 7.000 | 4.700
versicolor |  | 6.400 | 4.500
versicolor |  | 6.900 | 4.900
virginica |  | 6.300 | 6.000
virginica |  | 5.800 | 5.100
virginica |  | 7.100 | 5.900
virginica |  | 6.300 | 5.600

`col_keys` default values are the names of the data.frame used to fill the flextable.

### Change labels

Use `set_header_labels()` to replace labels of the bottom row of header.

    ft <- regulartable( head( iris ) )
    ft <- set_header_labels(ft, Sepal.Length = "Sepal",
        Sepal.Width = "Sepal", Petal.Length = "Petal",
        Petal.Width = "Petal", Species = "Species" )
    ft <- theme_vanilla(ft)
    ft <- autofit(ft)
    ft

Sepal | Sepal | Petal | Petal | 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 a row of labels

Use `add_header()` to add an header row.

    ft <- add_header(ft, Sepal.Length = "length",
        Sepal.Width = "width", Petal.Length = "length",
        Petal.Width = "width", Species = "Species", top = FALSE )
    ft <- theme_vanilla(ft)
    ft <- autofit(ft)
    ft

Sepal | Sepal | Petal | Petal | Species
length | width | length | 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

    ft <- add_header(ft, Sepal.Length = "Inches",
        Sepal.Width = "Inches", Petal.Length = "Inches",
        Petal.Width = "Inches", Species = "Species", top = TRUE )

    ft <- add_footer(ft, Sepal.Length = "* This is a note" )
    ft <- color(ft, color = "orange", part = "footer" )

    # merge identical cells
    ft <- merge_h(ft, part = "header")
    ft <- merge_v(ft, part = "header")
    ft <- merge_at(ft, i = 1, j = 1:5, part = "footer")

    ft <- theme_booktabs(ft)
    ft

Inches | Species
Sepal | Petal
length | width | length | width
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
* This is a note

### Define headers with a reference table

Use `set_header_df()` with a data.frame as parameter. Columns of the dataset will be transposed and joined using a key column.

#### Input dataset

Variable `col_keys` define key values to match with flextable column keys (defined by argument `col_keys` of `flextable()` function).

This key column will not be displayed. Other variables will added as rows. Note that variables names are not displayed.

    typology <- data.frame(
      col_keys = c( "Sepal.Length", "Sepal.Width", "Petal.Length",
                    "Petal.Width", "Species" ),
      type = c("double", "double", "double", "double", "factor"),
      what = c("Sepal", "Sepal", "Petal", "Petal", "Species"),
      measure = c("Length", "Width", "Length", "Width", "Species"),
      stringsAsFactors = FALSE )
    autofit( theme_vanilla(flextable(typology)) )

col_keys | type | what | measure
Sepal.Length | double | Sepal | Length
Sepal.Width | double | Sepal | Width
Petal.Length | double | Petal | Length
Petal.Width | double | Petal | Width
Species | factor | Species | Species

#### Add the dataset as header rows

Then use `set_header_df()` with parameter `key` that specifies name of the column used to permform the join. Order of columns matters, first column will be first row, second one will be the second row, etc.

    ft <- regulartable( head( iris ) )
    ft <- set_header_df( ft, mapping = typology, key = "col_keys" )

    ft <- merge_h(ft, part = "header")
    ft <- merge_v(ft, part = "header")

    ft <- theme_vanilla(ft)
    ft <- autofit(ft)
    ft

double | factor
Sepal | Petal | Species
Length | Width | Length | Width
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

## Cell widths and heights

The default sizes of flextable columns and rows are set by default values. This will drive to inadequate rows heights and columns widths in some cases. You can use function `dim` to get flextable dimensions.

    ft_base <- regulartable(head(iris))
    ft_base <- theme_tron_legacy(ft_base)
    ft_base

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

    dim(ft_base)
    #> $widths
    #> Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
    #>         0.75         0.75         0.75         0.75         0.75
    #>
    #> $heights
    #> [1] 0.25 0.25 0.25 0.25 0.25 0.25 0.25

### Pretty dimensions

Function `dim_pretty()` is computing optimized widths and heights.

    dim_pretty(ft_base)
    #> $widths
    #> [1] 0.9460630 0.8688196 0.9074752 0.8302318 0.5991121
    #>
    #> $heights
    #> [1] 0.2044994 0.1756366 0.1756366 0.1756366 0.1756366 0.1756366 0.1756366

### Adjusts automatically cell widths and heights

Function `autofit()` optimises widths and heights of the flextable. This function is almost always to be called once when using flextable objects, it makes compact tables.

    ft <- autofit(ft_base, add_w = 0, add_h = 0)

    dim(ft)
    #> $widths
    #> Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species
    #>    0.9460630    0.8688196    0.9074752    0.8302318    0.5991121
    #>
    #> $heights
    #> [1] 0.2044994 0.1756366 0.1756366 0.1756366 0.1756366 0.1756366 0.1756366
    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

> Soft returns support : function `autofit` and `dim_pretty` do not support soft returns and may return wrong results (will be considered as “”).

### Adjusts manually cell widths and heights

Function `width()` and `height()` let you control dimensions of a flextable. `height_all()` is an helper function to set the same height to each part of the table.

    ft <- autofit(ft_base)
    ft <- width(ft, j = ~ Species, width = 2)
    ft <- height_all( ft, height = .4 )
    ft <- height( ft, i = 3, height = 1 )
    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