PowerPoint presentations generation

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;" ) }
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. Initial PowerPoint file can be specified with argument path. 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. Content of original document is also preserved (but can be manipulated, i.e. delete a slide).

my_pres <- read_pptx()

Add a slide

Next thing to do is to add a new slide, use 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")

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 theses can be read easily with function layout_summary.

layout_summary(my_pres)

master layouts and slide layouts

officer uses a PowerPoint file as initial document. This is the original PowerPoint document where all slides 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 formating 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 function ph_with_text to add text into a new shape. The type of the shape is defined in the slide layout associated to the current slide, for example, using type = "title" will create a title shape in the 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")

Function layout_properties provides details about available shapes of a slide layout:

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

Write the PowerPoint

File can be generated using function print and argument target:

print(my_pres, target = "assets/pptx/first_example.pptx") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/first_example.pptx" ) )

Slides 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 function add_slide.

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 function remove_slide.

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

Selected slide can be set with function on_slide.

my_pres <- my_pres %>% on_slide(index = 1)

Add content into a placeholder

Add text

Use function ph_with_text to add text into a new shape. Argument type specify which placeholder of 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") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_with_text.pptx" ) )

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

Add image

Use function ph_with_img to add 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).

img.file <- file.path( Sys.getenv("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") %>% invisible()
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 function ph_with_img_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.

img.file <- file.path( Sys.getenv("R_HOME"), "doc", "html", "logo.jpg" ) doc <- read_pptx() %>% add_slide(layout = "Title and Content", master = "Office Theme") %>% ph_with_text(type = "title", str = "A image") %>% ph_with_img_at(src = img.file, left = 3, top = 4, height = 1.06, width = 1.39, rot = 45 ) print(doc, target = "assets/pptx/ph_with_img_at.pptx") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_with_img_at.pptx" ) )

Add table

Use 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") %>% invisible()
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 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") %>% invisible()
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.

slide_summary(doc)

In the following example, 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 (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, ph_empty gives more control on 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 not paragraph yet in the new shape, 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") %>% invisible()
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 produce a presentation made of one text shape containing 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")

There is a paragraph in the new shape, ph_add_par will be used to add a new paragraph and ph_add_text 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 = "additionnal paragraph") print(my_pres, target = "assets/pptx/ph_add_text_2.pptx") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_add_text_2.pptx" ) )

ph_hyperlink add an hyperlink to an existing placeholder in the current slide. 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") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_hyperlink.pptx" ) )

ph_slidelink add an internal link into an existing placeholder. 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") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_slidelink.pptx" ) )

Function ph_add_text has an optional argument href, if used, the chunk of text will be an hyperlink.

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") %>% invisible()
office_doc_link( url = paste0( "https://davidgohel.github.io/officer/articles/", "assets/pptx/ph_add_text_3.pptx" ) )