# PowerPoint presentations generation

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

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

    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

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

    layout_summary(my_pres)

    ##              layout       master
    ## 1       Title Slide Office Theme
    ## 2 Title and Content Office Theme
    ## 3    Section Header Office Theme
    ## 4       Two Content Office Theme
    ## 5        Comparison Office Theme
    ## 6        Title Only Office Theme
    ## 7             Blank Office Theme

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

    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.

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

    ##     master_name        name   type id                   ph_label     offx
    ## 6  Office Theme Two Content   body  3      Content Placeholder 2 0.500000
    ## 7  Office Theme Two Content   body  4      Content Placeholder 3 5.083333
    ## 12 Office Theme Two Content     dt  5         Date Placeholder 4 0.500000
    ## 16 Office Theme Two Content    ftr  6       Footer Placeholder 5 3.416667
    ## 29 Office Theme Two Content sldNum  7 Slide Number Placeholder 6 7.166667
    ## 32 Office Theme Two Content  title  2                    Title 1 0.500000
    ##         offy       cx        cy
    ## 6  1.7500000 4.416667 4.9496533
    ## 7  1.7500000 4.416667 4.9496533
    ## 12 6.9513889 2.333333 0.3993056
    ## 16 6.9513889 3.166667 0.3993056
    ## 29 6.9513889 2.333333 0.3993056
    ## 32 0.3003478 9.000000 1.2500000

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

    annotate_base(output_file = "assets/pptx/annotated_layout.pptx")

    ## pptx document with 7 slide(s)
    ## Available layouts and their associated master(s) are:
    ##              layout       master
    ## 1       Title Slide Office Theme
    ## 2 Title and Content Office Theme
    ## 3    Section Header Office Theme
    ## 4       Two Content Office Theme
    ## 5        Comparison Office Theme
    ## 6        Title Only Office Theme
    ## 7             Blank Office Theme

Download file annotated_layout.pptx - view with office web viewer

### Write the PowerPoint file

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/first_example.pptx"

Download file first_example.pptx - view with office web viewer

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

    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)

    ## [1] 3

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

    my_pres <- my_pres %>% remove_slide(index = 1)
    length(my_pres)

    ## [1] 2

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

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_with_text.pptx"

Download file ph_with_text.pptx - view with office web viewer

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_with_img.pptx"

Download file ph_with_img.pptx - view with office web viewer

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

    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" )
    }

    ## Loading required package: ggplot2

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_with_gg.pptx"

Download file ph_with_img.pptx - view with office web viewer

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.

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_with_table.pptx"

Download file ph_with_table.pptx - view with office web viewer

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_with_table_at.pptx"

Download file ph_with_table_at.pptx - view with office web viewer

## Remove content from a slide

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

    slide_summary(doc)

    ##   type id ph_label offx offy cx cy
    ## 1 body  2            NA   NA NA NA
    ##                                                                                                                                                                                                                                                    text
    ## 1 {5C22544A-7EE6-4342-B048-85BDC9FD1C3A}mpgcyldisphpdratwtqsecvsamgearcarb21.061601103.902.62016.46014421.061601103.902.87517.02014422.84108933.852.32018.61114121.462581103.083.21519.44103118.783601753.153.44017.02003218.162251052.763.46020.221031

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

    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.

    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.

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_add_text_1.pptx"

Download file ph_add_text_1.pptx - view with office web viewer

### Add to an existing placeholder of text

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

    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.

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_add_text_2.pptx"

Download file ph_add_text_2.pptx - view with office web viewer

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_hyperlink.pptx"

Download file ph_hyperlink.pptx - view with office web viewer

### Internal links

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_slidelink.pptx"

Download file ph_slidelink.pptx - view with office web viewer

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

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

    ## [1] "/private/var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T/RtmpPP5pg3/Rbuild2db46cfbaec8/officer/vignettes/assets/pptx/ph_add_text_3.pptx"

Download file ph_add_text_3.pptx - view with office web viewer

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