在输出格式之间切换,同时从 Shiny 生成可下载的 RMarkdown 报告

Switching between output formats while generating downloadable RMarkdown reports from Shiny

我正在尝试使用 Shiny 生成可下载的 RMarkdown 报告。我在 UI 中包含了单选按钮,以允许用户 select 报告的输出格式(Word 或 PDF)。我面临的问题是 UI 中的格式 selection 不影响输出格式。 radioButton 语句中的第一个选择是指定输出格式,即当前列表中的第一个选择 choices=list("PDF", "Word") 设置为 PDF,无论 selected 是什么,都会生成 PDF 输出在 UI。同样,如果列表中的第一个选项设置为 Word choices=list("Word", "PDF"),则 Word 文档就是最终输出,而不管 select 在 UI.[=14= 中编辑了什么]

我不确定自己做错了什么,所以非常感谢您的帮助!我在下面提供了一些虚拟代码。

闪亮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 模板

---
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)

}

```

我认为渲染文档的格式是选择的格式。只有文件名没有正确的扩展名。那是因为您在 downloadHandlerfilename 参数中有一个反应变量 (input$format)。在这种情况下,您必须使用 filename 的函数。即替换

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

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