简体   繁体   中英

How to use write.table to download a dataframe into a nice csv/Excel file?

I am trying to use the write.table() function, within Shiny downloadHandler() , to download the df reactive dataframe as a .csv file, per the reproducible code at the bottom. Function write.table() allows the dropping of column names (which I need) but results in non-Excel output ( Issue #1 ); write.csv() on the other hand results in nice Excel output but does not allow the dropping of column names ( Issue #2 ).

Is there a way to get write.table() to work properly for CSV? If not, is there any other way to resolve this?

This image shows the issues:

在此处输入图像描述

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)})
  
  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( # change this to write.csv to see Issue #2
        df(),
        na = "", 
        file, 
        col.names = FALSE, # comment out this line if changing to write.csv
        row.names = FALSE)
      }
  )
}

shinyApp(ui, server)

Below is resolved code reflecting comments posted through 05 May 2022:

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)})
  
  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)
      }
  )
}

shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM