Search code examples
rggplot2powerpointofficer

Using officer to add multiple ggplots and a title to a single PowerPoint slide


I have some code set up that loops through figure creation and adds them to a PowerPoint slide, but it currently can only add one figure to a slide meaning lots of manual work moving images around.

Here are the loops I'm currently working with, I have one of these for each figure I want to add and it results in them each being on their own slide.

  
  print(ggplot(demo.table.data %>% filter(str_detect(`Question`, j)), aes(x= `Category` , y= `Percent`)) +
          geom_bar(stat="identity",color='black', width=0.9, fill = "#1C4D0F" ) +
          labs(title = index[4,j]) +
          scale_y_continuous(labels = function(x) paste0(x, "%")) +
          scale_x_discrete(labels = scales::wrap_format(40)) +
          theme_excel_new() +
          theme(axis.text.x = element_text(size = 24, family = "Lato", color = "black")) +
          theme(axis.text.y = element_text(size = 24, family = "Lato", color = "black")) +
          theme(plot.title = element_text(face = "bold", family = "Lato", size = 30, color = "black")) +
          geom_text(aes(label = paste0(round(stat(y),1),"%"), group = `Question`), stat = 'summary', hjust = -.05, fun = sum, color = "Black", fontface = "bold", family = "Lato", size = 8) +
          facet_grid(TwoLevelFactor~., scales = "free_y", space = "free", switch = "y") +
          theme(strip.placement = "outside", strip.text.y = element_text(size = 24, family = "Lato", color = "Black", face = "bold")) +
          coord_flip())
  
  # Step 3
  # Store file path
  # str_replace_all replaces countries names so that it is alpha numeric to avoid invalid file path issues.
  
  plot_file_path <- paste0("C:/Users/Desktop/graphs/",j,"_Demo.png")
  
  # Append file path to list for each iteration
  file_path_list <- append(file_path_list, list(plot_file_path))
  
  # Step 4
  # Save the graph
  ggsave( filename = plot_file_path, plot = last_plot(), height = 20, width =  24, units = "in", device = "png", scale = 1, dpi = 300,)
}

#Add demos to the PowerPoint
for (i in seq(file_path_list)) {
  plot_png <- external_img(file_path_list[[i]])
  
  add_slide(connectedeconomy_pptx,
            layout = "Graph",
            master = "ConnectedEconomy") %>%
    ph_with(
      value = plot_png,
      location = ph_location_label(ph_label = "Content Placeholder 2")
    )
}

Solution

  • Your approach looks a bit complicated to me. Instead of exporting your files via ggsave and then importing them inside your loop I would approach this task like so:

    1. create your plots and store them in a list
    2. loop over a sequence of uneven numbers, i.e. do for (i in seq(1, length(plots), 2))
    3. add a slide, put plots i and i + 1 (if any) on the slide

    If required you could add two ggsave statements to the loop to additionally export the plots as pngs.

    Using a simple mtcars plot and the default pptx layout shipped with officer for the reprex:

    library(ggplot2)
    library(officer)
    plots <- lapply(1:10, function(i) {
      ggplot(mtcars, aes(hp, mpg)) +
        geom_point() +
        labs(title = paste("Plot", i))
    })
    
    # Create temporary file
    file <- tempfile(fileext = ".pptx")
    
    pptx <- read_pptx()
    for (i in seq(1, length(plots), 2)) {
      pptx <- add_slide(pptx, layout = "Two Content", master = "Office Theme")
      pptx <- ph_with(pptx,
        value = plots[[i]],
        location = ph_location_label(ph_label = "Content Placeholder 2")
      )
      
      if (i < length(plots)) {
        pptx <- ph_with(pptx,
          value = plots[[i + 1]],
          location = ph_location_label(ph_label = "Content Placeholder 3")
        )
      }
    }
    print(pptx, file)
    

    enter image description here