---
title: "Word documents generation"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Word}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


```{r, echo = FALSE, message=FALSE, warning=FALSE}
dir.create("assets/docx", recursive = TRUE, showWarnings = FALSE)
office_doc_link <- function(url){
  stopifnot(requireNamespace("htmltools", quietly = TRUE))
  htmltools::tags$p(  htmltools::tags$span("Download file "),
    htmltools::tags$a(basename(url), href = url), 
    htmltools::tags$span(" - view with"),
    htmltools::tags$a("office web viewer", target="_blank", 
      href = paste0("https://view.officeapps.live.com/op/view.aspx?src=", url)
      ), 
    style="text-align:center;font-style:italic;color:gray;"
    )
}
```

```{r}
library(officer)
# Package `magrittr` makes officer usage easier.
library(magrittr)
```

<div style="text-align:center;">
<img src="data:image/png;base64, " width="128" height="128"/>
</div>

## Quick start

1. Start with `read_docx`

Use the function `read_docx()` to create an R object representing a Word 
document.

The initial Word file can be specified with the `path` argument. If none is 
provided, this file will be an empty document located in the package directory. 
Formats and styles are defined in the initial file.

From the initial document, we will be able to use an object containing not only 
paragraph styles, character styles and table styles of the original document but 
also its content.

```{r}
my_doc <- read_docx() 
styles_info(my_doc)
```

2. Add elements to document

> By default new content is added at the end of the document. To understand how 
to add content at any location in the document, see the later section about 
cursor manipulation.

Let's create an image from a plot...

```{r results='hide'}
src <- tempfile(fileext = ".png")
png(filename = src, width = 5, height = 6, units = 'in', res = 300)
barplot(1:10, col = 1:10)
dev.off()
```

...and add that image to the document along with some new text paragraphs and a 
table.

```{r results='hide'}
my_doc <- my_doc %>% 
  body_add_img(src = src, width = 5, height = 6, style = "centered") %>% 
  body_add_par("Hello world!", style = "Normal") %>% 
  body_add_par("", style = "Normal") %>% # blank paragraph
  body_add_table(iris, style = "table_template")
```

3. Write the Word file

An (updated) Word file can be generated using the `print()` function with the 
`target` argument:

```{r results='hide'}
print(my_doc, target = "assets/docx/first_example.docx")
```

```{r echo=FALSE}
office_doc_link(url = paste0("https://davidgohel.github.io/officer/articles/", "assets/docx/first_example.docx"))
```



## Adding elements

There are two types of functions for adding elements.

- add content as a paragraph: images, tables, text. Use `body_add_*` functions:
    - body_add_par
    - body_add_img
    - body_add_table
    - body_add_break
    - body_add_toc
    - body_add_gg
    
- add text or image inside an existing paragraph. Use `slip_in_*` functions:
    - slip_in_img
    - slip_in_seqfield
    - slip_in_text
    
    The content is appened into the paragraph where the cursor is.

### `body_add_*` functions

The paragraph is the main top container for content within a Word document. 
*Note that tables are top container, they are at the same level as paragraphs*. 
`body_add_*` functions are designed to **add content as a top container**: text 
as an entire paragraph, table, image, page break...

A title is a paragraph. To add a title, use `body_add_par()` with the `style` 
argument pointing to the corresponding title style.

Use the function `styles_info()` to see available styles:

```{r message=FALSE}
read_docx() %>% styles_info() %>% 
  subset( style_type %in% "paragraph" )
```

> It is important to understand that these style names are read in the initial 
file provided to `read_docx()`. A few comments:

* One of the styles is *heading 1* which corresponds to a level 1 title. 
* When using `body_add_gg()` in the following code, using `style = "centered"` 
will set *centered* paragraph properties (defined as centered in the initial 
document) to the new paragraph where the plot will be added.
* Table templates are also defined in the initial document and can be used with 
`body_add_table()`. For advanced tabular formatting, use the `flextable` package 
instead ([flextable website](https://davidgohel.github.io/officer/)). It has a 
function `body_add_flextable()` that can be used with `officer`.

```{r}
if( require("ggplot2") ){
  gg <- ggplot(data = iris, aes(Sepal.Length, Petal.Length)) + 
    geom_point()
  
  read_docx() %>% 
    body_add_par(value = "Table of content", style = "heading 1") %>% 
    body_add_toc(level = 2) %>% 
    body_add_break() %>% 
  
    body_add_par(value = "dataset iris", style = "heading 2") %>% 
    body_add_table(value = head(iris), style = "table_template" ) %>% 
    
    body_add_par(value = "plot examples", style = "heading 1") %>% 
    body_add_gg(value = gg, style = "centered" ) %>% 
  
    print(target = "assets/docx/body_add_demo.docx")
}
```

```{r echo=FALSE, message=FALSE}
if( require("ggplot2") ){
  office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/body_add_demo.docx" ) )
}
```

### `slip_in_*` functions

The `slip_in_*` functions are designed to add content 
**inside an existing paragraph**: text, image or seq field. The element is 
inserted either at the beginning or end of the paragraph 
(`pos = c('after', 'before')`). Available functions are the following:

- `slip_in_img()`
- `slip_in_seqfield()`
- `slip_in_text()`

```{r}
img.file <- file.path( R.home("doc"), "html", "logo.jpg" )
read_docx() %>%
  body_add_par("R logo: ", style = "Normal") %>%
  slip_in_img(src = img.file, style = "strong", 
              width = .3, height = .3, pos = "after") %>% 
  slip_in_text(" - This is ", style = "strong", pos = "before") %>% 
  slip_in_seqfield(str = "SEQ Figure \u005C* ARABIC",
    style = 'strong', pos = "before") %>% 
  print(target = "assets/docx/slip_in_demo.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/slip_in_demo.docx" ) )
```

These have been implemented mostly to allow the addition of Word's special 
sequence fields (which facilitate numbering) at the beginning of paragraphs used 
as reference entries (e.g. a table or plot caption). See the section 
*Table and image captions*.

## Cursor manipulation

A cursor is available and can be manipulated so that content can be added 
relative to its position with the `body_add_*` functions: 

- `before` will insert a new element before the selected element in the document.
- `after` will insert a new element after the selected element in the document.
- `on` will replace the selected element in the document by a new element.

Cursor functions are the following:

- `cursor_begin()`
- `cursor_end()`
- `cursor_reach()`
- `cursor_backward()`
- `cursor_forward()`
- `cursor_bookmark()`

In order to illustrate the *cursor* functions, a document made up of several 
paragraphs will be used (let's use officer for that).

```{r}
read_docx() %>%
  body_add_par("paragraph 1", style = "Normal") %>%
  body_add_par("paragraph 2", style = "Normal") %>%
  body_add_par("paragraph 3", style = "Normal") %>%
  body_add_par("paragraph 4", style = "Normal") %>%
  body_add_par("paragraph 5", style = "Normal") %>%
  body_add_par("paragraph 6", style = "Normal") %>%
  body_add_par("paragraph 7", style = "Normal") %>%
  print(target = "assets/docx/init_doc.docx" )
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/init_doc.docx" ) )
```

Now, let's use `init_doc.docx` with `read_docx()` and manipulate its content 
with cursor functions.

```{r}
doc <- read_docx(path = "assets/docx/init_doc.docx") %>%

  # default template contains only an empty paragraph
  # Using cursor_begin and body_remove, we can delete it
  cursor_begin() %>% body_remove() %>%

  # Let add text at the beginning of the
  # paragraph containing text "paragraph 4"
  cursor_reach(keyword = "paragraph 4") %>%
  slip_in_text("This is ", pos = "before", style = "Default Paragraph Font") %>%

  # move the cursor forward and end a section
  cursor_forward() %>%
  body_add_par("The section stop here", style = "Normal") %>%
  body_end_section(landscape = TRUE, continuous = FALSE) %>%

  # move the cursor at the end of the document
  cursor_end() %>%
  body_add_par("The document ends now", style = "Normal")

print(doc, target = "assets/docx/cursor.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/cursor.docx" ) )
```

## Remove content

The function `body_remove()` lets you remove content from a Word document. This 
function used with `cursor_*` functions is a convenient tool to update an 
existing document.

For illustration purposes, we will generate a document that will be used as 
an initial document later when showing how to use `body_remove()`.


```{r}
library(officer)
library(magrittr)

str1 <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " %>% 
  rep(20) %>% paste(collapse = "")
str2 <- "Drop that text" 
str3 <- "Aenean venenatis varius elit et fermentum vivamus vehicula. " %>% 
  rep(20) %>% paste(collapse = "")

my_doc <- read_docx()  %>% 
  body_add_par(value = str1, style = "Normal") %>% 
  body_add_par(value = str2, style = "centered") %>% 
  body_add_par(value = str3, style = "Normal") 

print(my_doc, target = "assets/docx/ipsum_doc.docx")
```

The file `ipsum_doc.docx` now exists and contains a paragraph containing text 
*that text*. In the following example, we will position the cursor on that 
paragraph and then delete it:

```{r}
my_doc <- read_docx(path = "assets/docx/ipsum_doc.docx")  %>% 
  cursor_reach(keyword = "that text") %>% 
  body_remove()

print(my_doc, target = "assets/docx/ipsum_doc.docx")
```

**The text search is made via `xpath 1.0` and regular expressions are not supported.**

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/ipsum_doc.docx" ) )
```

## Replace content

The `body_add_*` functions let you replace content in a Word document.

For illustration purposes, we will generate a document that will be used as 
an initial document later.

```{r results='hide'}
my_doc <- read_docx()  %>% 
  body_add_par(value = str1, style = "Normal") %>% 
  body_add_par(value = str2, style = "centered") %>% 
  body_add_par(value = str3, style = "Normal") 

print(my_doc, target = "assets/docx/replace_template.docx")
```

The file `replace_template.docx` now exists and contains a paragraph containing 
text *that text*. In the following example, we will position the cursor on that 
paragraph and then replace it. Using `pos = "on"` will replace content where 
the cursor is with new content.

```{r results='hide'}
my_doc <- read_docx(path = "assets/docx/replace_template.docx")  %>% 
  cursor_reach(keyword = "that text") %>% 
  body_add_par(value = "This is a new paragraph.", style = "centered", pos = "on")

print(my_doc, target = "assets/docx/replace_doc.docx")
```

### Search-and-replace

You can also use the `body_replace_*` functions to search-and-replace text. 
`body_replace_text_at_bkm()` replaces text at a bookmark:

```{r results='hide'}
doc <- read_docx() %>%
  body_add_par("centered text", style = "centered") %>%
  slip_in_text(". How are you", style = "strong") %>%
  body_bookmark("text_to_replace") %>%
  body_replace_text_at_bkm("text_to_replace", "not left aligned")
```

To do the same with headers and footers of the Word document, use functions 
`headers_replace_text_at_bkm` and `footers_replace_text_at_bkm`.


`body_replace_all_text()` will, depending on the options provided, replace text 
either at the cursor or in the entire document:

```{r results='hide'}
doc <- read_docx() %>%
  body_add_par("Placeholder one") %>%
  body_add_par("Placeholder two")

# Show text chunk at cursor
docx_show_chunk(doc)  # Output is 'Placeholder two'

# Simple search-and-replace at current cursor, with regex turned off
body_replace_all_text(doc, "Placeholder", "new", only_at_cursor = TRUE, fixed=TRUE)
docx_show_chunk(doc)  # Output is 'new two'

# Do the same, but in the entire document and ignoring case
body_replace_all_text(doc, "placeholder", "new", only_at_cursor = FALSE, ignore.case=TRUE)
cursor_backward(doc)
docx_show_chunk(doc) # Output is 'new one'

# Use regex : replace all words starting with "n" with the word "example"
body_replace_all_text(doc, "\\bn.*?\\b", "example")
docx_show_chunk(doc) # Output is 'example one'
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/replace_doc.docx" ) )
```

To do the same with headers and footers of the Word document, use functions 
`headers_replace_all_text` and `footers_replace_all_text`.


## Sections

> A section starts at the end of the previous section (or the beginning of the 
document if no preceding section exists). It stops where the section is declared.

Sections can be added to a document by using a set of functions: 

* `body_end_section_landscape()`
* `body_end_section_portrait()`
* `body_end_section_columns()`
* `body_end_section_columns_landscape()`
* `body_end_section_continuous()`

To add content into a **landscape section**, you will need to :

1. Declare an ending section just before the content to be displayed 
in landscape orientation. Use function `body_end_section_continuous()`. 
2. Add the content to be displayed in landscape orientation.
3. Declare an ending section just after the content to be displayed 
in landscape orientation. Use function `body_end_section_landscape()`. 

```{r}
str1 <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " %>% 
  rep(5) %>% paste(collapse = "")
str2 <- "Aenean venenatis varius elit et fermentum vivamus vehicula. " %>% 
  rep(5) %>% paste(collapse = "")

my_doc <- read_docx()  %>% 
  body_add_par(value = str1, style = "centered") %>% 
  body_end_section_continuous() %>% 
  body_add_par(value = str2, style = "centered") %>% 
  body_end_section_landscape() 
print(my_doc, target = "assets/docx/landscape_section.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/landscape_section.docx" ) )
```




To add content into a **section with columns**, you will need to :

1. Declare an ending section just before the content to be displayed 
in landscape orientation. Use function `body_end_section_continuous()`. 
2. Add the content to be displayed in landscape orientation.
3. Declare an ending section just after the content to be displayed 
in landscape orientation. Use function `body_end_section_columns()`. 

Function `slip_in_column_break()` can be used to add a column break. As it starts a new column, 
it has to be used on the paragraph where the break happens. By default `slip_in_column_break()` 
insert a column break at the beginning of the paragraph where the cursor is.

```{r}
my_doc <- read_docx()  %>% 
  body_end_section_continuous() %>% 
  body_add_par(value = str1, style = "centered") %>% 
  body_add_par(value = str2, style = "centered") %>% 
  slip_in_column_break() %>%
  body_add_par(value = str2, style = "centered") %>% 
  body_end_section_columns(widths = c(2,2), sep = TRUE, space = 1) 
print(my_doc, target = "assets/docx/columns_section.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/columns_section.docx" ) )
```

To add content into a **section with columns and landscape orientation**, you will need to :

1. Declare an ending section just before the content to be displayed 
in landscape orientation. Use function `body_end_section_continuous()`. 
2. Add the content to be displayed in landscape orientation.
3. Declare an ending section just after the content to be displayed 
in landscape orientation. Use function `body_end_section_columns_landscape()`. 

```{r}
my_doc <- read_docx()  %>% 
  body_end_section_continuous() %>% 
  body_add_par(value = str1, style = "Normal") %>% 
  body_add_par(value = str2, style = "Normal") %>% 
  body_end_section_columns_landscape(widths = c(3,3), sep = TRUE, space = 1) 
print(my_doc, target = "assets/docx/columns_landscape_section.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/columns_landscape_section.docx" ) )
```


The following example demonstrate all known usages:

```{r}
my_doc <- read_docx()  %>% 
  body_add_par(value = "Default section", style = "heading 1") %>% 
  body_add_par(value = str1, style = "centered") %>% 
  body_add_par(value = str2, style = "centered") %>% 

  body_end_section_continuous() %>% 
  body_add_par(value = "Landscape section", style = "heading 1") %>% 
  body_add_par(value = str1, style = "centered") %>% 
  body_add_par(value = str2, style = "centered") %>% 
  body_end_section_landscape() %>% 
  
  body_add_par(value = "Columns", style = "heading 1") %>% 
  body_end_section_continuous() %>% 
  body_add_par(value = str1, style = "centered") %>% 
  body_add_par(value = str2, style = "centered") %>% 
  slip_in_column_break() %>%
  body_add_par(value = str1, style = "centered") %>% 
  body_end_section_columns(widths = c(2,2), sep = TRUE, space = 1) %>% 

  body_add_par(value = str1, style = "Normal") %>% 
  body_add_par(value = str2, style = "Normal") %>% 
  slip_in_column_break() %>%
  body_end_section_columns_landscape(widths = c(3,3), sep = TRUE, space = 1)

print(my_doc, target = "assets/docx/section.docx")
```

```{r echo=FALSE}
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/section.docx" ) )
```

## Table and image captions

`slip_in_seqfield()` and `slip_in_text()` can be combined to prefix a paragraph 
with references (i.e. chapter number and graphic index in the document). However, 
producing a plot or a table and its caption can be verbose.

Shortcut functions are implemented in the object `shortcuts` (it will at least 
give you a template of code to modify if it does not fit your needs exactly). 
`slip_in_tableref()`, `slip_in_plotref()` and `body_add_gg()` can make life 
easier.

Usage of these functions is illustrated below:

```{r}
library(magrittr)
library(officer)
if( require("ggplot2") ){

gg1 <- ggplot(data = iris, aes(Sepal.Length, Petal.Length)) + 
  geom_point()
gg2 <- ggplot(data = iris, aes(Sepal.Length, Petal.Length, color = Species)) + 
  geom_point()


doc <- read_docx() %>% 
  body_add_par(value = "Table of content", style = "heading 1") %>% 
  body_add_toc(level = 2) %>% 
  
  body_add_par(value = "Tables", style = "heading 1") %>% 
  body_add_par(value = "dataset mtcars", style = "heading 2") %>% 
  body_add_table(value = head(mtcars)[, 1:4], style = "table_template" ) %>% 
  body_add_par(value = "data mtcars", style = "table title") %>% 
  shortcuts$slip_in_tableref(depth = 2) %>%
  
  body_add_par(value = "dataset iris", style = "heading 2") %>% 
  body_add_table(value = head(iris), style = "table_template" ) %>% 
  body_add_par(value = "data iris", style = "table title") %>% 
  shortcuts$slip_in_tableref(depth = 2) %>%
  
  body_end_section(continuous = FALSE, landscape = FALSE ) %>% 
  
  body_add_par(value = "plot examples", style = "heading 1") %>% 
  body_add_gg(value = gg1, style = "centered" ) %>% 
  body_add_par(value = "graph example 1", style = "graphic title") %>% 
  shortcuts$slip_in_plotref(depth = 1) %>%
  
  body_add_par(value = "plot 2", style = "heading 2") %>% 
  body_add_gg(value = gg2, style = "centered" ) %>% 
  body_add_par(value = "graph example 2", style = "graphic title") %>% 
  shortcuts$slip_in_plotref(depth = 2) %>%
  
  body_end_section(continuous = FALSE, landscape = TRUE) %>% 
  
  body_add_par(value = "Table of tables", style = "heading 2") %>% 
  body_add_toc(style = "table title") %>% 
  body_add_par(value = "Table of graphics", style = "heading 2") %>% 
  body_add_toc(style = "graphic title")

print(doc, target = "assets/docx/toc_and_captions.docx")
}
```

```{r echo=FALSE}
if( require("ggplot2") ){
  office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/docx/toc_and_captions.docx" ) )
}
```

