Skip to main content
AI in Production 2026 is now open for talk proposals.
Share insights that help teams build, scale, and maintain stronger AI systems.
items
Menu
  • About
    • Overview 
    • Join Us  
    • Community 
    • Contact 
  • Training
    • Overview 
    • Course Catalogue 
    • Public Courses 
  • Posit
    • Overview 
    • License Resale 
    • Managed Services 
    • Health Check 
  • Data Science
    • Overview 
    • Visualisation & Dashboards 
    • Open-source Data Science 
    • Data Science as a Service 
    • Gallery 
  • Engineering
    • Overview 
    • Cloud Solutions 
    • Enterprise Applications 
  • Our Work
    • Blog 
    • Case Studies 
    • R Package Validation 
    • diffify  

Custom PowerPoints Using {officer}

Author: Theo Roe

Published: May 22, 2025

tags: r, officer, powerpoint, ggplot2, quarto, rmarkdown
officer R package logo

From a purely design perspective, Quarto’s standard PowerPoint output falls short. It is limited to seven layout options, with the most complex being “Two Content.” The {officer} R package offers a powerful alternative for those seeking full control and customisation.

Data comes in all shapes and sizes. It can often be difficult to know where to start. Whatever your problem, Jumping Rivers can help.

Why PowerPoint?

At work, I use a Linux operating system (OS), and at home, I use macOS. Within my little bubble, it’s easy to forget how much of the market share Microsoft still holds. It’s estimated that around 70% of the desktop operating system market share belongs to Microsoft. Many of the clients I work with prefer Microsoft outputs, such as PowerPoint, over HTML or PDF. Aside from company alignment with Microsoft, there are a few practical reasons why using PowerPoint with Quarto can be advantageous:

  • No need to be a CSS / LaTeX whizz-kid to produce professional-looking slides
  • Possible (and easy) to edit after rendering the doc!

What is {officer}?

From davidgohel.github.io/officer

The officer package lets R users manipulate Word (.docx) and PowerPoint (*.pptx) documents. In short, one can add images, tables and text into documents from R. An initial document can be provided; contents, styles and properties of the original document will then be available.

This means for this workflow, Quarto is sidestepped altogether, and we focus entirely on R scripts and R coding.

How?

There are a few ways to use {officer} - I’ll walk through the approach that I’ve found to be most effective.

Layout templates

First - you’ll need a PowerPoint presentation that contains template layout slides. There are no limits to these slides, the format can be as custom as you like and there can be as many layouts as you want. Remember - this file doesn’t need any actual slides, it only needs layouts! To create a layout:

  1. Enter “Slide Master” mode
  2. Add any content (headers, footers, styling etc) you want to appear on each slide to the “Slide Master”
  3. Create a new Layout Slide
Slide Master view in PowerPoint.

To insert content from R, the easiest way is via placeholders. These can be text, tables, images and more. To add a placeholder:

  1. Click “Insert Placeholder” and choose the content type
  2. If it’s a text placeholder, you can customise the formatting of the text

You can see below that I’ve added some basic Jumping River styling to mine, and added two placeholders; a text placeholder for a title and an image placeholder for a plot.

Slide Master view in PowerPoint.

In order to access these placeholders easily from R, it’s better to rename them:

  1. Home tab
  2. Click the “Select” dropdown
  3. Click “Selection pane”
  4. Select your placeholder and rename
Changing your placeholder names via the selection pane in PowerPoint.

Here I’ve named my image placeholder “plot”, and my text placeholder for the slide title, “title”. Note that it’s also a good idea to name your layout - just right click and hit rename. In this demo I’ve just left it as “Title Slide”.

The R code

Now that I’ve got my template set up, the rest is in R. First, we load {officer} and read the PowerPoint document in as an R object.

library("officer")
doc = read_pptx("mytemplate.pptx")

If you’ve forgotten your layout / placeholder names, access them through layout_summary() and layout_properties()

layout_summary(doc)
layout_properties(doc, layout = "Title Slide", master = "Office Theme")
Document properties for an officer document object.

Before any content can be added, content is needed! Let’s use the {palmerpenguins} package to create a simple plot of “Adelie” penguins data

library("palmerpenguins")
library("dplyr")
library("ggplot2")

adelie_plot = penguins |> 
  filter(species == "Adelie") |> 
  ggplot(aes(x = bill_length_mm, y = flipper_length_mm)) + 
  geom_point() + 
  theme_linedraw() + 
  theme(
    # Make the background transparent
    plot.background = element_rect(fill = "transparent", colour = NA),
    # Match the panel colour to the slide
    panel.background = element_rect(fill = "#F1EADE", colour = NA)) + 
  labs(
    x = "Bill Length (mm)",
    y = "Flipper Length (mm)")

I can add empty slides to the document using the add_slide() function. Here I simply choose a layout from my .pptx file to use.

doc = add_slide(doc, layout = "Jumping Rivers", master = "Office Theme")
doc

Then, using the ph_with() function, I can insert R objects into my placeholders by name

doc = ph_with(
  doc,
  value = "Adelie",
  location = ph_location_label("title")
)
# Add the plot
doc = ph_with(
  doc,
  value = adelie_plot,
  location = ph_location_label("myplot")
)

To create the PowerPoint, use print()

print(doc, "penguins.pptx")
An example of the PowerPoint output.

And there we have it! I’ve used only two placeholders here to keep the example simple, but in reality there is no limit.

Looping

It’s easy to make use of programming when using purely R code to generate PowerPoints. For instance, we could stick our code into a for loop, and add a slide for each Penguin species

# Read in doc again
# this resets the doc object to the original file
doc = read_pptx("mytemplate.pptx")

for (penguin_species in c("Adelie", "Chinstrap", "Gentoo")) {
  doc = add_slide(doc, layout = "Title Slide", master = "Office Theme")
  # Add the title using the iterator value
  doc = ph_with(
    doc,
    value = penguin_species,
    location = ph_location_label("title")
  )
  # Create the plot using the iterator value
  penguin_plot = penguins |> 
    filter(species == penguin_species) |> 
    ggplot(aes(x = bill_length_mm, y = flipper_length_mm)) + 
    geom_point() + 
    theme_linedraw()
    theme(
      plot.background = element_rect(fill = "transparent", colour = NA),
      panel.background = element_rect(fill = "#F1EADE", colour = NA)) + 
    labs(
      x = "Bill Length (mm)",
      y = "Flipper Length (mm)")
  # Add the plot
  doc = ph_with(
    doc,
    value = adelie_plot,
    location = ph_location_label("plot")
  )
}
# Output to a file
print(doc, "penguins_loop.pptx")
An example output for when looping and iteratively adding slides / inserting content.

Conclusion

There are a few drawbacks to this method:

  • It is quite annoying to insert large amounts of text using just an R script
  • Content added to the “Slide Master” slide cannot be moved or edited on the output file
  • The web version of powerpoint doesn’t have the Slide Master functionality features

However, I think the pros outweigh the cons:

  • Completely (and I mean completely) custom layouts
  • I haven’t covered this here but it’s really easy to convert ggplots to vector graphics in DrawingML format so they can be edited in PowerPoint
  • Easier to programmatically generate lots of slides
  • It can be edited after rendering by anyone!
  • It can be styled before rendering by anyone!

Jumping Rivers Logo

Recent Posts

  • Start 2026 Ahead of the Curve: Boost Your Career with Jumping Rivers Training 
  • Should I Use Figma Design for Dashboard Prototyping? 
  • Announcing AI in Production 2026: A New Conference for AI and ML Practitioners 
  • Elevate Your Skills and Boost Your Career – Free Jumping Rivers Webinar on 20th November! 
  • Get Involved in the Data Science Community at our Free Meetups 
  • Polars and Pandas - Working with the Data-Frame 
  • Highlights from Shiny in Production (2025) 
  • Elevate Your Data Skills with Jumping Rivers Training 
  • Creating a Python Package with Poetry for Beginners Part2 
  • What's new for Python in 2025? 

Top Tags

  • R (236) 
  • Rbloggers (182) 
  • Pybloggers (89) 
  • Python (89) 
  • Shiny (63) 
  • Events (26) 
  • Training (23) 
  • Machine Learning (22) 
  • Conferences (20) 
  • Tidyverse (17) 
  • Statistics (14) 
  • Packages (13) 

Authors

  • Amieroh Abrahams 
  • Tim Brock 
  • Aida Gjoka 
  • Shane Halloran 
  • Russ Hyde 
  • Myles Mitchell 
  • Theo Roe 
  • Colin Gillespie 
  • Gigi Kenneth 
  • Osheen MacOscar 
  • Sebastian Mellor 
  • Keith Newman 
  • Pedro Silva 

Keep Updated

Like data science? R? Python? Stan? Then you’ll love the Jumping Rivers newsletter. The perks of being part of the Jumping Rivers family are:

  • Be the first to know about our latest courses and conferences.
  • Get discounts on the latest courses.
  • Read news on the latest techniques with the Jumping Rivers blog.

We keep your data secure and will never share your details. By subscribing, you agree to our privacy policy.

Follow Us

  • GitHub
  • Bluesky
  • LinkedIn
  • YouTube
  • Eventbrite

Find Us

The Catalyst Newcastle Helix Newcastle, NE4 5TG
Get directions

Contact Us

  • hello@jumpingrivers.com
  • + 44(0) 191 432 4340

Newsletter

Sign up

Events

  • North East Data Scientists Meetup
  • Leeds Data Science Meetup
  • Shiny in Production
British Assessment Bureau, UKAS Certified logo for ISO 9001 - Quality management British Assessment Bureau, UKAS Certified logo for ISO 27001 - Information security management Cyber Essentials Certified Plus badge
  • Privacy Notice
  • |
  • Booking Terms

©2016 - present. Jumping Rivers Ltd