Arun kumar mahesh Arun kumar mahesh - 3 months ago 63
R Question

Downloading pdf plot using shiny app after reading excel files

As, I am new to shiny apps need some assistance, uploading excel file and generating table output in shiny app works fine, but can't able to download the plot to a pdf format
Here is my code

library(shiny)
library(openxlsx)
library(lattice)

runApp(
list(
ui = fluidPage(
titlePanel("plots"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
tags$hr(),
downloadButton('down',"download plot")
),
mainPanel(
tableOutput('contents'),
plotOutput('plot'))
)
),
server = function(input, output){
output$contents <- renderTable({
inFile <- input$file1

if(is.null(inFile))
return(NULL)
else
read.xlsx(inFile$datapath)
})

plotInput <- reactive({
df <- input$file1
xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")
})

output$plot <- renderPlot({
print(plotInput())
})

output$down <- downloadHandler(
filename = function(){paste("plot",".pdf",sep=".") },
content = function(file) {
pdf(file)
xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")
dev.off()
}
)
}
)
)

Answer

The problem was that, in some parts of you code, you were accessing a dynamic data frame via df() but you had never defined it.

In this kind of problems, it is the best to create a reactive data frame, say, df which only contains the uploaded data and it is passed to other reactive parts of the code via df().


Full example:

library(shiny)
library(openxlsx)
library(lattice)

runApp(
  list(
    ui = fluidPage(
      titlePanel("plots"),
      sidebarLayout(
        sidebarPanel(
          fileInput('file1', 'Choose xlsx file',
                    accept = c(".xlsx")),
          tags$hr(),
          downloadButton('down',"download plot")
        ),
        mainPanel(
          tableOutput('contents'),
          plotOutput('plot'))
      )
    ),
    server = function(input, output){


      df <- reactive({
        inFile <- input$file1
        req(inFile) # require that inFile is available (is not NULL) 
                    # (a user has uploaded data)

        # read.xlsx(inFile$datapath)
        head(iris, 10)
      })

      output$contents <- renderTable({
        # access uploaded data via df()
        df()
      })

      plotInput <- reactive({
        df <- df()
        xyplot(df[,2]~df[,1], df ,xlim=c(0,10),ylim=c(0,100),type = "b")
      })

      output$plot <- renderPlot({
        plotInput()
      })

      output$down <- downloadHandler(
        filename = function(){paste("plot",".pdf",sep=".") },
        content = function(file) {
          pdf(file)
          #xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")

          # you have to print the plot so that you can open pdf file
          print(plotInput())
          dev.off()
        }
      )
    }
  )
)