rshinyrpivottable

Export rpivottable output as image


I recently started using rPivotTable to produce some impressive charts and tables. I am using rPivotTable in a Shiny application. I was wondering if it is possible to export the output of the rPivotTable(Table, Bar chart, line chart etc) as image from the web browser. In RStudio(without Shiny), it can be done as the viewer has an option for Export->Save as Image. Is there any way to save the charts and tables.


Solution

  • A pivotTable is a htmlwidget, so you can use htmlwidgets::saveWidget to save the table in a html file and webshot::webshot to export it to png (or pdf).

    library(shiny)
    library(rpivotTable)
    library(htmlwidgets)
    library(webshot)
    
    ui <- fluidPage(
      br(),
      rpivotTableOutput("pivotbl"),
      br(),
      downloadButton("export", "Export")
    )
    
    server <- function(input, output, session){
    
      pivotTable <- rpivotTable(
        Titanic,
        rows = "Survived",
        cols = c("Class","Sex"),
        aggregatorName = "Sum as Fraction of Columns",
        inclusions = list( Survived = list("Yes")),
        exclusions= list( Class = list( "Crew")),
        vals = "Freq",
        rendererName = "Table Barchart"
      )
    
      output[["pivotbl"]] <- renderRpivotTable({
        pivotTable
      })
    
      output[["export"]] <- downloadHandler(
        filename = function(){
          "pivotTable.png"
        },
        content = function(file){
          tmphtml <- tempfile(fileext = ".html")
          saveWidget(pivotTable, file = tmphtml)
          webshot(tmphtml, file = file)
        }
      )
    
    }
    
    shinyApp(ui, server)
    

    EDIT

    Here is a way to export only the graph, using the dom-to-image JavaScript library.

    Download the file dom-to-image.min.js and put it in the www subfolder of the app.

    Here is the app:

    library(shiny)
    library(rpivotTable)
    
    js <- "
    function filter(node){
      return (node.tagName !== 'i');
    }
    function exportPlot(filename){
      var plot = document.getElementsByClassName('pvtRendererArea');
      domtoimage.toPng(plot[0], {filter: filter, bgcolor: 'white'})
        .then(function (dataUrl) {
          var link = document.createElement('a');
          link.download = filename;
          link.href = dataUrl;
          link.click();
        });
    }
    Shiny.addCustomMessageHandler('export', exportPlot);
    "
    
    ui <- fluidPage(
      tags$head(
        tags$script(src = "dom-to-image.min.js"),
        tags$script(HTML(js))
      ),
      br(),
      rpivotTableOutput("pivotbl"),
      br(),
      actionButton("export", "Export")
    )
    
    server <- function(input, output, session){
    
      pivotTable <- rpivotTable(
        Titanic,
        rows = "Survived",
        cols = c("Class","Sex"),
        aggregatorName = "Sum as Fraction of Columns",
        inclusions = list( Survived = list("Yes")),
        exclusions= list( Class = list( "Crew")),
        vals = "Freq",
        rendererName = "Table Barchart"
      )
    
      output[["pivotbl"]] <- renderRpivotTable({
        pivotTable
      })
    
      observeEvent(input[["export"]], {
        session$sendCustomMessage("export", "plot.png")
      })  
    
    }
    
    shinyApp(ui, server)