---
title: "Format content"
output: 
  rmarkdown::html_vignette:
    toc: true 
    toc_depth: 3
vignette: >
  %\VignetteIndexEntry{Format content}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r echo = FALSE}
knitr::opts_chunk$set(
  message = FALSE,
  collapse = TRUE,
  comment = "#>"
)
```


```{r warning=FALSE, echo=FALSE, message=FALSE}
library(officer)
library(flextable)
library(htmltools)
```


By default, the displayed content of each cell will be the 
result of a simple formatting. The content can also be 
*composed* 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.

## Simple functions for formatting content

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 and eventually on a subset of rows.

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()`

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

ft <- flextable(dat)
ft
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)
```


> Their names is `col_format_*` as the first version was not working with rows subset. 
This limitation is no more true and the functions should then be named `format_int`, 
`format_num`... as they can operate on rows and columns.


## 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. 


```{r}
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
```

## compose function

### Usage

`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:

```{r}
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
```

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

![](https://www.ardata.fr/img/illustrations/flextable_compose.svg){width=350px}


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):

```{r}
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
```

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

```{r}
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
```

Or to define specific title headers:

```{r}
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
```

Note that `compose` is not appending but is replacing the content. 

### Limitation for PowerPoint

Using images in flextable is not supported when output format is PowerPoint. This is not a choice nor a unimplemented 
feature. This is because PowerPoint is not able to embed images in a table cell. That's a PowerPoint limitation.

If beeing able to display images in PowerPoint table is important to you, you can use the `plot` function or the 
`save_as_image` and embed the result in the PowerPoint. You will of course loose ability to edit the table in PowerPoint.

### Images

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

```{r}
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
```

Note this chunk option requires package officedown in a R Markdown
context with Word output format.

### minibar

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

```{r}
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)
```

Note this chunk option requires package officedown in a R Markdown
context with Word output format.

### linerange

Function `compose` supports *mini linerange* insertion. Use function `linerange` in `as_paragraph` call:

```{r}
myft <- flextable( head(iris, n = 10 ))

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

autofit(myft)
```

Note this chunk option requires package officedown in a R Markdown
context with Word output format.

### Sugar functions for complex formatting

Functions `as_b`, `as_i`, `as_sub`, `as_sup` are special functions that 
can be used together. They set a value as bold, italic, subscripted or superscripted. This is particularly useful when the headers need complex 
formatting.

```{r}
data <- structure(list(Species = structure(1:3, .Label = c("setosa", 
"versicolor", "virginica"), class = "factor"), col1 = c(5.006, 
5.936, 6.588)), class = "data.frame", row.names = c(NA, -3L))

ft <- flextable(data)
ft
ft <- compose(ft, part = "header", j = "Species", 
    value = as_paragraph(as_i(as_b("Species"))))
ft <- compose(ft, part = "header", j = "col1", 
    value = as_paragraph(as_b("µ"), as_sup("blah")))
ft
```

## Captions

Captions are supported for HTML and Word output (also from a bookdown project
with its specificities taken into account).

Capacities are different from one format to another. For the Word part, we can
produce real auto-numbered captions with a bookmark on the automatic number
which can then be used as a reference, i.e. for cross-referencing. For the HTML
part, you can produce real captions but without the auto-numbering.

Of course, in a bookdown, we benefit from the cross reference capabilities.

The recommended method to set a caption is via the function `set_caption`. If
this function is used, the caption will be defined from here.

Two other methods are available for `knitr` and are presented below in order of
triggering:

1. with knitr's chunk options:

    * `tab.cap.style`: Word style name to use for table captions.
    * `tab.cap.pre`: Prefix for Word numbering chunk (default to "Table").
    * `tab.cap.sep`: Suffix for Word numbering chunk (default to ": ").
    * `tab.cap`: Caption label.
    * `tab.id`: Caption Word bookmark (unique identifier).

2. with knitr chunk and bookdown options (if you're in a bookdown):

    * `tab.cap.style`: Word style name to use for table captions.
    * `tab.cap.pre`: Prefix for Word numbering chunk (default to "Table").
    * `tab.cap.sep`: Suffix for Word numbering chunk (default to ": ").
    * `tab.cap`: Caption label.
    * `label`: Caption reference unique identifier.

(This css instructions is only there to make the caption styled:)

```{css}
caption {
  color:red;
  line-height: 1.5em;
  font-size: 10px;
}
```


```{r}
ft <- set_caption(ft, caption = "this is a caption")
ft
```

You can have a look at R Markdown document illustrating captions for different 
supported format here:

```{r eval=FALSE}
system.file(package = "flextable", "examples", "rmd", "captions")
```

Copy one of these files in your working directory and run knitr:

```{r echo=FALSE}
dir <- system.file(package = "flextable", "examples", "rmd", "captions")
files <- list.files(dir, pattern = "^captions_")
tags$ul(lapply(files, tags$li))
```


## footnotes

Adding footnotes is possible by using function `compose` but it requires a 
two step approach (add the reference symbol and add the corresponding footnote 
in the footer part). 

To make the process simpler, use function `footnote` that will ease the addition 
of footnotes. 

```{r}
ft <- flextable(head(iris))
ft <- footnote( ft, i = 1, j = 1:3,
            value = as_paragraph(
              c("This is footnote one",
                "This is footnote two",
                "This is footnote three")
            ),
            ref_symbols = c("a", "b", "c"),
            part = "header")
ft <- valign(ft, valign = "bottom", part = "header")
autofit(ft)
```

You can also add footnotes inline using the `inline` argument and specify a seperator string with `sep` (default "; ")

```{r}
ft <- flextable(head(iris))
ft <- autofit(ft)
ft <- footnote( ft, i = 1, j = 1:2,
                value = as_paragraph(
                  c("This is footnote one",
                    "This is footnote two")
                ),
                ref_symbols = c("a", "b"),
                part = "header",inline=T)
ft <- footnote( ft, i = 1, j = 3:4,
                value = as_paragraph(
                  c("This is footnote three",
                    "This is footnote four")
                ),
                ref_symbols = c( "c","d"),
                part = "header",inline=T)
ft
```

## Two lines in a cell

> A cell is made of one single paragraph of text. Paragraphs 
can contain several chunks of text with different formatting 
but also images. (see [keypoints](./overview.html#keypoints))

When designed, flextable was not supposed to support soft return (a new line in a paragraph).
As requested by some users, some workarounds have been implemented to let add some `\n` 
as *soft break* in paragraphs. 

With HTML, it works fine. But with Word or PowerPoint it comes with limitations/issues (we are working on it):

* With PowerPoint the padding is also applied where the soft break is written.
* With Word, the text format is lost and the default style is used.

