Search code examples
rshinyr-markdownreportshinydashboard

How can you make customized downloadable reports in r shiny?


So basically, my app has 10 different tables and graphs being generated for the user as results. Now, what I want to do is, display a checklist for the user and then ask the user to select the items they want to include in their downloaded report. This will make a customized report which will only include the things the user wishes to have. So, please help me out with the process of adding items into a report only if a checkbox is checked. I, kind of, have got the idea that I will have to generate the report with r-markdown but would love to have some clarity on it further.

app.R

library(shiny)
library(rmarkdown)
server <- function(input, output) {
  output$downloadReport <- downloadHandler(
    filename = function() {
      paste('my-report', sep = '.', switch(
        input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
      ))
    },
    content = function(file) {
      src <- normalizePath('test.Rmd')
      
      # temporarily switch to the temp dir, in case you do not have write
      # permission to the current working directory
      owd <- setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(src, 'test.Rmd', overwrite = TRUE)
      
      out <- rmarkdown::render('test.Rmd',
                               params = list(text = input$text,outp=input$Try),
                               switch(input$format,
                                      PDF = pdf_document(), 
                                      HTML = html_document(), 
                                      Word = word_document()
                               ))
      file.rename(out, file)
    }
  )
}

ui <- fluidPage(
  tags$textarea(id="text", rows=20, cols=155, 
                placeholder="Some placeholder text"),
  
  flowLayout(radioButtons('format', 'Document format', c('HTML', 'Word'),
                          inline = TRUE),
             checkboxGroupInput("Try","Let's hope this works",choiceNames = list("include hi","include hey","include hello","include how are you"),choiceValues = list("HI","HEY","HELLO","HOW ARE YOU")),
             downloadButton('downloadReport'))
  
)

shinyApp(ui = ui, server = server)

test.Rmd

---
title: "Parameterized Report for Shiny"
output: html_document
params:
  text: 'NULL'
  outp: 'NULL'
---

# Some title

`r params[["text"]]`
`r params[["outp"]]`

In this, I have added the checkboxGroupInput with id "Try" and I get the value of it as output. So, I am halfway there except now, I just need to get plots as output instead of choicevalues.


Solution

  • Your code looks good. Just pass the data over as an argument and create plots as you would in your Shiny App. You can use the default plot function, but also ggplot2 or plotly. To include/exclude plots/tables, also pass the checkbox value input$Try as parameter to the report and use conditions to add plots/tables as shown below.

    I only post the Rmd and the lines I changed in your Shiny App. Everything else looks good.

    server <- function(input, output) {
        output$downloadReport <- downloadHandler(
            filename = function() {
                paste('my-report', sep = '.', switch(
                    input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
                ))
            },
            content = function(file) {
                src <- normalizePath('test.Rmd')
                # temporarily switch to the temp dir, in case you do not have write
                # permission to the current working directory
                owd <- setwd(tempdir())
                on.exit(setwd(owd))
                file.copy(src, 'test.Rmd', overwrite = TRUE)
                
                include <- input$Try
                out <- rmarkdown::render('test.Rmd',
                                         params = list(tbl = mtcars, include = include),
                                         switch(input$format,
                                                PDF = pdf_document(), 
                                                HTML = html_document(), 
                                                Word = word_document()
                                         ))
                file.rename(out, file)
            }
        )
    }
    

    Updated r markdown:

    ---
    title: "Parameterized Report for Shiny"
    output: html_document
    params:
      tbl: NA
      include: NA
    ---
    
    ```{r echo=FALSE}
    library(knitr)
    tbl <- params$tbl
    include <- params$include
    ```
    
    ```{r echo=FALSE, results='asis'}
    if ('HI' %in% include) {
        kable(tbl[1:5,], caption= 'A table')
    }
    ```
    
    ```{r echo=FALSE, result='asis'}
    if ('HEY' %in% include) {
        plot(tbl$mpg, tbl$cyl)
    }
    ```
    

    What I really like is that you don't have to restart the Shiny App every time you change the report, as it is independent of the app itself.