Search code examples
rshinyexcelr

R shiny, excelR package how to download the table/dataframe?


How can I download the table from excelR package? The reason why I want to use excelR package is that the user can input values directly but I want to give them the option to download the list if there are many more to add instead of a few rows.

Please see below minimum reproducible code. When running the below code and click the download button, it gives me an error message Warning: Error in as.data.frame.default: cannot coerce class ‘c("jexcel", "htmlwidget")’ to a data.frame [No stack trace available]

enter image description here

library(shiny)
library(excelR)

ui <- fluidPage(
  fluidRow(
    column(6,
           titlePanel("Template")
    ),
    column(2,
           downloadButton("download1", "Download Template")
    )
  ),
  fluidRow(
    excelOutput("template2"))
)

server <- function(input, output, session) {
  core_data = reactive({
    data.frame(Session_Name = rep("",10),
               Description1="", Description2="",
               Weeks_per_year="",
               Patients_per_clinic="")
  })
  
  core_columns = reactive({
    data.frame(title=c('Session_Name','Description1',
                       'Description2',"Weeks_per_year",
                       "Patients_per_clinic"),
               width= c(300,300,100,100,100),
               type=c('text','text','text',"numeric","numeric")) 
  })
  
  core_df = reactive({
    excelTable(data=core_data(), columns = core_columns())
  })
  
  output$template2 <- renderExcel({
    core_df()
  })
  
  output$download1 <- downloadHandler(
    filename = function(){"user_template.csv"}, 
    content = function(file){
      write.csv(core_df(), file,row.names = FALSE)
    }
  )
  
}

shinyApp(ui, server)

Solution

  • The issue is that core_df() is not a dataframe but an object of class excelObj instead. Adapting the example code from ?excel_to_R you could convert your template to an R dataframe and export it to a css like so:

    output$download1 <- downloadHandler(
        filename = function() {
          "user_template.csv"
        },
        content = function(file) {
          write.csv(excel_to_R(input$template2), file, row.names = FALSE)
        }
      )