Search code examples
rcpu-wordsectionsofficer

Alternate portrait and landscape sections using officer package in R


I would like to make a .pdf report that alternates between portrait (for text) and landscape (for large figures) sections. I use the officer package in R which generates a .docx, that I can convert into .pdf using Word or LibreOffice.

I made some attempts, but I have the following problems: I have a blank portrait page at the end, which I would like to remove, and if I convert into pdf it adds blank pages between the portrait and landscapes pages. You can also detect these blank pages in word by numbering the pages (they switch for 1 to 3 will skipping the 2), or looking at the impression viewer. This problem is explained in http://wordfaqs.ssbarnhill.com/BlankPage.htm for how to deal with them in Word, but I would like a solution to remove those blank pages using officer because I will have hundreds of sections alternating between portrait and landscape to deal with.

Here is my attempt:

library(officer)

doc_1 <- read_docx()

doc_1 <- body_add_par(doc_1, value = "Portrait")
doc_1 <- body_end_block_section(doc_1, block_section(prop_section()))

doc_1 <- body_add_par(doc_1, value = "Landscape")
doc_1 <- body_end_section_landscape(doc_1)

temp <- tempfile(fileext = ".docx")

temp

print(doc_1, target = temp)

# system(paste0('open "', temp, '"'))

The answer of David (underneath) improves my problem, but it does remove some of the portrait orientations when I try to iterate it using body_add_docx (which I use for efficiency reasons, see https://github.com/davidgohel/officer/issues/184):


library(officer)

portrait_section_prop <- prop_section(page_size = page_size(orient = "portrait"))
landscape_section_prop <- prop_section(page_size = page_size(orient = "landscape"))

core <- function(i){
  
  doc_1 <- read_docx() |> 
    body_add_par(value = paste("Portrait", i)) |> 
    body_end_block_section(value = block_section(portrait_section_prop)) |> 
    body_add_par(value = paste("Landscape", i)) |> 
    body_end_block_section(value = block_section(landscape_section_prop)) |> 
    body_set_default_section(landscape_section_prop)
  
  return(doc_1)
  
}

accu <- core(1)

for(i in 2:10){
  
  doc_1 <- core(i)
  
  temp <- tempfile(fileext = ".docx")

  print(doc_1, temp)

  accu <- body_add_docx(accu, temp)

}

print(accu, target = tempfile(fileext = ".docx")) |> browseURL()



Solution

  • Here is the code you need, you need to define the same default section than the one you want to end the document so that Word agree to not add a page:

    library(officer)
    
    portrait_section_prop <- prop_section(page_size = page_size(orient = "portrait"))
    landscape_section_prop <- prop_section(page_size = page_size(orient = "landscape"))
    
    doc_1 <- read_docx() |> 
      body_add_par(value = "Portrait") |> 
      body_end_block_section(value = block_section(portrait_section_prop)) |> 
      body_add_par(value = "Landscape") |> 
      body_end_block_section(value = block_section(landscape_section_prop)) |> 
      body_set_default_section(landscape_section_prop)
    
    temp <- tempfile(fileext = ".docx")
    
    
    print(doc_1, target = temp)
    

    enter image description here