I am currently trying to generate a Shiny App that at the press of a button generates and downloads data for a user. I have a user defined function that pulls data from some places, analyzes, and creates a .csv comprised of numerous tables.
The bottleneck I'm running into is successfully taking this .csv file comprised of multiple tables and allowing it to be easily downloaded. I have tried applying the solution presented here, but when I run the application script, all of the data is generated from the button but it doesn't bring up the download window as I'd hoped. Is there a way of using downloadHandler and link it to something other than a downloadButton or downloadLink function?
Current UI Function:
ui <- dashboardPage(
dashboardHeader(title = "Download Center"),
dashboardSidebar(
sidebarMenu(id="mytabs",
sidebarMenuOutput("menu")
)
),
dashboardBody(tabItems(
tabItem(tabName = "DataHarah", h2("Download Your Data Here"),
textInput(inputId='startyear', label='What is the first year?'
,value=2021, width = NULL, placeholder = "Inputs should be
a four digit year (e.g. 2022)."),
textInput(inputId='endyear', label='What is the last year?'
,value=2022, width = NULL, placeholder = "Inputs should be
a four digit year (e.g. 2022)."),
actionButton("do", "Generate & Download Your Data!")
))
))
Current Server Function & Initialization:
observeEvent(input$do,
{DataTalk(input$startyear,input$endyear) # function that generates a csv file
# containing multiple tables.
output$downloadData <- downloadHandler( #download handler that may not be connected properly.
filename = c('mycsv.csv'),
content = function(file){
file.copy('mycsv.csv',file)})})}
shinyApp(ui, server)
Related
Sorry for what seems like a basic question, I'm very new to R and programming in general. I want to be able to determine what file type was picked from a file. For example, in this code I need to have two separate buttons for importing a CSV or excel file:
observeEvent(input$CSV, {
Table <- read.table(file.choose(), header=TRUE, sep=",")
output$ImportedTable <- DT::renderDataTable(Table)
})
observeEvent(input$Excel, {
Table <- read_excel(file.choose())
output$ImportedTable <- DT::renderDataTable(Table)
})
(input$Excel/CSV is the output of an actionButton in the main pannel)
Ideally, I'd like to only require one button instead of two, and have the program able to determine what file type was chosen, and import it accordingly. and ideally, I'd like to be able to sort what data types are available to choose from when importing, since currently it allows the user to pick all file types, instead of just ones in a table format. I'd appreciate any help, thanks!
You seem to work with shiny (this is an important bit of information missing from your main post).
In shiny you can use fileInput to restrict the format of input files. Here is a minimal reproducible example.
library(shiny)
ui <- fluidPage(
fileInput(inputId = "file_csv", label = "CSV file", accept = ".csv"),
fileInput(inputId = "file_xlsx", label = "XLSX file", accept = ".xlsx"),
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
Note that you can see the effect of accept when opening the app in your browser of choice. RStudio's native app window or Viewer Pane does not seem to respect the accept argument.
I am working on a shiny app where the user uploads a number of csv files based on which some output is created. The files to upload are produced by an external application and all lie in the same folder. I want the user to be able to select all files in the folder for upload and I am currently using
shiny::fileInput() with the option multiple = TRUE in the shiny App.
The problem I have is that the output folder contains a file that can be quite large and that is not required for the analysis in the app. The app works fine if the user just deselects that file in the upload menu. But I was wondering if there is a way that I can tell the app to ignore a certain file (based on the file name), so that even if the user selects all files in the folder for upload, the large file is not uploaded while all the other selected files still are.
I know that you can set a maximum file size in the options (shiny.maxRequestSize) but this does not seem to solve my problem, as the upload then ends with an error if the large file is selected.
Here is a minimal example of the app:
library(shiny)
options(shiny.maxRequestSize = 30*1024^2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# Upload menu is created here:
fileInput(
inputId = "upload",
label = "Upload Files",
buttonLabel = "Select files...",
multiple = TRUE
)
),
mainPanel(
tableOutput(outputId = "files")
)
)
)
server <- function(input, output, session) {
output$files <- renderTable(
input$upload[, c("name", "size")]
)
}
shinyApp(ui, server)
I am working on a Shiny app that reads Word documents uploaded by users. The uploaded document then displays a table of all elements in the document and their formatting. I want it to also show any pictures from the uploaded Word doc. Documents containing multiple images aren't an issue - users will only ever upload documents with one image.
To do this, I am using the officer package. It has a function called media_extract where you can do exactly what I want. The issue is, while the documentation says this function can be used to extract images from .doc or .ppt files, I can only get it to work for the latter. This is because media_extract takes the image file path as an argument, but I cannot generate a file path for Word docs. The file path is generated by using one of two officer functions depending on the file type: docx_summary or pptx_summary. These are also the functions I use to generate the tables rendered in my app. The pptx_summary creates a table with a media_path column, which displays a file path for image elements, while docx_summary generates no such column. Absent that column and the path it includes, I don't know how to extract images from Word docs using this function.
For your convenience, here is my code for two Shiny apps: one that reads powerpoints and one for word docs. If you upload a powerpoint file and word file that include an image you will see how the tables generated in each app are different. My powerpoint app also renders an image, to show you how that is done. Obviously that functionality is not in my word app...
Powerpoint reader app:
library(officer)
library(DT)
library(shiny)
ui<- fluidPage(
titlePanel("Document Scanner"),
sidebarLayout(
sidebarPanel(
fileInput("uploadedfile", "Upload a file", multiple=FALSE,
accept=c(".ppt", ".pptx", ".docx"))
),
mainPanel(
tags$h3(tags$b("Document Summary")),
br(),
DT::dataTableOutput("display_table"),
br(),
imageOutput("myImage")
)
)
)
server<-function(input,output) {
#creating reactive value for uploaded file
x<-reactive({
uploadedfileDF<- input$uploadedfile
uploadedfileDataPath<- uploadedfileDF$datapath
read_pptx(uploadedfileDataPath)
})
#rendering formatting table
output$display_table<-DT::renderDataTable({
req(input$uploadedfile)
DT::datatable(pptx_summary(x()))
})
#rendering images from powerpoint
output$myImage<-renderImage({
readFile<-x()
fileSummaryDF<-pptx_summary(readFile)
#Getting path to image (this is basically straight from the documentation
#for media_extract)
fileSummaryDF_filtered<- fileSummaryDF[fileSummaryDF$content_type %in% "image", ]
media_file <- fileSummaryDF_filtered$media_file
png_file <- tempfile(fileext = ".png")
media_extract(readFile, path = media_file, target = png_file)
list(src = png_file,
alt="Test Picture")
})
}
shinyApp(ui, server)
Word reader app:
library(officer)
library(DT)
library(shiny)
ui<- fluidPage(
titlePanel("Word Doc Scanner"),
sidebarLayout(
sidebarPanel(
fileInput("uploadedfile", "Upload a file", multiple=FALSE,
accept=c(".doc", ".docx"))
),
mainPanel(
tags$h3(tags$b("Document Summary")),
br(),
DT::dataTableOutput("display_table"),
imageOutput("image1")
)
)
)
server<-function(input,output) {
# creating reactive content from uploaded file
x<-reactive({
print(input$uploadedfile)
uploadedfileDF<- input$uploadedfile
uploadedfileDataPath<- uploadedfileDF$datapath
docDF<-read_docx(path=uploadedfileDataPath)
summaryDF<-docx_summary(docDF)
})
#rendering formatting table
output$display_table<-DT::renderDataTable({
req(input$uploadedfile)
DT::datatable(x())
})
#how to render image without a image path anywhere in table?
}
shinyApp(ui, server)
If this can't be done in officer then I'm happy to do it a different way. Thank you.
I have a Shiny application that requires the user to upload multiple small text files, I do this with fileInput. When I upload multiple files, the progress bar seems to half reset after each file is uploaded in turn. This looks very messy and I'd prefer it if the bar simply showed how many files had finished uploading rather than the progress of any individual file.
Here is a gif of the behavior:
My question is: Is there a way using base Shiny to change the behavior of the upload progress bar for fileInput? And if not, are there any other packages that could be used?
Here is an example of using fileInput
library(shiny)
ui <- fluidPage(
titlePanel("File Input Progress Bar Demo"),
fileInput(
inputId = "MyFiles",
label = "Upload multiple files",
multiple = T
),
mainPanel()
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
The code below produces a DataTable output that I'd like to have it emailed using an Email button, similar to the Export button created below. Is there an easy way to add a button so that when you click, it pops up Microsoft Outlook to send the datatable as an attachment, say in csv format?
Also, please click here and here to help with a similar questions.
#Load required packages
require(shiny)
#Create a dataframe
df <- data.frame(random=1:160)
server <- function(input,output,session){
#Display df using DataTable and apply desired options
output$display <- renderDataTable({df},
option=list(pageLength=100,
"dom" = 'T<"clear">lfrtip',
"tableTools" = list(
"sSwfPath" = "//cdn.datatables.net/tabletools/2.2.3/swf/copy_csv_xls_pdf.swf",
"aButtons" = list(list("sExtends" = "csv","oSelectorOpts"=list("page"="all"),"sButtonText" = "Export","aButtons" ="csv")))
)
)
}
ui <- shinyUI(fluidPage(
#Add a title
h1('Testing TableTools'),
#Add required JS libraries
tagList(
singleton(tags$head(tags$script(src='//cdn.datatables.net/1.10.4/js/jquery.dataTables.min.js',type='text/javascript'))),
singleton(tags$head(tags$script(src='//cdn.datatables.net/tabletools/2.2.3/js/dataTables.tableTools.min.js',type='text/javascript'))),
singleton(tags$head(tags$link(href='//cdn.datatables.net/tabletools/2.2.3/css/dataTables.tableTools.css',rel='stylesheet',type='text/css')))
),
mainPanel(
#Display results
dataTableOutput('display')
)
))
shinyApp(ui = ui, server = server)
A quick way is to use mailto(which works well with Outlook).
The mailto would need to be inside an HTML() tag for shiny to render it.
HTML(
<a href="mailto:hello#rshiny.com?
body='Hello,World! Check out my data.'
&subject='Data'
&attachment='\\myfolder\shinyData.csv'">click here for email!</a>
)
There are two hypothetical ways to do this.
Have the mailto in ui.R
The code would need to download the datatable at the user's end (probably in the temp folder), and attach it there.
Have the mailto in server.R
You'll need the csv file already saved on your server in order to load it as an attachment. You would need to use the above code inside a renderUI() and also pass the file from your server to the user's end.
There is a downloadHandler() function which allows users to download from the server which could be of use for the above.
I've never tried passing attachments around as you are trying, however the above logic should both allow you to create an email, and get you on the right path to attaching files.