0

I need to do something extremely similar to what asked and answered here: How to edit and save changes made on Shiny dataTable using DT package

The key difference is that in my case the dataframe (table) is not a global variable. Data is stored in a csv file. A user can click on the Read button, visualize it in Shiny, edit the table there, and then click on save. The problem I face is that the code below is using observeEvent in such a way the data is always kept in a global variable. Instead, when clicking on Save, I would need it to point directly whatever data is available in the output datatable displayed in the app. Code:

library(shiny)
library(shinydashboard)
library(shinyBS)
library(dplyr)
library(lubridate)
library(DT)

Admit <- c("Admitted","Rejected","Admitted", "Rejected", "Admitted", "Rejected", "Admitted",
           "Rejected","Admitted", "Rejected", "Admitted","Rejected","Admitted", "Rejected","Admitted","Rejected", "Admitted", "Rejected",
           "Admitted","Rejected", "Admitted" ,"Rejected","Admitted", "Rejected") 

Gender <- c("Male","Male","Female","Female", "Male",   "Male",   "Female", "Female", "Male","Male","Female","Female",
            "Male","Male","Female","Female","Male",   "Male",   "Female", "Female","Male","Male","Female","Female")

Dept <- c( "A","A", "A", "A", "B", "B", "B", "B", "C", "C", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "F", "F", "F", "F")

Freq <- c("512", "313",  "89",  "19", "353", "207",  "17",   "8", "120", "205", "202", "391", "138", "279", "131", "244",  "53", "138",
          "94", "299",  "22", "351",  "24", "317")

banking.df <- data.frame(Admit,Gender,Dept, Freq,stringsAsFactors = FALSE) 

d1 = banking.df
d1$Date = Sys.time() + seq_len(nrow(d1))


ui <- fluidPage(
  
  mainPanel(
    h3(" EDITABLE Table:"),
    fluidPage(
      titlePanel("UC Berkley Admissions"),
      
      mainPanel(
        tabsetPanel(
                        id = 'dataset',
                        tabPanel("Sample Bank", 
                                 
                                 DT::dataTableOutput("banking.df_data"),
                                 br(),
                                 actionButton("viewBtn","View"),
                                 br(),
                                 actionButton("saveBtn","Save"),
                                 br(),
                                 DT::dataTableOutput("updated.df")
                                )
                    )
        ))
  )
  
)

server <- function(input, output, session) {   
  
      output$banking.df_data <- renderDataTable({
        
        
        
        df <- datatable(
                        d1,
                        selection = 'none', editable = TRUE, 
                        rownames = TRUE,
                        extensions = 'Buttons',
                        
                        options = list(
                          paging = TRUE,
                          searching = TRUE,
                          fixedColumns = TRUE,
                          autoWidth = TRUE,
                          ordering = TRUE,
                          dom = 'Bfrtip',
                          buttons = c('csv', 'excel')
                        ),
                        
                        class = "display"
                      )
        
        return(df)
      })
      
      
      observeEvent(input$banking.df_data_cell_edit, {
              d1[input$banking.df_data_cell_edit$row,input$banking.df_data_cell_edit$col] <<- input$banking.df_data_cell_edit$value
      })
      
      view_fun <- eventReactive(input$viewBtn,{
              if(is.null(input$saveBtn)||input$saveBtn==0)
              {
                returnValue()
              }
              else
              {
                DT::datatable(d1,selection = 'none')
              }
        
      })
      
      
      observeEvent(input$saveBtn,{
        cat("\n\n* Saving table in directory: ", getwd())
        file_name <- 'test.csv'
        curr_dt_time <- as.character(Sys.time())
        curr_dt_time <- gsub(":", "_", curr_dt_time  )
        if(file.exists(file_name)){
              df <- read.csv(file = file_name)
              
              write.csv(df, paste0(file_name,"_last_save_",curr_dt_time,".csv")
                        #, row.names = FALSE
              )
        }
        write.csv(d1,'test.csv')
      })
      
      output$updated.df<-renderDataTable({
        view_fun()
      }
      )
}


cat("\nLaunching   'shinyApp' ....")
shinyApp(ui, server)
Angelo
  • 1,594
  • 5
  • 17
  • 50
  • I'm not sure why you want to show two data frames. I also don't understand why you keep reading the same file (test.csv) and also saving it. Do you need to keep track of an original copy and a modified one? Could you explain a little more please? – Tomas Capretto Apr 01 '21 at 02:32
  • Hi Tomas, I tried to adapt the code I found on the link I provided but you're right I definitely do not need to show two dataframes. On the other hand, thanks for pointing it out, I on purpose keep track of the original in case one of the many users accidentally edit and save the CSV file. – Angelo Apr 01 '21 at 12:15

0 Answers0