Upload file, display file in data.frame table and save table in file, or save file into data.frame in local directory for editing and upload it afterwrads?


#1

The code below displays a table and saves it to a file:

library(rhandsontable)
library(shiny)


ui <- fluidPage(
  titlePanel("Edit and save table"),
  sidebarLayout(sidebarPanel(
    helpText("Shiny app based on an example given in the rhandsontable package.", 
             "Right-click on the table to delete/insert rows.", 
             "Double-click on a cell to edit"),
    wellPanel(
      h3("Table options"),
      radioButtons("useType", "Use Data Types", c("TRUE", "FALSE"))
    ),
    br(),
    wellPanel(
      h3("Save table"),
      div(class='row', 
          div(class="col-sm-6", 
              actionButton("save", "Save"))),
      div(class="col-sm-6",
          radioButtons("fileType", "File type", c("ASCII", "RDS")))
    )
  ),
  mainPanel(
    wellPanel(
      uiOutput("message", inline=TRUE)
    ),
    
    actionButton("cancel", "Cancel last action"),
    br(), br(), 
    
    rHandsontableOutput("hot"),
    br(),
    wellPanel(
      h3("Add a column"),
      div(class='row', div(class="col-sm-5", 
                uiOutput("ui_newcolname"),
                actionButton("addcolumn", "Add")),
          div(class="col-sm-4", 
              radioButtons("newcolumntype", "Type", c("integer", "double", "character"))),
          div(class="col-sm-3"))
    )
  )
)
)
   

server <- shinyServer(function(input, output) {
  values <- reactiveValues()
  outdir <- getwd()
  DF  = data.frame(integer = c(NA, 2:10), 
                       logical = c(NA, rep(TRUE, 9)), 
                       character = c(NA, LETTERS[1:9]),
                       factor = c(NA, factor(letters[1:9])),
                       date = c(NA, seq(from = Sys.Date(), by = "days", 
                                        length.out = 9)),
                       stringsAsFactors = FALSE)
  
  DF$factor_ch = as.character(DF$factor)
  DF$date_ch = c(NA, as.character(seq(from = Sys.Date(), by = "days", 
                                         length.out = 9)))
  rhandsontable(DF, width = 550, height = 300)
  
  observe({
    if (!is.null(input$hot)) {
      values[["previous"]] <- isolate(values[["DF"]])
      DF = hot_to_r(input$hot)
    } else {
      if (is.null(values[["DF"]]))
        DF <- DF
      else
        DF <- values[["DF"]]
    }
    values[["DF"]] <- DF
  })
  
  output$hot <- renderRHandsontable({
    DF <- values[["DF"]]
    if (!is.null(DF))
      rhandsontable(DF, useTypes = as.logical(input$useType), stretchH = "all")
  })
  observeEvent(input$save, {
    fileType <- isolate(input$fileType)
    finalDF <- isolate(values[["DF"]])
    if(fileType == "ASCII"){
      dput(finalDF, file=file.path(outdir, sprintf("%s.txt", outfilename)))
    }
    else{
      saveRDS(finalDF, file=file.path(outdir, sprintf("%s.rds", outfilename)))
    }
  }
  )
  
  observeEvent(input$cancel, {
    if(!is.null(isolate(values[["previous"]]))) values[["DF"]] <- isolate(values[["previous"]])
  })
  output$ui_newcolname <- renderUI({
    textInput("newcolumnname", "Name", sprintf("newcol%s", 1+ncol(values[["DF"]])))
  })
  observeEvent(input$addcolumn, {
    DF <- isolate(values[["DF"]])
    values[["previous"]] <- DF
    newcolumn <- eval(parse(text=sprintf('%s(nrow(DF))', isolate(input$newcolumntype))))
    values[["DF"]] <- setNames(cbind(DF, newcolumn, stringsAsFactors=FALSE), c(names(DF), isolate(input$newcolumnname)))
  })
  output$message <- renderUI({
    if(input$save==0){
      helpText(sprintf("This table will be saved in folder \"%s\" once you press the Save button.", outdir))
    }else{
      outfile <- ifelse(isolate(input$fileType)=="ASCII", "table.txt", "table.rds")
      fun <- ifelse(isolate(input$fileType)=="ASCII", "dget", "readRDS")
      list(helpText(sprintf("File saved: \"%s\".", file.path(outdir, outfile))),
           helpText(sprintf("Type %s(\"%s\") to get it.", fun, outfile)))
    }
  })

The code below uploads a file:



ui <- fluidPage(
  
  tags$head(
    tags$style(HTML("
                    @import url('//fonts.googleapis.com/css?family='Helvetica', 'Arial', sans-serif:400,700');
                    "))
    ),
  fluidRow(
    column(width = 3, offset = 1),
    headerPanel(
      h1("glycoPipe - Identification and Analysis Pipeline R Package", 
         style = "font-family: 'Lobster', 'cursive';
         font-weight: 500; line-height: 1.1; 
         color: #394779;"))
      ),
  
  
  sidebarLayout(
    sidebarPanel(
      fluidRow(
        column(width = 3, offset = 0,
               img(src="logo.jpeg", height = 50, width = 200, align = "middle"))
      ),
      fluidRow(
        column(width = 3, offset = 0,div(style = "height:25px;background-color: #99CCFF", strong("Urology"))
        )
      ),
      
      # "")
      #fileInput("file", "upload the file"),
      #h5("Max file size to upload is 5 MB")
      fluidRow(
        column(width = 10,
               
               selectInput("value", label = h4("Do you have a parameter file ready to use, Y/N?"), 
                           choices =c("", "Y" , "N"), selected = NULL))
      ),
      conditionalPanel(
        condition = "input.value == 'Y'",
        helpText(h4("Select your params file (tab delimited).")),
        fluidRow(
          column(width = 10,fileInput("file", "upload the file" ),
                 helpText("Default max file size 5 MB"),
                 accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv', ',tsv'),
                 tags$hr(),
                 h5(helpText("select the parameters below")),
                 checkboxInput(inputId = "Header","Header?", value = FALSE),
                 br(),
                 radioButtons(inputId = "sep", label = "separator", choices = c(Comma = ",", Semicolon = ";", Tab = "\t", Space = " "))
          )
          
        )
      ),
      conditionalPanel(
        condition = "input.value == 'N'",
        helpText(h4("Fetch the glycoPipe_PARAMS_TEMPLATE file. You' ll save
                    a copy to your workig folder with a new name. glycoPipe
                    will then quit, and you will fill in and save your PARAMS file.
                    Then you' ll need to restart glycoPipe.
                    
                    Now save the template file under a new name in a location
                    of your choice.  The best suffix is .tsv" )),
        fluidRow(
        column(width = 10, myParamsFile = readLines(file.choose()),
               edit(myParamsFile)
               #fileInput("file2", "upload the file" ),
               #helpText("Default max file size 5 MB"),
               #accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv', ',tsv'),
               #tags$hr(),
               #h5(helpText("select the parameters below")),
               #checkboxInput(inputId = "Header","Header?", value = FALSE),
               #br(),
               #radioButtons(inputId = "sep", label = "separator", choices = c(Comma = ",", Semicolon = ";", Tab = "\t", Space = " "))
        )
      )
      )
    ),
     
    
    mainPanel(
      #textOutput("value"),
      tableOutput("contents")
      #tableOutput("contents2")
      
    )
  )
)



server <- function(input, output){
  
  # output$value <- renderText({
  # paste("You chose", input$value)
  # })

  output$contents <- renderTable({
    inFile = input$file
    if(is.null("inFile")){
     return()
    }
    
    #read.table(inFile$datapath, header = FALSE, sep = "", quote =  "\"'",
      #         dec = ".", numerals = c("allow.loss", "warn.loss", "no.loss"),
       #        row.names, col.names, as.is = !stringsAsFactors,
        #       na.strings = "NA", colClasses = NA, nrows = -1,
       #        skip = 0, check.names = TRUE, fill = !blank.lines.skip,
       #        strip.white = FALSE, blank.lines.skip = TRUE,
        #       comment.char = "#",
       #        allowEscapes = FALSE, flush = FALSE,
        #       stringsAsFactors = default.stringsAsFactors(),
        #  fileEncoding = "", encoding = "unknown", text, skipNul = FALSE)
    #readLines("~/Downloads/glycoPipe_PARAMS_TEMPLATE.tsv")
  })
  #output$contents2 <- renderTable({
    #inFile2 = input$file2
   # if(is.null("inFile2")){
    #  return()
   # }
  #})
}

shinyApp(ui = ui, server = server)

Is it possible to save the uploaded file into a data.frame for display, editing, saving and processing by the program?. Should the file be read as data. frame in the local directory for editing and saving and uploaded afterwards for processing?


#2

cannot coerce class “c(“rhandsontable”, “htmlwidget”)” to a data.frame. This is the error that I get when IO try to run this code:

 DF = read.delim(inFile$datapath)
    rhandsontable(DF, width = 550, height = 300)

read.delim() returns a dataframe and rhandsonetable requires a dataframe. I do not understand why it does notwork

as.data.frame( DF = read.delim(inFile$datapath)
rhandsontable(DF, width = 550, height = 300)) returns the same error.


#3

So that this can help anybody else who is interested on the same topic, here is good code from the Github:

library(shiny)


ui <- fluidPage(
  titlePanel("Edit Data File"),
  helpText("Changes to the table will be automatically saved to the source file."),
  # uncomment line below to use action button to commit changes
  actionButton("saveBtn", "Save"),
  rHandsontableOutput("hot")
)

server <- (function(input, output, session) {
  fname = tempfile(fileext = ".tsv")
  
  in_data <- reactive({
    inFile <- input$file
    if (is.null(inFile)) return(NULL)     
    else read.csv(inFile$datapath, as.is=TRUE)  
  })
  output$frame <- renderTable({
    in_data()
  })
  
  observe({
    # remove button and isolate to update file automatically
    # after each table change
    input$saveBtn
    hot = isolate(input$hot)
    if (!is.null(hot)) {
      write.table(hot_to_r(input$hot), fname)
      print(fname)
    }
  })
  
  output$hot = renderRHandsontable({
    if (!is.null(input$hot)) {
      DF = hot_to_r(input$hot)
    } else {
      DF = read.table("glycoPipe_PARAMS_TEMPLATE.tsv", sep = "\t", stringsAsFactors = FALSE)
    }
    
    rhandsontable(DF) %>%
      hot_table(highlightCol = TRUE, highlightRow = TRUE)
  })
})
shinyApp(ui = ui, server = server)