How To Add totals to a DT::datatable?

前端 未结 3 1437
夕颜
夕颜 2021-01-05 11:06

I am trying to add totals to a data table footer. Using code from different sources, I wrote the following application using Shiny. The problem is, when I run it, the follow

相关标签:
3条回答
  • 2021-01-05 11:47

    Looks like you're using the same example program I did in shiny DataTables footer Callback sums so my solution to the footer callback issue is below. This is the easiest that I've found to manipulate on a column by column basis.

    library(shiny)
    library(DT)
    
    ui <- fluidPage(
    
      title = 'Select Table Rows',
    
      hr(),
    
      h1('A Server-side Table'),
    
      fluidRow(
        column(9, DT::dataTableOutput('x3'))
      )
    
    )
    
    
    server <- function(input, output, session) {
    
      # server-side processing
    
      mtcars2 = mtcars[, 1:8]
    
      sketch <- htmltools::withTags(table(
                      class = "display",
                      style = "bootstrap",
                      tableHeader(colnames(mtcars2)),
                      tableFooter(colnames(mtcars2))
              ))
    
      output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
                                                    container = sketch,
                                                    extensions = 'Buttons',
                                                    options = list(
                                                      scrollX = TRUE,
                                                      scrollY = TRUE,
                                                      pageLength = 10,
                                                      order = list(list(1, 'asc')),
                                                      dom = 'Blrtip',
                                                      buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
                                                      footerCallback = JS(
           "function( tfoot, data, start, end, display ) {",
           "var api = this.api(), data;",
            "total = api.column( 1, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
            "total1 = api.column( 2, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
           "total2 = api.column( 3, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
            "total3 = api.column( 4, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
           "total4 = api.column( 5, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
            "total5 = api.column( 6, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
           "total6 = api.column( 7, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
            "total7 = api.column( 8, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
            "$( api.column( 1 ).footer() ).html(total.toFixed(2));
            $( api.column( 2 ).footer() ).html(total1.toFixed(2));
            $( api.column( 3 ).footer() ).html(total2.toFixed(2));
            $( api.column( 4 ).footer() ).html(total3.toFixed(2));
            $( api.column( 5 ).footer() ).html(total4.toFixed(2));
            $( api.column( 6 ).footer() ).html(total5.toFixed(2));
            $( api.column( 7 ).footer() ).html(total6.toFixed(2));
            $( api.column( 8 ).footer() ).html(total7.toFixed(2));",
            "}"
            ))
          ))
    }
    
    shinyApp(ui = ui, server = server)
    
    0 讨论(0)
  • 2021-01-05 11:50

    This is a version without using Shiny. I used the same JavaScript as @gscott above, but this is for a standalone table. I used this in a RMarkdown document. The key to this, which I struggled with, is the container argument, which adds the footer to the table.

    library(htmlwidgets)
    library(DT)
    library(htmltools)
    
    sketch <- htmltools::withTags(table(
      tableHeader(colnames(mtcars)), 
      tableFooter(c(0,0,0,0,0,0,0,0,0,0,0,0))
    ))
    
    jsCode <- "function(row, data, start, end, display) {
      var api = this.api(), data;
      total = api.column(7, {page: 'current'}).data().reduce( function(a, b) { return a + 
    b}, 0);
      total2 = api.column(6, {page: 'current'}).data().reduce( function(a, b) { return a 
    + b}, 0);
      total3 = api.column(2, {page: 'current'}).data().reduce( function(a, b) { return a 
    + b}, 0);
      $( api.column(7).footer() ).html('Total: ' + total.toFixed(2));
      $( api.column(6).footer() ).html('Total: ' + total2.toFixed(2));
      $( api.column(2).footer() ).html('Total: ' + total3.toFixed(2))
      }"
    
    DT::datatable(mtcars, container = sketch, options=list(scrollY=300, scrollX=TRUE, scroller=TRUE, footerCallback = JS(jsCode)))
    
    0 讨论(0)
  • 2021-01-05 11:50

    I managed to solve the same problem with the answers above, and the following is my implementation to reduce the amount of repeated JavaScript codes.

    I looped through the columns using columns().eq(0).each(), then aggregate the data, and add the result to the footer.

    library(shiny)
    library(DT)
    
    ui <- fluidPage(
            title = 'Select Table Rows', hr(), h1('A Server-side Table'),
            fluidRow(
                    column(9, DT::dataTableOutput('x3'))
            )
    )
    
    server <- function(input, output, session) {
            mtcars2 = mtcars[, 1:8]
            sketch <- htmltools::withTags(table(
                    class = "display", style = "bootstrap",
                    tableHeader(colnames(mtcars2)),
                    tableFooter(colnames(mtcars2))
            ))
    
            output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
                    container = sketch,
                    extensions = 'Buttons',
                    options = list(
                            scrollX = TRUE, scrollY = TRUE,
                            pageLength = 10, order = list(list(1, 'asc')),
                            dom = 'Blrtip', buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
                            footerCallback = JS(
                                    "function( tfoot, data, start, end, display ) {",
                                            "var api = this.api(), data;",
                                            "api.columns().eq(0).each( function(index) {",
                                                    "var col = api.column(index);",
                                                    "if(index == 0) return $(api.column(index).footer()).html('Total')",
                                                    "var data = col.data();",
                                                    "total = data.reduce( function(a, b) { return a + b }, 0 );",
                                                    "$( api.column(index).footer() ).html(total.toFixed(2));",
                                            "})",
                                  "}"
                          ))
            ))
    }
    
    0 讨论(0)
提交回复
热议问题