How to download data of bar chart from shiny dashboard? - r

I am getting error file, while downloading data of bar chart rendered in shiny UI.
There is a download button just below the chart. While click on the 'Download data' button, data should be downloaded into csv format.
Code:
library(shiny)
library(ECharts2Shiny)
dat <- data.frame(c(1, 2, 3), c(2, 4, 6))
names(dat) <- c("Type-A", "Type-B")
row.names(dat) <- c("Time-1", "Time-2", "Time-3")
ui <- fluidpage( loadEChartsLibrary(),
tags$div(id="test", style="width:50%;height:400px;"),
deliverChart(div_id = "test"), downloadButton("test", "Download Data"))
server <- function(input, output) {
renderBarChart(div_id = "test", grid_left = '1%', direction = "vertical",
data = dat)
}
shinyApp(ui = ui, server = server)
I want to download the data of that bar chart in ".csv" format.
Can anyone help me out to correct the code?
Thank you.

I think you cannot use the same "renderTable" server output for all of your UI inputs. AKA, you need to make a separate input and output for your image in the form of a downloadable file. Here is an example of what I did to download a .csv file:
output$downloadData <- reactive({
output$downloadData <- downloadHandler(
filename = function() {
paste("ProcessedData-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(DataTable, file)
}
)
Therefore in your download button you would replace "test" with "downloadData" so that it connects to a new server output. Notice that I am creating the file here with write.csv, but not actually writing to any disk just generating the file and passing it into the downloadData output for users to trigger and then save to their own disk when they hit the downloadData input button. You are trying to save a picture so I suggest trying something along the lines of generating an image file inside of the content call. Recall that you can save images as objects:
#up in the UI somewhere
ui <- fluidpage(loadEChartsLibrary(),
tags$div(id="test", style="width:50%;height:400px;"),
deliverChart(div_id = "test"), downloadButton("downloadData", "Download Data"))
server <- function(input, output) {
output$test <- renderBarChart(div_id = "test", grid_left = '1%', direction = "vertical",
data = dat)
output$downloadData <- reactive({
output$downloadData <- downloadHandler(
filename = function() {
paste("Image.png", sep="") #just the file name you want to have as default
},
content = function(file) {
write.csv(DataTable, file)
)
}
I don't have your actual code so this may not work as a plug and play solution, but I believe this is the right direction.

Related

In RShiny using renderPrint/renderText to show error when expected files are missing in downloadHandler

I am using a downloadHandler in a shiny app which let's me download 4 reactive dataframes that has been created. I want to include a functionality if either one of the dataframes has not been created then that will be printed in renderPrint/renderText saying one of the dataframes is missing. A minimal example from the server code is given below but it does not work the way I want it to.
output$dl <-
if((df1()!= '') || (df2()!='') || (df3()!= '') || (df4()!= '') ){
downloadHandler(
filename = "New_Data.xlsx",
content = function(file){
write_xlsx(list("S1" = df1(), "S2" = df2(), "S3" = df3(), "S4" = df4()), path = file)
}else{
output$dl_error <- renderPrint({'One of the dataframes is missing'})
}
)
or something like this
data_list <- reactive({
list("S1" = df1(),
"S2" = df2(),
"S3" = df3(),
"S4" = df4())
})
output$dl <- reactive({
if(length(data_list()==4)){
downloadHandler(
filename = "New_Data.xlsx",
content = function(file){
write_xlsx(data_list(), path = file)
}
)
}else{
output$dl_error <- renderPrint({'One of the dataframes is missing'})
}
})
It will be great if someone can help me out with this. Also, it would be better if the error message in the renderPrint/renderText shows which dataframe is missing.
As said in my comment, you could disable the button. You can use the shinyjs package to do that easily. Another option is to hide the download button with a conditionalPanel. Here is a third option. I hide the download button with a conditionalPanel and instead I display a "fake" download button. When the dataframe is available, the fake data button is hidden and the true download button becomes visible. If the user clicks on the fake download button, he is told that the dataframe is not available with an alert.
library(shiny)
library(shinyalert)
library(writexl)
ui <- fluidPage(
useShinyalert(),
br(),
conditionalPanel(
condition = "!output.ok",
actionButton("fake", "Download", icon = icon("save"))
),
conditionalPanel(
condition = "output.ok",
style = "display: none;",
downloadButton("dwnld", "Download", icon = icon("save"))
),
br(),
actionButton("databtn", "Generate dataframe")
)
server <- function(input, output, session){
observeEvent(input[["fake"]], {
shinyalert(
title = "Error!",
text = "The dataframe is not ready yet",
type = "error"
)
})
df <- reactiveVal(NULL)
observeEvent(input[["databtn"]], {
df(iris)
})
output[["ok"]] <- reactive({
!is.null(df())
})
outputOptions(output, "ok", suspendWhenHidden = FALSE)
output[["dwnld"]] <- downloadHandler(
filename = "iris.xlsx",
content = function(file){
write_xlsx(list(iris = df()), path = file)
}
)
}
shinyApp(ui, server)

download CSV using filtered dataframe RShiny

I've made an shiny app where I'm filtering a dataset using some values and then I would like to be able to download that filtered dataset. However, I'm struggling to understand how I can pass the filtered dataset to the csv downloader. It is a very large dataset so can't use the buttons available in renderDataTable (I think?) Does anyone have any ideas of how I can do this?
Example app:
### data ###
egDf <- data.frame(col1 = sample(letters,10000,replace=T), col2 = sample(letters,10000, replace=T))
### modules ###
chooseCol1UI <- function(id){
ns <- NS(id)
uiOutput(ns('chooserCol1'))
}
chooseCol1 <- function(input, output, session, data){
output$chooserCol1 <- renderUI({
ns <- session$ns
pickerInput(inputId = ns('chosenCol1'),
label = 'Col1',
choices = paste(sort(unique(egDf$col1))),
options = list(`actions-box` = TRUE),
multiple = TRUE)
})
return(reactive(input$chosenCol1))
}
csvDownloadUI <- function(id, label = "Download CSV") {
ns <- NS(id)
downloadButton(ns("downloadData"), label)
}
csvDownload <- function(input, output, session, data) {
output$downloadData <- downloadHandler(
filename = function() {
paste(names(data), Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(data, file, row.names = FALSE)
}
)
}
displayTableUI <- function(id){
ns <- NS(id)
DT::dataTableOutput(ns('displayer'))
}
displayTable <- function(input, output, session, data, col1Input){
output$displayer <- DT::renderDataTable(egDf %>% filter(col1 %in% col1Input()))
}
### server ###
server <- function(input,output){
chosenCol1 <- callModule(chooseCol1,
id = 'appChooseCol1', data = egDf)
callModule(module = displayTable, id = "appDisplayTable",
col1Input = chosenCol1)
}
### ui ###
ui <- fluidPage(
sidebarPanel(
chooseCol1UI("appChooseCol1")),
mainPanel(displayTableUI("appDisplayTable")))
### app ###
shinyApp(ui = ui, server = server)
A few years ago I made an app with such a button. In my case I created a reactive expression in the server.R file that is being passed to the downloadHandler.
Here's the app and here's the github code. Head to the server.R file and search for the "download" string.
In the app you'll find a blue download button in the "Data" tab. The app let's you apply filters that applies in the datatable, that you can download via the button.
Edit: here's the server portion of code of interest:
#data download button
output$idDwn <- downloadHandler(
filename = function() {
paste('uCount ', format(Sys.time(), "%Y-%m-%d %H.%M.%S"), '.csv', sep='')
},
content = function(file) {
write.csv(datasetInputFilters(), file)
}
)
I would create eventReactive function that allows your col1Input.
# Reactive function based on input
react_df <- eventReactive(input$chosenCol1, {
return(egDf %>% filter(col1 %in% input$chosenCol1))
})
output$displayer <- renderDataTable(react_df())
# Download box
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
output_d <- react_df()
write.csv(output_d, file, row.names = FALSE)
}
)
I dealt with this issue recently and unfortunately that solution didn't work for me. But simply using writexl::write_xlsx() instead of write.csv() was enough.

Shiny DownloadHandler unable to save .csv file

I'm trying to download my datatable into, a csv. file. Unfortuantely, even though the download starts, it's stuck with calculating and doesn't save the data. The file size is 8mb large and I only could workaround this issue with downloading only the filtered dataset. I also tried setting the donload size to 10 mb with shiny.maxRequestSize=30*1024^2
I really need the option to save the whole dataset. If anyone could provide some insights I would much appreciate it (And yes, I run the App in the Browser)
my ui function looks like this:
tbl <- read.csv(file.choose(new = FALSE), header = TRUE, sep = ",", row.names=1)
ui <- navbarPage(
title = "Data Table Options",
#Tab with the dataset table
tabPanel("Lot Dataset",
div(h3("Download"), style = "color:blue"),
helpText(" Select the download format"),
radioButtons("type", "Format type:",
choices = c("Excel (CSV)", "Text (Space Separated)", "Doc")),
helpText(" Click on the download button to download the Lot Dataset"),
downloadButton("download_filtered", "Download Filtered Data"),
br(),
br(),
br(),
DT::dataTableOutput("dt"), #datatable
),
)
my server function like this:
server <- function(session, input, output) {
#Increasing Downloadsize to 10MB
options(shiny.maxRequestSize=10*1024^2)
#render the datatable
output$dt <- DT::renderDataTable({
datatable(tbl, filter = "top", options = list(
lengthMenu = list(c(25, 50, 100, -1), c("25", "50", "100", "All")),
pageLength = 25))
})
#bottom panel with row indices
output$filtered_row <-
renderPrint({
input[["dt_rows_all"]]
})
#file extension for download
fileext <- reactive({
switch(input$type,
"Excel (CSV)" = "csv", "Text" = "txt", "Doc" = "doc")
})
#downloadHandler() for file download of Lot Dataset
output$download_filtered <- downloadHandler(
filename = function() {
paste("MLdataset_test", fileext(), sep=".") #filename
},
content = function(file) {
#write tbl with filter
write.csv(tbl[input[["dt_rows_all"]], ],
file = file, row.names = F)
}
)
}
Any help appreciated!!!

downloading file in shiny

I want a user to download a file which is in tabular format with header along with two search widgets on top. The output is forecasted values along with 80%(High-low) and 95%(High-low) confidence interval.So there are five columns, five rows(default). However, i am having two challenges here.
Challenge 1:
When I run the app, after clicking on "Download the file" filename is coming as download data with no extension whereas I have mentioned filename should be "forecasted" with png extension and it should come as forecated.png
Challenge 2: After typing png as extension while saving the file, the file is saved but nothing gets printed.
I have searched in various forums and try to replicate them but nothing seems to be working.
Please suggest.
shiny UI
library(shiny)
downloadButton(outputId = "downloaddata" ,label ="Download the file"),
shiny server
output$downloaddata<-downloadHandler(
filename = function(){
paste("forecasted","png",sep=",")
},
content = function(file){
png(file)
h <-input$fst
tab<-forecast(Model_mape(),h)
datatable(as.data.frame(tab), options = list(
columnDefs = list(list(targets = c(1, 3), searchable = FALSE)),
pageLength = 10))
dev.off()
}
)
Maybe it could help you (it's a simple instance):
Ui :
library(shiny)
shinyUI(fluidPage(
mainPanel(plotOutput("plot1"),
downloadButton("downloadplot","Download your plot"))
))
Server :
library(shiny)
shinyServer(function(input, output) {
your_plot = function(){
(plot(rnorm(1000,0,1)))
}
output$plot1 <- renderPlot({
your_plot()
})
output$downloadplot <- downloadHandler(
filename = "plot_exemple.png",
content = function(file) {
png(file, width = 1200, height = 800)
print(your_plot())
dev.off()
})
})
With this, you can easily download a png (open it in a browser).

How to download multiple reports created using R markdown and R shiny in a zip file

I have created an R shiny application to download dynamic reports using R Markdown. Previously I was downloading one report at a time by selecting the row in the data table in r shiny and clicking on download button, the selected row's column values would get filled in the report, this was working perfectly fine.
But now i am trying to download multiple reports, so that if I select multiple rows in a datatable in r shiny and click on download, the number of reports downloaded should be equal to number of rows selected.
For this I am trying to create a zip file which contains all my individual report but I am getting this
error: pandoc document conversion failed with error 1
I had researched for this error but couldn't find anything. Please help!
ui <- {
tagList(
div(id = "downloadBtn",
downloadButton("downloadData", "Download")),
DT::dataTableOutput('myTable1')
)
}
dataJ <- read.csv(file = "iris.csv", header = TRUE, stringsAsFactors =
FALSE)
server <- function(input, output)
{
output$myTable1 <- DT::renderDataTable({
DT::datatable(dataJ, options = list(orderClasses = TRUE), filter = 'top')})
output$downloadData <- downloadHandler(
filename = function()
{
paste("output", "zip", sep = ".")
},
content = function(file)
{
k = list(input$myTable1_rows_selected)
fs <- c()
for ( i in k)
{
params <- list(j=i)
path <- paste(i,".docx")
rmarkdown::render("R_markdown_script.Rmd", rmarkdown::word_document(),
output_file = path , params = params,
envir = new.env(parent = globalenv()))
fs <- c(fs,path)
}
zip(zipfile = file, files = fs)
if (file.exists(paste0(file, ".zip")))
file.rename(paste0(file, ".zip"), file)
},
contentType = "application/zip" )
}
runApp(list(ui = ui, server = server))
Here is a reproducible example (to make it work, create an rmarkdown file with the default content using RStudio, and save it as "test.rmd" in the same folder as your Shiny app).
Important:
You need to run the app externally inside your web browser. Somehow it does not work in the viewer pane or RStudio window (you get the download window but then no file is saved).
If you are on Windows, you need to make sure that you install RTools first, and also put the rtools/bin folder in your system path.
app.R
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
sidebarPanel(
downloadButton("downloadData", "Download")
),
mainPanel(
DT::dataTableOutput('myTable1')
)
)
))
server <- shinyServer(function(input, output) {
output$myTable1 <- DT::renderDataTable(iris)
output$downloadData <- downloadHandler(
filename = function() {
paste0("output", ".zip")
},
content = function(file) {
k <- input$myTable1_rows_selected
fs <- c()
for (i in k) {
path <- paste0(i, ".docx")
rmarkdown::render("test.rmd", rmarkdown::word_document(), output_file = path)
fs <- c(fs, path)
}
zip(file, fs)
},
contentType = "application/zip"
)
})
shinyApp(ui = ui, server = server)
Hello I also installed Rtools/bin and was running the code on the web browser, but when I click on download button, download window doesn't comes up and shows '404 Not Found', but when I check the directory, the doc files report are saving directly to directory, no zip file is produced. Please see below code.
ui <- {
tagList(
div(id = "downloadBtn",
downloadButton("downloadData", "Download")),
DT::dataTableOutput('myTable1')
)
}
dataJ <- read.csv(file = "iris.csv", header = TRUE, stringsAsFactors =
FALSE)
server <- function(input, output)
{
output$myTable1 <- DT::renderDataTable({
DT::datatable(dataJ, options = list(orderClasses = TRUE), filter = 'top')})
output$downloadData <- downloadHandler(
filename = ("output.zip"),
content = function(file)
{
k <- (input$myTable1_rows_selected)
fs <- c()
for ( i in k)
{
path <- paste0(i,".docx")
rmarkdown::render("R_markdown_script.Rmd", output_file = path ,
params = list(j=i), envir = new.env(parent = globalenv()))
fs <- c(fs,file)
}
zip(zipfile = file, files = fs)
},
contentType = "application/zip" )
}
runApp(list(ui = ui, server = server))`

Resources