Problem downloading list of data frames with download button

Dear community, I hope you are all well. I'been having trouble with triyng to download many data frames into an excel file.

Currentrly I'm using the function write.xlsx from package openxlsx to download several data frames. The aim is that each data frame will be stored into a different sheet in the excel file. For this, I'm creating a list with the data frames I want to store which then is passed to the write.xlsx function.

The problem I'm having is with a particular data frame that is created in order to store some answers from the user. The user in my app select some answers from some questions and then is supposed to press a button and generate a score (which is printed after hitting the button). Then the user can download the answers in a excel file as a record. The problem is that, the sheet that contains the answers is empty.

Below I attach a simple example of what I'm trying to do. The data frame df is actually being filled with the selected options (as the print command shows). However, I don't understand why it is not being printed properly in the download_list command.

Thanks for your help.

library(shiny)
library(openxlsx)

#Create example data frame
Name <- c("Jon", "Bill", "Maria", "Ben", "Tina")
Age <- c(23, 41, 32, 58, 26)

df_example <- data.frame(Name, Age)



ui <- fluidPage(

    # Application title
    titlePanel(title = "Tab1"),

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
          radioButtons(inputId = "RadioButton1", label = "Answer yes or no",
                       choices = c("Yes" = 1, "No" = 0), selected = 0),
          downloadButton("download1", "Download"),
        ),

        
        mainPanel(
          selectInput(inputId = "q1", label = "Question 1",
                      choices = c("Answer 1" = "1",
                                  "Answer 2" = "0")),
          selectInput(inputId = "q2", label = "Question 2",
                      choices = c("Answer 1"  = "1",
                                  "Answer 2" = "0.5",
                                  "Answer 3" = "0")),
          actionButton(inputId = "button1", label = tags$strong("Generarate score")),
          textOutput("finalscore")
          
        )
    )
)


server <- function(input, output) {

  
  
  choicesq1 <- c("Answer 1" = "1",
                 "Answer 2" = "0")
  
  choicesq2 <- c("Answer 1"  = "1", "Answer 2" = "0.5", "Answer 3" = "0")
  
  #Data frame for storing questions results
  df <- data.frame(Question = character(),
                   Answer = character(),
                   stringsAsFactors = FALSE)
  
  q1_r <- reactive({ 
    if(input$RadioButton1 == 1){
      0.105*as.numeric(input$q1)
    } else if (input$RadioButton1 == 0){
      0.123*as.numeric(input$q1)}
  })
  
  q2_r <- reactive({ 
    if(input$RadioButton1 == 1){
      0.071*as.numeric(input$q2)
    } else if (input$RadioButton1 == 0){
      0.083*as.numeric(input$q2)} 
  })
  
  
  observeEvent(input$button1, {
  
    score <- (q1_r() + q2_r())
    
    output$finalscore <- renderText({
      paste("The score obtained is", score)
    })
    
    if(input$RadioButton1 == 1){
      df[1,1]  <- "Question 1"
      df[2,1]  <- "Question 2"
      df[1,2]  <- names(choicesq1)[choicesq1 == input$q1]
      df[2,2]  <- names(choicesq2)[choicesq2 == input$q2]
    } else if(input$RadioButton1 == 0) {
      df[1,1]  <- "Question 1"
      df[2,1]  <- "Question 2"
      df[3,1]  <- "No Question 3"
      df[1,2]  <- names(choicesq1)[choicesq1 == input$q1]
      df[2,2]  <- names(choicesq2)[choicesq2 == input$q2]
      df[3,2]  <- "No Answer 3"
    }
    
 print(df)
    
})
  
  download_list <- list("Example"= df_example,
                        "Q&A" = df)
  
  output$download1 <- downloadHandler(
    
    filename = function(){
      paste0("results",".xlsx")
    },
    
    content = function(file){
      
      write.xlsx(download_list, file) 
      
    }
  )

} 
  
shinyApp(ui = ui, server = server)

Hi!

I see some issues with the app code:

  • df is not a reactive object (you define it as a data.frame inside the server fn)
  • download_list is not in a reactive context
  • using the & symbol for a name might give some errors while exporting

I have applied changes to your app server code, according to the above and it works :white_check_mark: :

server <- function(input, output) {
  
  
  
  choicesq1 <- c("Answer 1" = "1",
                 "Answer 2" = "0")
  
  choicesq2 <- c("Answer 1"  = "1", "Answer 2" = "0.5", "Answer 3" = "0")
  
  #Data frame for storing questions results
  reactive_data <- reactiveValues()
  reactive_data$df <- data.frame(Question = character(),
                   Answer = character(),
                   stringsAsFactors = FALSE)
  
  q1_r <- reactive({ 
    if(input$RadioButton1 == 1){
      0.105*as.numeric(input$q1)
    } else if (input$RadioButton1 == 0){
      0.123*as.numeric(input$q1)}
  })
  
  q2_r <- reactive({ 
    if(input$RadioButton1 == 1){
      0.071*as.numeric(input$q2)
    } else if (input$RadioButton1 == 0){
      0.083*as.numeric(input$q2)} 
  })
  
  
  observeEvent(input$button1, {
    
    score <- (q1_r() + q2_r())
    
    output$finalscore <- renderText({
      paste("The score obtained is", score)
    })
    
    if(input$RadioButton1 == 1){
      reactive_data$df[1,1]  <- "Question 1"
      reactive_data$df[2,1]  <- "Question 2"
      reactive_data$df[1,2]  <- names(choicesq1)[choicesq1 == input$q1]
      reactive_data$df[2,2]  <- names(choicesq2)[choicesq2 == input$q2]
    } else if(input$RadioButton1 == 0) {
      reactive_data$df[1,1]  <- "Question 1"
      reactive_data$df[2,1]  <- "Question 2"
      reactive_data$df[3,1]  <- "No Question 3"
      reactive_data$df[1,2]  <- names(choicesq1)[choicesq1 == input$q1]
      reactive_data$df[2,2]  <- names(choicesq2)[choicesq2 == input$q2]
      reactive_data$df[3,2]  <- "No Answer 3"
    }
    
    print(reactive_data$df)
    
  })

  output$download1 <- downloadHandler(
    
    filename = function(){
      paste0("results",".xlsx")
    },
    
    content = function(file){
      
      download_list <- list("Example"= df_example,
                            "QA" = reactive_data$df)
      
      write.xlsx(download_list, file) 
      
    }
  )
  
} 

HTH!


This post was published by an Appsilon team member. Our company can help you get the most out of RShiny and Posit/RStudio products.

Check our open positions here.

Appsilon: Building impactful RShiny Dashboards and providing R coding services.
Appsilon_GIFsmall_whitebg

1 Like

Hi agus! Thank you very much for your help. It works perfectly.

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

If you have a query related to it or one of the replies, start a new topic and refer back with a link.