0

I'm trying to use officer to make a report. However, sometimes, the plots that I want to add don't have enough data, so rather than throwing an error, I just want R to leave a blank space where that plot would go.

However, I've tried using try() and an if statement, but neither work. For try(), officer just skips over any line that uses it, even if the plot exists.

I've tried the is.error() function from the BBmisc package, but, despite the plot printing an error when you try to load it, is.error("error_plot") gives FALSE. (As an aside, if anyone familiar with BBmisc/ggplot2 knows why this is, I'm curious.)

How can I get officer to skip over these errors (and just the errors)?

#Set up

library(officer)
library(ggplot2)
library(dplyr)
library(BBmisc)
#Read in blank deck
blank_deck <- read_pptx()

#Define location for objects
my_location_1 <- ph_location(left = .43, top = 2.18, height = 2.36, width = 4.17)
my_location_2 <- ph_location(left = 5.39, top = 2.18, height = 2.36, width = 4.17)

#Make a simple plot--this plot is good
good_plot <- try(ggplot(data = iris, aes(x = Species, y = Sepal.Length)) +
  geom_col())

#Make a simple plot--this plot intentionally is wrong
error_plot <- try(ggplot(data = iris, aes(x = Species, y = Sepal.Length)) +
  geom_col() +
  facet_wrap(~Species2))

Here's solution 1, with try()

#Note: run the code from the set up section first

sample <- blank_deck %>%
  add_slide(layout = "Title Slide", master = "Office Theme") %>%
  ph_with(value = "My Title", ph_location_label(ph_label = "Title 1")) %>%
  add_slide(layout = "Blank", master = "Office Theme") %>%
  try(ph_with(value = good_plot, location = my_location_1)) %>% 
  try(ph_with(value = error_plot, location = my_location_2)) %>% 
  add_slide(layout = "Title Slide", master = "Office Theme") %>%
  ph_with(value = "End", ph_location_label(ph_label = "Title 1")) %>%
  base::print(
    target = '/home/define/your/pathway/mydeck.pptx')

And here's my attempt at using an if/then statement with is.error():

sample <- blank_deck %>%
  add_slide(layout = "Title Slide", master = "Office Theme") %>%
  ph_with(value = "My Title", ph_location_label(ph_label = "Title 1")) %>%
  add_slide(layout = "Blank", master = "Office Theme") %>%
  if_else(is.error("good_plot"), (ph_with(value = empty_content(), location = my_location_1)),
                   (ph_with(value = error_plot, location = my_location_2))) %>%
  if_else(is.error("error_plot"), (ph_with(value = empty_content(), location = my_location_2)),
                   (ph_with(value = error_plot, location = my_location_2))) %>% 
  add_slide(layout = "Title Slide", master = "Office Theme") %>%
  ph_with(value = "End", ph_location_label(ph_label = "Title 1")) %>%
  base::print(
    target = '/home/define/your/pathway/mydeck.pptx')
J.Sabree
  • 2,280
  • 19
  • 48
  • This doesn't answer this question exactly, but a workaround is to run this in an R Markdown file. Then, in that chunk, set error = TRUE. By doing this, R will persist past the error, without requiring try(), is.error(), etc. – J.Sabree Jul 05 '22 at 21:34

1 Answers1

0

Problem

This problem (at least in attempt 1) is caused by the faulty use of pipes %>%. A pipe takes the output from the code on its left side, and provides it as the first argument for the first function on the right side. (Though a . placeholder can be used to specify another argument position of the first function).

This code:

read_pptx() %>%
  add_slide(layout = "Blank", master = "Office Theme") %>%
  ph_with(value = good_plot, location = my_location_1) %>% 
  base::print(target = 'mydeck.pptx')

Would do the same as:

foo <- read_pptx()
foo <- add_slide(foo, layout = "Blank", master = "Office Theme")
foo <- ph_with(foo, value = good_plot, location = my_location_1)
base::print(foo, target = 'mydeck.pptx')

But your first attempt (simplified):

read_pptx() %>%
  add_slide(layout = "Blank", master = "Office Theme") %>%
  try(ph_with(value = good_plot, location = my_location_1)) %>% 
  base::print(target = 'mydeck.pptx')

Does the same as:

foo <- read_pptx()
foo <- add_slide(foo, layout = "Blank", master = "Office Theme") 
foo <- try(foo, ph_with(value = good_plot, location = my_location_1))
base::print(foo, target = 'mydeck.pptx')

Note the problem in line 3: the output from add_slide() is passed as first argument to try(), not to ph_with().

Solution

Only use pipes if you want to pass output to the first function:

blank_deck <- read_pptx()

sample <- blank_deck %>%
          add_slide(layout = "Title Slide", master = "Office Theme") %>%
          ph_with(value = "My Title", ph_location_label(ph_label = "Title 1")) %>%
          add_slide(layout = "Blank", master = "Office Theme")

try(sample <- ph_with(sample, value = good_plot, location = my_location_1))

try(sample <- ph_with(sample, value = error_plot, location = my_location_2))

sample <- sample %>% 
          add_slide(layout = "Title Slide", master = "Office Theme") %>%
          ph_with(value = "End", ph_location_label(ph_label = "Title 1")) %>%
          base::print(target = 'mydeck.pptx')

enter image description here

Caspar V.
  • 1,782
  • 1
  • 3
  • 16