Search code examples
rofficer

R Officer Update the text of a shape


I am using officer to generate a weekly PowerPoint deck for my management. They have provided me with a template they wish to use. I have automated the whole process apart from one part which is causing me some difficulty i was hoping someone could help with

The first slide in the template for them is a very nice cover slide but contains a text box with the Week number the report is to address so for example Report Week 5. I wish to change this every week i run the report. The next iteration would be Report Week 6. The name of the text box is called TextField 26 when i press ALT+F10 in windows

I have tried numerous solutions from here, here and here

I just cant seem to reference the slide itself within the template. I have seen the response on GITHUB related to a similar question where the advice was to remove the old shape and re-add it. I would be happy to do this but again I am unable to reference the title slide.

I would really appreciate anyone's insight to this

Thank you very much for your time


Solution

  • To go off my comment, I wrote a function that should work. Unfortunately the RDCOMClient package does require you to be on a windows computer to work

    devtools::install_github("omegahat/RDCOMClient")
    library(RDCOMClient)
    
    ReplaceTextInObject <- function(path, Find, Replace, SlideNum = NULL){
      ppApp <- COMCreate("powerpoint.application")
      #Requires absolute paths from C drive
      path <- normalizePath(c("C://Users",path), winslash = "\\")[2] 
      ppoint <- ppApp[["Presentations"]]$Open(path, WithWindow = F)
      slides <- 1:ppoint$Slides()$Count()
      #if SlideNum is NULL - loop through each slide
      if(!is.null(SlideNum)&&
         all(SlideNum%%1)==0&&
         all(SlideNum<=ppoint$Slides()$Count())){
        slides <- SlideNum
      } else{
        stop("m must be either an integer or NULL")
      } 
    
      for(j in slides){
        Slide <- ppoint$Slides(j)
        n <- Slide$Shapes()$Range()$Count() # Total number of shape objects on slide
        #if there are shapes with text - attempt find and replace
        if(n>0){
          for(i in 1:n){
            if(Slide$Shapes(i)$HasTextFrame()==-1&&
               Slide$Shapes(i)$TextFrame()$HasText()==-1){
                 Slide$Shapes(i)$TextFrame()$TextRange()$Replace(FindWhat = Find,
                                                                 ReplaceWhat = Replace)
            }
          }
        }
      }
    
      ppoint$Save()
      ppoint$Close()
      rm(Slide, ppoint, ppApp)
    }
    

    This function will take a slide number then look through all the objects in the slide. If the object (or shape as VBA has them listed in the documentation) can contain text and has text, then we attempt the find and replace function in that shape object.

    If you knew the exact shape index, then you don't need to bother with a loop, but this will do most of the heavy lifting for you. So if the text field is really unique in your template, this should solve your problem.