How to download multiple word document files with selectInput, with each selected option being a different file

I have an R Markdown document which is parameterized, and then I am using downloadHandler() to pass values to it such that users can download a Word document based off of the client they select.

I allowed the selection of multiple clients, but the issue is that it combines the clients' data into one Word Document (which is what you'd expect). Does anyone know of any way to select multiple clients at once, click the Generate Report button, and then have multiple Word documents downloaded- one for each client?

library(shiny)

shinyApp(
  ui = fluidPage(
   selectInput("Client", "Client", 
               c("Bob Jones 1",            "Bob Jones 2",        "Bob Jones 3",           "Bob Jones 4",         
                 "Bob Jones 5",         "Bob Jones 6" ), multiple = TRUE),
    downloadButton("report", "Generate report")
  ),
  server = function(input, output) {
    
    output$contents <- renderTable({
      
      req(input$file1)
      
      inFile <- input$file1
      
      read_excel(inFile$datapath, 1)
    })
    output$report <- downloadHandler(
      
      
      # For PDF output, change this to "report.pdf"
      filename = "report.doc",
      content = function(file) {
        # Copy the report file to a temporary directory before processing it, in
        # case we don't have write permissions to the current working dir (which
        # can happen when deployed).
        tempReport <- file.path(tempdir(), "report.Rmd")
        file.copy("report.Rmd", tempReport, overwrite = TRUE)
        
        # Set up parameters to pass to Rmd document
        params <- list(n = input$Client)
        
        # Knit the document, passing in the `params` list, and eval it in a
        # child of the global environment (this isolates the code in the document
        # from the code in this app).
        rmarkdown::render(tempReport, output_file = file,
                          params = params,
                          envir = new.env(parent = globalenv())
                          
        )
      }
      
      
    )
  }
)

I don't think it's possible to download multiple files from html (in general, not just in Shiny). So instead you could have a loop that rendered the document for each client, then zipped them into a single file (using zip())` or similar.

I'd recommend prototyping that code outside of your app because it'll be relatively complex and is largely independent of reactivity. Some thing like this:

write_reports <- function(clients) {
  report_path <- tempfile()
  dir.create(report_path)
  file.copy("report.Rmd", report_path)
  
  for (client in clients) {
    params <- list(n = client)
    rmarkdown::render(tempReport, 
      output_file = paste0("report-", client, ".html"),
      params = params,
      envir = new.env(parent = globalenv()
    )
  }
  
  zip_path <- tempfile()
  zip(report_path, zip_path)        
  zip_path
}

(Completely untested but hopefully gives you the idea. You'd also need to delete the .Rmd so it doesn't get included in the bundle)

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