Jakub Małecki
Jakub Małecki

Reputation: 634

Switch page layout conditionally for MS Word documents generated from Rmarkdown code

I create MS Word documents using Rmarkdown and officer/officedown packages. My output is officdown::rdocx_document. I have code like this in my Rmarkdown file:

library(flextable)
library(officer)

tables <- list(
  flextable(iris),
  flextable(mtcars)
  # and potentially more tables, the list is dynamic
)

I want to toggle portrait/landscape layout depending on the number of columns of each table. For example, if the number of columns is greater than 5 the page orientation should be landscape, otherwise portrait.

I know that officer package provides block_section function, but I don't know how to use it dynamically. Please notice that I don't know how many tables will be there, the list is dynamic.

I tried this, according to the help page of block_section function:

orients <- calculate_page_orient(tables)  # a helper that will determine the orientation based on the number of columns in a table
for (i in seq_len(lenght(tables))) {
  block_section(prop_section(type = "continuous")
  tables[[i]]
  block_section(prop_section(page_size = page_size(orient = orients[i])))
}

But it doesn't work. How I can dynamically set the page layout using officer package?

Upvotes: 0

Views: 59

Answers (1)

stefan
stefan

Reputation: 125418

Here is one possible implementation which instead of using block_section uses !---BLOCK_LANDSCAPE_START/END---> to set the page layout to landscape and which uses chunk option results='asis' to dynamically render your tables within a for loop. Also note that I loop directly over the datasets and do the conversion to a flextable inside the loop.

---
output: officedown::rdocx_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, fig.cap = TRUE)
library(officedown)
library(officer)
library(flextable)
```

```{r}
tables <- list(
  iris,
  mtcars
) |> 
  lapply(head)
```

```{r}
calculate_page_orient <- function(x) {
  if (ncol(x) > 5) "landscape" else "portrait"
}
```

```{r results='asis'}
for (tbl in tables) {
  orient <- calculate_page_orient(tbl)
  if (orient == "landscape") cat("\n\n<!---BLOCK_LANDSCAPE_START--->\n\n")
  ft <- flextable(tbl)
  ft <- autofit(ft)
  flextable_to_rmd(ft)
  if (orient == "landscape") cat("\n\n<!---BLOCK_LANDSCAPE_STOP--->\n")
  cat("\\newpage\n\n")
}
```

enter image description here

Upvotes: 0

Related Questions