Switching between output formats while generating downloadable RMarkdown reports from Shiny

I am trying to generate downloadable RMarkdown reports using Shiny. I have included radioButtons in the UI to allow the user to select the output format of the report (Word or PDF). The problem I am facing is that the format selection in the UI is not impacting the output format. The first choice in the radioButton statement is dictating the output format, i.e., currently the first choice in the list, choices=list("PDF", "Word"), is set to PDF, this is producing a PDF output regardless of what is selected in the UI. Similarly, if the first choice in the list is set to Word, choices=list("Word", "PDF"), then a Word document is the final output regardless of what is selected in the UI.

I am unsure what I doing wrong so I would really appreciate any help! I have provided some dummy code below.

Shiny UI/Server

# Load packages
suppressWarnings(suppressMessages(library(shiny)))
suppressWarnings(suppressMessages(library(tidyverse)))
suppressWarnings(suppressMessages(library(rmarkdown)))
suppressWarnings(suppressMessages(library(bookdown)))
suppressWarnings(suppressMessages(library(knitr)))

# Define data frame variables
countries = c("Canada", "United States of America", "Qatar", "Scotland", "Bangladesh")
capitals = c("Ottawa", "Washington, DC", "Doha", "Edinburgh", "Dhaka")
values = seq(1, 5, 1)

# Build data fram
df = data.frame(countries, capitals, values)

# User interface
ui = fluidPage(

  # Define title for the app
  titlePanel("Dummy example"),

  # Sidebar layout with input and output definitions
  sidebarLayout(
    sidebarPanel(
      selectInput("select_country", "Select Country:", choice = unique(df$countries)),
      uiOutput("select_capital"),
      radioButtons("format", "Summary Format:", choices=list("PDF", "Word"), inline=TRUE),
      downloadButton("download_report", "Download Report")
    ),
    mainPanel(
    )
  )
)

# Server logic
server = function(input, output, clientData, session) {

  # Build capitals filter based on selected country
  output$select_capital = renderUI({

      df = df[df$countries == input$select_country, ]
      choice = unique(df$capitals)

    selectInput(
      "select_capital",
      "Select Capital:",
      choices = choice
    )
  })


  # Download report
  output$download_report = downloadHandler(

    filename = paste("report",
      switch(input$format, "Word"="docx", "PDF"="pdf"), sep="."),

    content = function(file) {
      normalized_path = normalizePath("report.Rmd")

      # Temporarily switch to a temp directory in case you do not have permission
      # to the current working directory
      owd = setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(normalized_path, "report.Rmd", overwrite=TRUE)

      # Set up parameters to pass to Rmd documents
      params = list(countries = input$select_country,
        capitals = input$select_capital,
        format = input$format)

      out = rmarkdown::render("report.Rmd",
        switch(input$format, "PDF"=pdf_document(), "Word"=word_document()),
        params=params,
        envir=new.env())
        file.rename(out, file)

    }
  )

}

# Run RShiny app
shinyApp(ui, server)

RMarkdown template

---
title: "Dummy example"
date: "`r format(Sys.time(), '%B %d, %Y')`"
output:
  bookdown::pdf_document2:
    toc: false
    df_print: kable
    extra_dependencies: ["float"]
  bookdown::word_document2:
    toc: false
classoption: twocolumn
params:
  countries: NA
  capitals: NA
  format: NA
urlcolor: blue
always_allow_html: true
header-includes:
  - \usepackage{booktabs}
  - \usepackage{longtable}
  - \usepackage{array}
  - \usepackage{multirow}
  - \usepackage{float}
  - \usepackage{tabu}
---

```{r packages, echo=FALSE, eval=TRUE, message=FALSE, include=FALSE}
knitr::opts_chunk$set(fig.pos = "!H", out.extra = "")

# Load packages
library(tidyverse)
library(rmarkdown)
library(bookdown)
library(knitr)
library(flextable)
library(kableExtra)
```

```{r print-dataframe, echo=FALSE, eval=TRUE, message=FALSE, results="asis"}

# Print data frame
print(params$format)
if (params$format == "Word") {

  # Use flextable if the output format is Word
  flextable(df)

} else {

  # Use kable if the output format if PDF
  df = knitr::kable(df, booktabs=T, caption="Dummy example") %>%
      kableExtra::kable_styling(latex_options=c("scale_down", "HOLD_position", "repeat_header"))
  print(df)

}

```

I also posted this question on stackoverflow. Stephane Laurent solved this problem there by replacing

filename = paste("report", switch(input$format, "Word"="docx", "PDF"="pdf"), sep=".")

with

filename = function(){
  paste("report", switch(input$format, "Word"="docx", "PDF"="pdf"), sep=".")
}

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.