I am looking for a way to download text displayed on an app by generation a .txt file. Here is my attempt, with no success unfortunately:
library(shiny)
ui <- fluidPage(
sidebarPanel(
h4("Title"),
p("Subtitle",
br(),"Line1",
br(),"Line2",
br(),"Line3"),
downloadButton("Download Metadata", label = "Download")
)
)
server <- function(input, output, session){
output$downlaodData <- downloadHandler(
filename = function(){
paste("data-", Sys.Date(), ".txt", sep = "")
},
content = function(file) {
write.txt(data, file)
}
)
Thank you for your help
You cannot write text that is displayed on your page like that. You could download text stored as data or as user input. There are also some issues in your code:
data is not defined, so you are not specifying what should be downloaded
write.txt is not a function, use write.table instead
The downloadbutton and the downloadHandler should have the same id.
Working example
library(shiny)
text=c("Line1", "Line2","Line3")
ui <- fluidPage(
sidebarPanel(
h4("Title"),
p("Subtitle",
br(),text[1],
br(),text[2],
br(),text[3]),
downloadButton("download_button", label = "Download")
)
)
server <- function(input, output, session){
output$download_button <- downloadHandler(
filename = function(){
paste("data-", Sys.Date(), ".txt", sep = "")
},
content = function(file) {
writeLines(paste(text, collapse = ", "), file)
# write.table(paste(text,collapse=", "), file,col.names=FALSE)
}
)
}
shinyApp(ui,server)
Related
Is it possible to download an empty word document via shiny app?
ui <- fluidPage(
downloadButton("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
}
shinyApp(ui, server)
I wonderif there is a way to download 2 dataframes in the same excel file but in different sheet via shiny app.
library(shiny)
library(xlsx)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
downloadButton("dl","Export in Excel")
),
mainPanel(
)
)
))
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
paste0("df_dmodel", "_Table", ".xls")
},
content = function(file){
tbl<-iris
tbl2<-mtcars
write.xlsx(tbl,tbl2 file,
sheetName = "Sheet1", row.names = FALSE)
}
)
})
shinyApp(ui = ui, server = server)
try changing your server code to this. Also, remember to open the app in your browser and not just the rstudio viewer (assuming your are using rstudio). Hope this helps!
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
paste0("df_dmodel", "_Table", ".xlsx")
},
content = function(file){
tbl<-iris
tbl2<-mtcars
sheets <- mget(ls(pattern = "tbl")) # getting all objects in your environment with tbl in the name
names(sheets) <- paste0("sheet", seq_len(length(sheets))) # changing the names in your list
writexl::write_xlsx(sheets, path = file) # saving the file
}
)
})
An alternative to Andrew's answer using write.xlsx from openxlsx with a list of dataframes.
library(shiny)
library(openxlsx)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
downloadButton("dl","Export in Excel")
),
mainPanel(
)
)
))
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
"test.xlsx"
},
content = function(filename){
df_list <- list(iris=iris, mtcars=mtcars)
write.xlsx(x = df_list , file = filename, row.names = FALSE)
}
)
})
shinyApp(ui = ui, server = server)
As per the docs, the downloadHandler should accept contentType as a string. Since the contentType is not a constant, I am trying to pass a variable or reactive. But the app fails whenever the contentType is not strictly a string. How could I pass a variable value?
I have tried function(){}, reactive, eventReactive. What confuses me is that it works just fine for filename = function(){}.
ui <- fluidPage(
downloadLink("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
},
contentType = function() {
"text/csv"
}
)
}
shinyApp(ui, server)
In this case, the error message is
is.na() applied to non-(list or vector) of type 'closure' and the file is not downloaded correctly (server error).
ui <- fluidPage(
radioButtons("csvs", label = "Type to download", choices = c(".txt", ".csv"), selected = ".csv"),
downloadLink("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), input$csvs, sep="")
},
content = function(file) {
write.csv(data, file)
}
)
}
shinyApp(ui, server)
An easier and working way is to let the user pick it with a radioButton
I have a simple shiny app which downloads a .txt file. My problem is that I want to be able to set the filename from the app and download it as filename.txt for example and not "download_button" as it is now.
library(shiny)
text=c("Line1", "Line2","Line3")
ui <- fluidPage(
sidebarPanel(
h4("Title"),
p("Subtitle",
br(),text[1],
br(),text[2],
br(),text[3]),
downloadButton("download_button", label = "Download")
)
)
server <- function(input, output, session){
output$download_button <- downloadHandler(
filename = function(){
paste("data-", Sys.Date(), ".txt", sep = "")
},
content = function(file) {
writeLines(paste(text, collapse = ", "), file)
# write.table(paste(text,collapse=", "), file,col.names=FALSE)
}
)
}
shinyApp(ui,server)
Hopefully this addresses your issue. I just included a text input with the default value set to your filename as above, and then set the filename in the download function to that text input.
text=c("Line1", "Line2","Line3")
ui <- fluidPage(
sidebarPanel(
h4("Title"),
p("Subtitle",
br(),text[1],
br(),text[2],
br(),text[3]),
textInput("filename", "Input a name for the file", value = paste0("data-", Sys.Date(),".txt")),
downloadButton("download_button", label = "Download")
)
)
server <- function(input, output, session){
output$download_button <- downloadHandler(
filename = function(){
input$filename
},
content = function(file) {
writeLines(paste(text, collapse = ", "), file)
}
)
}
shinyApp(ui,server)
I have multiple tables in reactive objects in my shiny app (RA_s,Per), and I download each separately. Now, I'm trying to download one zip file containing all of this tables using a download button.
Here is my code, I don't know how to complete downloadHandler function. I want to download a zip file which contain 2 csv files RA_s and Per.
Code
shinyServer(function(input, output) {
RA_s <- reactive({
iris
})
Per <- reactive({
sepal1 <- RA_s()["Sepal_Length"]
sepal2 <- RA_s()["Sepal_Width"]
value = sepal1*sepal2
c = cbind(RA_s(),value)
})
output$downloadData <- downloadHandler(
filename = function() {
paste0("output", ".zip")
},
content = function(file) {
...
})
})
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Download", tabName = "d")
)
body<- dashboardBody(
tabItems(
tabItem(tabName = "d",
downloadButton('downloadData', 'Download')
)
)
dashboardPage(
dashboardHeader(title = "Valo"),
sidebar,
body
)
You can first save the zip files, and then zip them, as follows:
library(shiny)
server<- shinyServer(function(input, output) {
RA_s <- reactive({
iris
print(iris)
})
Per <- reactive({
sepal1 <- RA_s()["Sepal.Length"]
sepal2 <- RA_s()["Sepal.Width"]
value = sepal1*sepal2
c = cbind(RA_s(),value)
})
output$downloadData <- downloadHandler(
filename = 'two_csvs.zip',
content = function(fname) {
write.csv(RA_s(), file = "csv1.csv", sep =",")
write.csv(Per(), file = "csv2.csv", sep =",")
zip(zipfile=fname, files=c("csv1.csv","csv2.csv"))
},
contentType = "application/zip"
)
})
ui<- shinyUI(
downloadButton('downloadData', 'Download')
)
shinyApp(ui,server)
You can specify a subdirectory of course, to keep your directory clean. Hope this helps!