Generating markdown report in shiny?


#1

Hi,

Could some one point me to an example of how to generate a markdown document based on inputs in Shiny? Ideally, I would render the markdown document in the application, rather than downloading it.

This example is pretty close to what I am looking for, but I don’t know what the contents of the report.Rmd’ file or how to pass parameters to it, courtesy of this Stackoverflow question

Thanks

Iain


#2

There is a good Rstudio reference guide. I would read the Passing Parameters section carefully.

Essentially you set up your Rmd document with the parameters defined in the header, then you use rmarkdown::render() to pass along a list of parameters to be used in the report.

To use the shiny inputs as parameters you’d need to isolate the input object as you pass it into rmarkdown::render() as an option to params. e.g.

 render(myTemplate.Rmd, 
        output_file = "myTemplate.pdf", 
        params = list(paramOne = isolate(input$param))
       )

#3

I think this article (Generating downloadable reports) walks you through what you’re trying to achieve. Let me know if that’s not enough.


Code snippet to create download link for markdown report?
#4

Thanks - that is exactly what I was looking for.


#5

Is it possible to produce multiple reports (let’s say, a report per region) when a user clicks on the button? If so, how would that work? I envision utilizing the purrr::walk() function to make this happen, but I’m not sure I’m applying it correctly.

Also, is there a possibility of zipping the multiple documents produced and have the user download a single .zip file instead of multiple files?


#6

Are you looking for multiple reports or would looping over the region and storing it one report work?
It is possible to write a loop in markdown
https://stackoverflow.com/questions/17178831/generate-markdown-comments-within-for-loop

A similar trick can be used to insert all the images in a directory
https://www.biostars.org/p/219801/

files <- list.files(path = "Desktop", pattern = "png", full.names = TRUE)
for (f in files) {
  cat(paste0("![image_label](", f, ")\n"))
  }

Although this approach has a bit of a drawback as it embeds the code segment in the document too. Perhaps someone has a solution.


#7

Yes, if we use the article @barbara shared with you as the base, then you would use purrr::walk to run the rmarkdown::render() function, and add the region to the params list.

I have not tested this code, but it would look something like this:

region_vector %>%
 walk(~rmarkdown::render(tempReport, output_file = file,
          params = list(input$slider, .x,
          envir = new.env(parent = globalenv())))

#8

I’m looking for the production of multiple reports, one per region.

I have a project in which the client has about 250 branch locations, and they would like the ability for their branch managers to receive a PDF report for their own branch location. We’ve mentioned to them the possibility of providing user login access to the app for each manager that would be restricted to their branch, but they didn’t appear interested in that aspect.

The current set-up is that a user can select a particular branch and then download that branch’s report, but needless to say it’s quite manually-intensive due to the sheer number of branches.


#9

Brilliant Edgar, I’ll give this a shot.

EDIT: One more question: Should the .Rmd document be saved in the same directory as the app.R file, or should it be saved within the www folder?

EDIT2: To answer my question in the EDIT above, this example suggests the .Rmd file just needs to be in the same directory as the .R files.


#10

Hi Edgar,

Just to follow up on this, your code works once you adjust for a missing bracket:

walk(~rmarkdown::render(tempReport, output_file = file,
          params = list(input$slider), .x,
          envir = new.env(parent = globalenv())))

#11

Awesome! Thank you for the follow up


#12

I do have another issue - which I’m not sure can be replicated.

I have put together below a more simplified version of the initial app. For some reason, when I click on “Generate report”, the file created is called “report” when I specified it to be “report.pdf”. I end up having to manually change the downloaded file name to add “.pdf” in order for my computer to recognize it as a PDF document. Is anyone else experiencing the same issue? Is there a correction to be made to the below?

app.R:

library(rmarkdown)
library(shiny)

shinyApp(
  ui = fluidPage(
    sliderInput("slider", "Slider", 1, 100, 50),
    downloadButton("report", "Generate report")
  ),
  server = function(input, output) {
    output$report <- downloadHandler(
      filename = "report.pdf",
      content = function(file) {
        tempReport <- file.path(tempdir(), "report.Rmd")
        file.copy("report.Rmd", tempReport, overwrite = TRUE)

        params <- list(n = input$slider)

        render(tempReport, output_file = file,
           params = params,
           envir = new.env(parent = globalenv())
        )
      }
    )
  }
)

report.Rmd:

---
title: "Dynamic report"
output: pdf_document
params:
  n: NA
---

```{r}
# The `params` object is available in the document.
params$n
```

A plot of `r params$n` random points.

```{r}
plot(rnorm(params$n), rnorm(params$n))
```

#13

There’s a known issue with the RStudio IDE on Windows where it loses filename and extension of file downloads:
https://github.com/rstudio/shiny/issues/1562


#14

@winston, but this also means that if the app is deployed anywhere, it will function as normal, right? (since all servers run on Linux)


#15

It depends on the browser. I believe that all modern browsers should keep the filename and extension.


#16

Thanks Winston. I thought I was going nuts.


#17

A post was split to a new topic: Generating markdown reports from shiny?