Append a new line in a data frame when saving it in downloadHandler

78 views Asked by At

I want to append a new line in a data frame and save it as csv file in R shiny.

df <- data.frame(x = 1:5, y = 1:5)
fn <- "Result.csv"
header <- "this is a new line"
writeLines(header, fn)

## Shiny server file------------

output$OutputFile <- downloadHandler(
    content <- function() {
      write.table(x = df, 
                  file = fn,
                  sep = ",",
                  append = TRUE,
                  quote = FALSE,
                  col.names = TRUE,
                  row.names = FALSE
                  )
      }
    )

But it did not work, is it possible to use write.table in shiny?

1

There are 1 answers

0
gss On

I think it is not possible to use append = TRUE argument in write.table() in case of shiny::downloadHandler(). I have read a documentation for parameter append and see:

logical. Only relevant if file is a character string. If TRUE, the output is appended to the file. If FALSE, any existing file of the name is destroyed.

If I understand this correct, write.table with append = TRUE looks for the file with specified name and in specified directory to see if this file exists and if yes - it appends object to the content of this file. However, in case of shiny::downloadHandler() functions using to write file do not write the files directly to the folder, but creates a downloadable file, which then can be download using the web browser. Below you can see the MRE showing how to use downloadHandler():

library(shiny)

df <- data.frame(x = 1:5, y = 1:5)
#fn <- "Result.csv"
#header <- "this is a new line"
#writeLines(header, fn)

ui <- fluidPage(
  downloadButton("OutputFile")
)

server <- function(input, output, session) {
  output$OutputFile <- downloadHandler(
    filename = function() {
      "Result.csv"
    },
    content = function(file) {
      write.table(x = df, 
                  file = file,
                  sep = ",",
                  append = TRUE,
                  quote = FALSE,
                  col.names = TRUE,
                  row.names = FALSE
      )
    }
  )
}

shinyApp(ui, server)

However, we can try to create something different to make use of append = TRUE, but not using downloadHandler. We can do something like this:

  1. At the beginning (i.e. when starting an App), create the file (are destroy the previous file with the same name).
  2. Read this file, so it will be accessible in the App (optionally: monitor if this file was edited and if yes - read it again).
  3. Use a button to write a content to this file (using write.table with parameter append set to TRUE):
library(shiny)
library(magrittr)

df <- data.frame(x = 1:5, y = 1:5)
df2 <- data.frame(x = 10, y = 10)
write.table(df, "Result.csv", sep = ",", append = FALSE, quote = FALSE,
            col.names = TRUE, row.names = FALSE)

ui <- fluidPage(
  tableOutput("result"),
  actionButton("append", "Append 'df2'")
)

server <- function(input, output, session) {
  file <- reactiveFileReader(100, session, "Result.csv", read.table, header = TRUE, sep = ",")
  
  output$result <- renderTable({
    file()
  })
  
  observe({
    write.table(df2, "Result.csv", sep = ",", append = TRUE, quote = FALSE,
                col.names = FALSE, row.names = FALSE)
  }) %>% 
    bindEvent(input$append)
  
}

shinyApp(ui, server)