Home > Software design >  How to insert a row of text on top of a table downloaded using the shiny download handler?
How to insert a row of text on top of a table downloaded using the shiny download handler?

Time:05-06

Chosen solution added to end of this OP

In the below shortened reproducible code the user can download the output dataframe by clicking on the downloadButton() at the top of the UI. How do I insert a row of text, describing the table, above the table when it is downloaded as a csv file? As shown in the image at the bottom.

Reproducible code:

library(dplyr)
library(DT)
library(shiny)
library(shinyWidgets)
library(tidyverse)

ui <-
  fluidPage(fluidRow(
    column(width = 8,
           h3("Click below to download:"),
           downloadButton("sumsDownload","Download",style = "width:20%;"),
           h3("Summed Data:"),
           DT::dataTableOutput("sums")
          )
  ))

server <- function(input, output, session) {
  data <- reactive({
    data.frame(
      Period = c("2020-01", "2020-02", "2020-03", "2020-01", "2020-02", "2020-03"),
      ColA = c(1000.01, 20, 30, 40, 50, 60),
      ColB = c(15.06, 25, 35, 45, 55, 65)
    )
  })
  
  summed_data <- reactive({
    data() %>%
      group_by(!!sym("Period")) %>%
      select("ColA", "ColB") %>% summarise(across(everything(), sum))
  })
  
  output$sums <- renderDT({datatable(data = summed_data(),rownames = FALSE)})
  
  output$sumsDownload <- downloadHandler(
    filename = function() {paste("sumsDownload","csv",sep=".")},
    content = function(file) {write.csv(summed_data(), file,row.names=FALSE)}
  )
  
}

shinyApp(ui, server)

enter image description here

Chosen solution:

Create a reactive dataframe df that merges the summed_data() dataframe with a vector (placed at the top of the df dataframe) with the table name of "Summed Data" followed by a series of NA in that row, which are then filtered out in downloadHandler(). The downloadHandler() below is also revised from the OP, replacing write.csv() with write.table().

df <- reactive({ # `df` modifies `summed_data` for csv download
    as.data.frame(
      rbind(
        c("Summed Data",rep(NA,ncol(summed_data())-1)),
        colnames(summed_data()),
        matrix(unlist(summed_data(), use.names=FALSE),
               nrow = nrow(summed_data()),
               )
          )
      )
  })
  
  output$sumsDownload <- downloadHandler(
    filename = function() {paste("sumsDownload","csv",sep=".")},
    content = function(file){
      write.table( 
        df(),
        na = "", 
        file, 
        sep = ",", # add this per road_to_quantdom on May/05/22
        col.names = FALSE, 
        row.names = FALSE)
      }
  )
}

CodePudding user response:

Open the output file in append mode, write the header line, and then write the CSV data:

f <- file("mtcars.csv", "a")
writeLines("Motor Trend Car Road Tests", f)
write.csv(mtcars, f)
close(f)

head(readLines("mtcars.csv"))
#> [1] "Motor Trend Car Road Tests"                                                                   
#> [2] "\"\",\"mpg\",\"cyl\",\"disp\",\"hp\",\"drat\",\"wt\",\"qsec\",\"vs\",\"am\",\"gear\",\"carb\""
#> [3] "\"Mazda RX4\",21,6,160,110,3.9,2.62,16.46,0,1,4,4"                                            
#> [4] "\"Mazda RX4 Wag\",21,6,160,110,3.9,2.875,17.02,0,1,4,4"                                       
#> [5] "\"Datsun 710\",22.8,4,108,93,3.85,2.32,18.61,1,1,4,1"                                         
#> [6] "\"Hornet 4 Drive\",21.4,6,258,110,3.08,3.215,19.44,1,0,3,1"
  • Related