22

With the button extension to DT package, is there a way to specify that the buttons download either (1) all the data feeding the datatable, or (2) only the data on the visible page.

Below is the example from the documentation.

datatable(
  iris, extensions = 'Buttons', options = list(
    dom = 'Bfrtip',
    buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
  )
)
zx8754
  • 52,746
  • 12
  • 114
  • 209
Vlad
  • 3,058
  • 4
  • 25
  • 53
  • The buttons already do the second thing. Just hit the copy-Button when you type 'setosa' in the searchbar. and if you don't apply any filter you get the first. So I do not see what the issue here is – 5th May 24 '18 at 13:01

4 Answers4

29

As @divibisan said, one option is to use the server argument of renderDT() to control whether the download button will download only the current or all rows.

That would work well if you want to have one download button. However if you want to have two buttons always appear, where one download the current page and one downloads the full dataset, you can use the following code:

library(shiny)

ui <- fluidPage(
  DT::DTOutput("table")
)

server <- function(input, output, session) {
  output$table <- DT::renderDT(server = FALSE, {
    DT::datatable(
      mtcars,
      extensions = c("Buttons"),
      options = list(
        dom = 'Bfrtip',
        buttons = list(
          list(extend = "csv", text = "Download Current Page", filename = "page",
               exportOptions = list(
                 modifier = list(page = "current")
               )
          ),
          list(extend = "csv", text = "Download Full Results", filename = "data",
               exportOptions = list(
                 modifier = list(page = "all")
               )
          )
        )
      )
    )
  })
}

shinyApp(ui, server)
DeanAttali
  • 25,268
  • 10
  • 92
  • 118
  • 1
    Hi DeanAttali, this solution doesn't work on my end. When I click on Download Full Results is still download data for a single page. Any thoughts? Could it be because mine is a renderDataTable? or because I have extensions = c("Buttons","FixedColumns") ? – Angelo Apr 16 '21 at 13:46
  • Nobody can answer that without seeing your code, but you should try to copy the exact code I have in my answer to determine if you're doing something wrong or not. If the exact code I provided has a different behaviour for you, then something with the package is wrong. – DeanAttali Apr 16 '21 at 19:52
  • Hi @DeanAttali this solution works really well, thanks. However this doesn't work when used in shiny modules. Not sure, but I guess something to do with namespace for the Buttons extension – Dhiraj Apr 21 '21 at 07:30
  • 1
    That's not my experience, I believe it works in modules. If you think it does not, then you should create a minimal reproducible example showing that this functionality is broken in modules, and submit it as an issue to the package. – DeanAttali Apr 22 '21 at 00:10
  • 3
    @DeanAttali it totally works in modules too. My bad, missed the `server = FALSE` part – Dhiraj May 12 '21 at 11:04
  • Its the way you answered the question, "That would work well". You should say, "That does work". You must have `server = FALSE` to get the whole data set. – kraggle Jul 22 '22 at 14:33
  • This looks really helpful - is there a way to limit the number of rows to download (say 10,000?) – supercoolphysicist Nov 23 '22 at 10:02
15

See this answer: Buttons: download button with scroller downloads only few rows

Whether the buttons export all data or only visible data is determined by the server argument in the DT::renderDT function call. If server=FALSE then the buttons will export all data in the table, while if server=TRUE they will only export visible data.

You could set the server argument with a variable to make this a selectable option.

output$table <- DT::renderDT(server = input$download_all, {
    DT::datatable( ... )
}

The other option you might want to look at is the exportOptions: modifier: selected option that determines whether to download only selected rows (the default) or all rows. You can read about that option here: https://datatables.net/extensions/buttons/examples/print/select.html

Note that your users might run into performance and memory issues using server=FALSE if your data table is very large.

DeanAttali
  • 25,268
  • 10
  • 92
  • 118
divibisan
  • 11,659
  • 11
  • 40
  • 58
5

you are looking for the modifiers: page: selected. here is a working example

ui <- fluidPage(
  title = "Examples of DataTables",
  sidebarLayout(
    mainPanel(
      tabsetPanel(
        id = 'dataset',
        tabPanel("diamonds", DT::dataTableOutput("mytable1"))
      )
    )
  )
)

server <- function(input, output) {

  # choose columns to display
  diamonds2 = diamonds[sample(nrow(diamonds), 1000), ]
  output$mytable1 <- DT::renderDataTable({
    DT::datatable(diamonds2,
                  extensions = 'Buttons',
                  options = list(
                    dom = 'Bfrtip',
                    buttons = 
                      list(
                        list(
                        extend = 'csv',
                        buttons = c('csv'),
                        exportOptions = list(
                          modifiers = list(page = "current")
                        )
                      ))
                    )
                  )
  })

}

shinyApp(ui, server)

hope this helps!

Bertil Baron
  • 4,923
  • 1
  • 15
  • 24
  • 2
    The code provided doesn't run, and I believe that it would only print the current page even without the options you added. – DeanAttali Jan 08 '20 at 06:06
  • 1
    I don't think `modifiers = list(page = "all")` does anything useful unless `server = FALSE`. And as @DeanAttali points out, I don't think `modifiers = list(page = "current")`actually changes any default behavior when `server = TRUE` (the default). – Giovanni Colitti Jan 27 '22 at 20:17
  • This works @Bertil Baron. – TarJae Dec 04 '22 at 07:57
3

If you want to include the options to download the current page and the entire dataset as both a csv or an excel file, I've managed to implement this as two separate dropdown buttons with those options, together with the copy and print buttons:

enter image description here

Here is the modified working code:

library(shiny)

ui <- fluidPage(
  DT::dataTableOutput("table")
)

server <- function(input, output, session) {
  output$table <- DT::renderDataTable(server = FALSE, {
    DT::datatable(
      mtcars,
      extensions = "Buttons",
      filter = "top",
      selection = "none", #this is to avoid select rows if you click on the rows
      rownames = FALSE,
      
      options = list(
        
        scrollX = TRUE,
        autoWidth = FALSE,
        dom = 'Blrtip', # the important thing is that there is the l to allow for the lengthMenu 
        # https://stackoverflow.com/questions/52645959/r-datatables-do-not-display-buttons-and-length-menu-simultaneously
        
        buttons = list(
          
          # insert buttons with copy and print
          # colvis includes the button to select and view only certain columns in the output table
          # from https://rstudio.github.io/DT/extensions.html 
          I('colvis'), 'copy', 'print',
          
          # code for the first dropdown download button
          # this will download only the current page only (depends on the number of rows selected in the lengthMenu)
          # using modifier = list(page = "current")
          # only the columns visible will be downloaded using the columns:":visible" option from:
          # https://stackoverflow.com/questions/72317260/how-to-download-only-the-selected-columns-in-a-dataframe-using-colvis-from-dt-in/72317607#72317607
          list(
            extend = 'collection',
          buttons = list(
          list(extend = "csv", filename = "page",exportOptions = list(
            columns = ":visible",modifier = list(page = "current"))
          ),
          list(extend = 'excel', filename = "page", title = NULL, 
               exportOptions = list(columns = ":visible",modifier = list(page = "current")))),
          text = 'Download current page'),
          
          # code for the  second dropdown download button
          # this will download the entire dataset using modifier = list(page = "all")
          list(
            extend = 'collection',
            buttons = list(
              list(extend = "csv", filename = "data",exportOptions = list(
                columns = ":visible",modifier = list(page = "all"))
              ),
              list(extend = 'excel', filename = "data", title = NULL, 
                   exportOptions = list(columns = ":visible",modifier = list(page = "all")))),
            text = 'Download all data')
          
        ),
        # add the option to display more rows as a length menu
        lengthMenu = list(c(10, 30, 50, -1),
                          c('10', '30', '50', 'All'))
        ),
      class = "display"
      )
    
  })
}

shinyApp(ui, server)
FranBC
  • 57
  • 5