---
title: "PowerPoint presentations generation"
output: 
  rmarkdown::html_vignette:
    toc: true 
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{PowerPoint}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


```{r, echo = FALSE, message=FALSE, warning=FALSE}
dir.create("assets/pptx", 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>


## Introduction

Use the function `read_pptx()` to create an R object representing a PowerPoint 
document. The initial PowerPoint 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 available slide layouts will be those available in the 
template file. The content of original document is also preserved (but can be 
manipulated, i.e. delete a slide).
 
```{r}
my_pres <- read_pptx() 
```

### Add a slide

To add a new slide, use the function `add_slide()`. It requires 3 arguments: 

- an rpptx object
- a slide layout name
- a master layout name

```{r}
my_pres <- my_pres %>% 
  add_slide(layout = "Title and Content", master = "Office Theme")
```

**Note that the `layout` and `master` values must match values from the initial document.** 
Layout names and master layout names are not available in a tidy view within
PowerPoint, but these can be read easily with the function `layout_summary()`.


```{r}
layout_summary(my_pres)
```

#### master layouts and slide layouts

`officer` uses a PowerPoint file as the initial document. This is the original
PowerPoint document where all slide layouts, shapes (placeholders) and
styles come from. Major points to be aware of are:

* Slide layouts are relative to a master layout. A document can contain one or 
more master layouts; a master layout can contain one or more slide layouts. 
* A slide layout inherits design properties from its master layout but some 
properties can be overwritten.
* Designs and formatting properties of layouts and shapes (placeholders in a 
layout) are defined within the initial document. There is no R function to 
modify these values - they must be defined in the initial document.



### Add text content into a placeholder

Use the function `ph_with_text()` to add text into a new shape. The type of the 
shape is defined in the slide layout associated with the current slide. For 
example, using `type = "title"` will create a title shape in the current slide.


```{r}
my_pres <- my_pres %>% 
  ph_with_text(type = "title", str = "A title") %>%
  ph_with_text(type = "ftr", str = "A footer") %>%
  ph_with_text(type = "dt", str = format(Sys.Date())) %>%
  ph_with_text(type = "sldNum", str = "slide 1") %>%
  ph_with_text(str = "Hello world", type = "body")
```

> The function `layout_properties` provides details about the available shapes 
for a slide layout.

You can use columns `type`, `id` but also `ph_label` to identify or recognize shapes.
`ph_label` is the label that can be associated to a placeholder in a slide template. 
`type` and `id` are often required to identify which placeholder should receive a content.

```{r}
layout_properties ( x = my_pres, layout = "Two Content", master = "Office Theme" ) %>% head()
```

#### generate an annotated file from base template

The function `annotate_base()` can be used to generate a PowerPoint file from a template. The title of each slide will contain the `layout` and `master` names and each body element will have the `index` identified. This provides a visual method for linking slide elements to the relevant layout attributes. 

```{r}
annotate_base(output_file = "assets/pptx/annotated_layout.pptx")
```

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

### Write the PowerPoint file

The (updated) Powerpoint file can be generated using the `print()` function 
along with the `target` argument:

```{r}
print(my_pres, target = "assets/pptx/first_example.pptx") 
```

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

## Slide selection and manipulation

There are 3 functions to let you manipulate slides: `add_slide()`, 
`remove_slide()` and `on_slide()`.

A slide can be added with the `add_slide()` function.

```{r}
my_pres <- read_pptx() %>% 
  add_slide(layout = "Two Content", master = "Office Theme") %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  add_slide(layout = "Title Only", master = "Office Theme")
length(my_pres)
```

A slide can be removed with the `remove_slide()` function.

```{r}
my_pres <- my_pres %>% remove_slide(index = 1)
length(my_pres)
```

A slide can be selected with the `on_slide()` function.

```{r}
my_pres <- my_pres %>% on_slide(index = 1)
```


## Add content into a placeholder

### Add text

Use the function `ph_with_text()` to add text into a new shape. The `type` 
argument specifies which placeholder from the associated layout is to be added 
(`index` is to be used when a `type` is not unique in the slide layout).


```{r}
doc <- read_pptx() %>%
  add_slide(layout = "Two Content", master = "Office Theme") %>%
  ph_with_text(type = "body", str = "A first text", index = 1) %>%
  ph_with_text(type = "body", str = "A second text", index = 2) %>%
  ph_with_text(type = "title", str = "A title") %>%
  ph_with_text(type = "ftr", str = "Slide footer") %>%
  ph_with_text(type = "dt", str = format(Sys.Date()))

print(doc, target = "assets/pptx/ph_with_text.pptx") 
```

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

Again, use `layout_properties()` to see what placeholders are available in the 
slide layout.

### Add image

Use the function `ph_with_img()` to add an image into a placeholder. As for all 
`ph_with_*` functions, the `type` argument specifies the placeholder from the 
associated layout to be added as a new shape (and `index` is to be used when a 
`type` is not unique in the slide layout).

```{r}
img.file <- file.path( R.home("doc"), "html", "logo.jpg" )

doc <- read_pptx() 
doc <- doc %>%
  add_slide(layout = "Two Content", master = "Office Theme") %>%
  ph_with_text(type = "body", str = "body (index 1) is text", index = 1) %>% 
  ph_with_img(type = "body", index = 2, src = img.file, height = 1.06, width = 1.39 )

print(doc, target = "assets/pptx/ph_with_img.pptx")
```

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

To add an image into a new shape at arbitrary coordinates, use the function 
`ph_with_img_at()`. The arguments `left` and `top` specify the top left 
coordinate of the new shape and the `width` and `height` arguments specify the 
dimensions of the new shape.

### Add ggplot

Use function `ph_with_gg()` to add a ggplot object as an image into a placeholder. 
As for all `ph_with_*` functions, argument `type` specifies the placeholder of 
the associated layout to be added as a new shape (`index` is to be used when 
an `type` is not unique in the slide layout).

```{r}
if( require("ggplot2") ){
  doc <- read_pptx()
  doc <- add_slide(doc, layout = "Title and Content",
    master = "Office Theme")

  gg_plot <- ggplot(data = iris ) +
    geom_point(mapping = aes(Sepal.Length, Petal.Length), size = 3) +
    theme_minimal()

  if( capabilities(what = "png") )
    doc <- ph_with_gg(doc, value = gg_plot )

  print(doc, target = "assets/pptx/ph_with_gg.pptx" ) 
}
```

```{r echo=FALSE}
if( file.exists("assets/pptx/ph_with_gg.pptx"))
  office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/",
                                 "assets/pptx/ph_with_img.pptx" ) )
```

To add a ggplot object into a new shape at arbitrary coordinates, use function `ph_with_gg_at`. 
Arguments `left` and `top` are specifying the top left coordinate of the new shape 
and arguments `width` and `height` are specifying the dimensions of the new shape.

### Add table

Use the function `ph_with_table()` to add a table into a placeholder.

```{r}
doc <- read_pptx() 
doc <- doc %>%
  add_slide(layout = "Title and Content", master = "Office Theme") %>%
  ph_with_table(type = "body", value = head(mtcars) )

print(doc, target = "assets/pptx/ph_with_table.pptx")
```

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

To add a table into a new shape at arbitrary coordinates, use the 
function `ph_with_table_at()`. 

```{r}
doc <- read_pptx() 
doc <- doc %>%
  add_slide(layout = "Title and Content", master = "Office Theme") %>%
  ph_with_table_at(value = head(mtcars), left = 1, top = 3, 
                 height = 7, width = 7 )

print(doc, target = "assets/pptx/ph_with_table_at.pptx")
```

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


## Remove content from a slide

Use `slide_summary()` to easily identify shapes in the slide that can be removed.

```{r}
slide_summary(doc)
```

In the following example, the shape corresponding to `type "body"` will be 
removed from the current slide:

```{r}
doc <- ph_remove(x = doc, type = "body")
```

## Append text sequentially in a shape

### Add to an empty new placeholder

`ph_empty()` (and `ph_empty_at`) will add a new empty placeholder in the current 
slide. When using `ph_with_text()`, added text automatically inherits from the 
layout placeholder, whereas `ph_empty()` allows for more control of the format 
of added text and paragraphs.

```{r}
my_pres <- read_pptx() %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_empty(type = "body")
```

As there is no paragraph in the new shape yet, the function `ph_add_par()` will 
be used to add a new paragraph. Then `ph_add_text()` will be used to add text 
into that new paragraph.

```{r}
text_prop <- fp_text(color = "red", font.size = 20)
my_pres <- my_pres %>% 
  ph_add_par() %>%
  ph_add_text(str = "This is a red text!", style = text_prop ) %>% 
  ph_add_par(level = 2) %>%
  ph_add_text(str = "Level 2") %>% 
  ph_add_par(level = 3) %>%
  ph_add_text(str = "Level 3")

print(my_pres, target = "assets/pptx/ph_add_text_1.pptx")
```

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

### Add to an existing placeholder of text

The following code produces a presentation comprised of one text shape 
containing the text "A first text".

```{r}
my_pres <- read_pptx() %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "A first text")
```

Since there is now a paragraph in the new shape, `ph_add_par()` will be used to 
add another paragraph and `ph_add_text()` then has to be used to add text into 
the last paragraph of the shape.

```{r}
text_blue_prop <- update(text_prop, color = "blue" )
my_pres <- my_pres %>% 
  ph_add_text(str = "A small red text!", style = text_prop ) %>% 
  ph_add_text(str = "Blue text first... ", pos = "before", style = text_blue_prop ) %>% 
  ph_add_par(level = 2) %>%
  ph_add_text(str = "additional paragraph")

print(my_pres, target = "assets/pptx/ph_add_text_2.pptx") 
```

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

## Links

### External links

`ph_hyperlink()` adds a hyperlink to an existing placeholder in the current 
slide. The argument `href` should contain a valid URL (i.e. starting with 
`http(s)`).

```{r}
doc <- read_pptx() %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "Blah blah blah") %>% 
  ph_hyperlink(type = "body", href = "https://cran.r-project.org") %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "placeholder target")

print(doc, target = "assets/pptx/ph_hyperlink.pptx")
```

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


### Internal links

`ph_slidelink()` adds an internal link into an existing placeholder. The 
argument `slide_index` should contain the index of the target slide.

```{r}
doc <- read_pptx() %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "Blah blah blah") %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "placeholder target") %>% 
  on_slide(index = 1 ) %>% 
  ph_slidelink(type = "body", slide_index = 2)

print(doc, target = "assets/pptx/ph_slidelink.pptx")
```

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

### Add text with links

The function `ph_add_text()` has an optional argument `href`. If used, the chunk 
of text will be added as a hyperlink. If `href` is not used and `slide_index` is, 
the link will point to another slide in the document.

```{r}
my_pres <- read_pptx() %>% 
  add_slide(layout = "Title and Content", master = "Office Theme") %>% 
  ph_with_text(type = "body", str = "An ") %>% 
  ph_add_text(str = "hyperlink", href = "https://cran.r-project.org" )

print(my_pres, target = "assets/pptx/ph_add_text_3.pptx")
```

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

## Ressources

Len Kiefer wrote two very good blog posts about officer, he is providing nice examples with the corresponding R code:

* http://lenkiefer.com/2017/09/23/crafting-a-powerpoint-presentation-with-r/
* http://lenkiefer.com/2017/09/27/use-purrr/



