Download text and generate txt file in Shiny - r

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

Download file as word document in a shiny app

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)

Download multiple dataframes in multiple sheets of the same excel file in a shiny app

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)

How to implement R Shiny downloadHandler with variable contentType?

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

How to set filename of your choice when you download file from shiny app

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)

Downloading multiple reactive objects containing data tables

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!

Resources