使用DT导出表格时保持格式(DataTables按钮扩展) [英] Keep formatting when exporting table with DT (DataTables buttons extension)

查看:71
本文介绍了使用DT导出表格时保持格式(DataTables按钮扩展)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个闪亮的应用程序,其中有人上载文件,计算了一些比率,并且可以使用阈值滑块设置这些比率的格式.我为此使用DT::formatStyle,它的工作真的很好.据我了解,该函数会创建一个回调来处理条件格式.

I made a shiny app where someone uploads a file, some ratios are computed, and those ratios can be formatted using sliders for thresholds. I use DT::formatStyle for this and it is working really fine. As far as I understand this function, it creates a callback to handle the conditional formatting.

然后,我要使用DT中的按钮扩展名导出数据.我想在导出为pdf或打印时保留格式.事实证明这是行不通的:数据未经任何格式导出.我尝试设置exportOptions(list(stripHtml = FALSE)),但仍然无法正常工作.

Then, I want to export the data, using the buttons extension in DT. I want to keep the formatting when exporting to pdf or printing. It turns out that this doesn't work: the data is exported without any formatting. I tried to set exportOptions(list(stripHtml = FALSE)), but it still doesn't work.

令我惊讶的是,即使我直接从Firefox打印(如File/Print ...;我仅尝试使用Firefox,并且该应用程序只能在Firefox中运行),颜色也会掉落,但保留字体粗细.我怀疑可能需要调整CSS,但是我不知道该怎么做.

What surprises me as well, is that even when I print directly from Firefox (as File/Print... ; I have tried with Firefox only, and the app will only be run in Firefox), the color is dropped, but font weight is kept. I suspect that I may have to tweak the CSS but I do not know how to do that.

我希望有一种方法可以使pdf和/或打印文件保持原样",与我在浏览器中看到的最接近. 下面是一个示例:

I would like to have a way to make the pdf and/or the print "as is", the closest to what I see in the browser. Below is an example:

library(shiny)
library(DT)
library(dplyr)
data("starwars")

ui <- fluidPage(title = "Ratios",
  sidebarLayout(
    sidebarPanel(width = 2,
                 actionButton("button", "Go"), # Emulates data loading
                 sliderInput("seuil_j", "Threshold J",
                             min = 0,  max = 80, value = 35, step = 0.5)),
    mainPanel( 
      fluidRow(column(width = 12,
                      DT::dataTableOutput("ratios"))))
  )
)

server <- function(input, output, session) {
  donnees_ratios <- reactive({
    req(input$button)
    set.seed(14)
    starwars %>% 
      select(1:10) %>% # DataTables is not happy with list columns
      mutate(signe = sample(c(1, -1), replace = TRUE, size = nrow(.)),
             ratio_j = signe * mass / height) %>% 
      select(name, mass, height, signe, ratio_j, everything())
  })

  output$ratios <- DT::renderDataTable({
    donnees_ratios() %>% 
      creer_DT() %>% 
      formatter_DT(input)
  })
}

creer_DT <- function(donnees) {
  datatable(donnees, 
            rownames = FALSE, 
            class = 'cell-border stripe compact hover',
            extensions = c("Buttons"),
            options = list(
              dom = 'Blfrtip',
              buttons = list(
                list(extend = "pdf", 
                     exportOptions = list(stripHtml = FALSE,
                                                     columns = ':visible'),
                     orientation = 'landscape'),
                list(extend = "print", 
                     exportOptions = list(stripHtml = FALSE,
                                          columns = ':visible')),
               "excel", "csv", "colvis"),
              language = list(
                decimal = ",",
                thousands = "&#8239;"  # small unbreakable space
              )
            )
  )
}

formatter_DT <- function(table, input) {
  table %>% 
    formatPercentage(columns = c("ratio_j"),
                     digits = 1L, dec.mark = ",", mark = "&#8239;") %>%
    formatRound(columns = c("height", "mass"),
                digits = 1L, dec.mark = ",", mark = "&#8239;") %>%
    format_seuil("ratio_j", input$seuil_j)
}

format_seuil <- function(table, column, seuil) {
  # Threshold for the aboslute value, and different coloring if higher or lower
  formatStyle(table, column, 
              fontWeight = styleInterval(
                c(-seuil / 100, seuil / 100), c("bold", "normal", "bold")),
              color = styleInterval(
                c(-seuil / 100, seuil / 100), c("red", "black", "orange")
              ))
}

shinyApp(ui, server)

我可以导出为pdf或打印,但是显示已修改.我也可以使用rmarkdownknitr生成pdf,但这是工作的两倍,感觉就像我错过了使用按钮扩展名的东西.

I can export to pdf or print, but the display is modified. I could also generate a pdf with rmarkdown and knitr, but this would be twice the work, and it feels like I miss something using the buttons extension.

我希望这很清楚,感谢您的帮助!

I hope that is clear and thanks for helping!

弗洛里安

推荐答案

tl; dr您无法继续设置格式;您必须编写一个自定义JavaScript函数.

PDFprint按钮的行为完全不同.

tl;dr You cannot keep formatting; you have to write a custom JavaScript function.

PDF and print buttons have very different behaviors.

单击print按钮时,将使用用户代理(在这种情况下为浏览器)将HTML文档呈现为页面文档(PDF).有一个名为 CSS Paged Media 的W3C标准,用于定义如何将CSS规则应用于页面媒体.
这些CSS规则包含在CSS @media print规则中.
此处提供了有关CSS Paged Media的综合指南: print-css.rocks .

When you click the print button, you use the user agent (in this use case, the browser) to render the HTML document as a paged document (PDF). There's a W3C standard named CSS Paged Media that defines how CSS rules are applied for paged media.
Theses CSS rules are enclosed in CSS @media print at-rule.
There's a comprehensive guide about CSS Paged Media here: print-css.rocks.

使用CSS分页媒体进行交易并非易事:

Dealing with CSS Paged Media is not straightforward:

    浏览器严重违反了CSS Paged Media标准;无头用户代理(wkhtmltopdfweasyprintXML Prince ...)用于通过CSS Paged Media生成PDF.由于pandoc 2.0,使用这些用户代理之一非常容易:它们可以替换LaTeX引擎.
  • 打开HTML文件时,默认情况下浏览器不应用@media print(规则中应用@media screen).因此,很难弄清@media print规则.我知道要跟踪这些规则的唯一方法是使用Chrome开发者工具(打开菜单,选择More toolsRendering.在Rendering面板中,您可以模拟选择print的分页媒体). /li>
  • browsers badly implement CSS Paged Media standards; headless user agents (wkhtmltopdf, weasyprint, XML Prince...) are used to generate PDF with CSS Paged Media. Using one of these user agents is quite easy since pandoc 2.0: they can replace a LaTeX engine.
  • when you open a HTML file, browsers do not apply @media print by default (they apply @media screen at-rule). So, it can be hard to figure out @media print rules. The only mean I know to track theses rules is to use the Chrome Developer Tools (open the menu, select More tools and Rendering. In the Rendering panel, you can emulate a paged media selecting print).

由于要使用浏览器生成样式化的PDF,我认为CSS分页媒体规则是不可行的方法.此外,将无头用户代理与动态HTML文档一起用作Shiny App极其复杂.因此,我的建议是忘记print按钮.

Since you want to use a browser to generate a styled PDF, I think CSS paged media rules is an impracticable way. Moreover, using a headless user agent with a dynamic HTML document as a Shiny App is extremely complex. So, my advise is to forget the print button.

DataTables库依赖于pdfmake JavaScript库来生成PDF文件.您可以将传递JavaScript函数的自定义样式应用于pdfHtml5按钮的 customize选项 .此函数自定义发送到 pdfmake API 的文档对象.

DataTables library relies on pdfmake JavaScript library to generate a PDF file. You can apply custom styles passing a JavaScript function to the customize option of the pdfHtml5 button. This function customizes the document object sent to the pdfmake API.

为了了解DataTables传递给pdfmakeJSON文档对象的结构,可以将其输出到浏览器控制台:

In order to understand the structure of the JSON document object passed by DataTables to pdfmake, you can output it to the browser console:

library(shiny)
library(DT)
library(dplyr)
data("starwars")

ui <- fluidPage(title = "Ratios",
                sidebarLayout(
                  sidebarPanel(width = 2,
                               actionButton("button", "Go"), # Emulates data loading
                               sliderInput("seuil_j", "Threshold J",
                                           min = 0,  max = 80, value = 35, step = 0.5)),
                  mainPanel( 
                    fluidRow(column(width = 12,
                                    DT::dataTableOutput("ratios"))))
                )
)

server <- function(input, output, session) {
  donnees_ratios <- reactive({
    req(input$button)
    set.seed(14)
    starwars %>% 
      select(1:10) %>% # DataTables is not happy with list columns
      mutate(signe = sample(c(1, -1), replace = TRUE, size = nrow(.)),
             ratio_j = signe * mass / height) %>% 
      select(name, mass, height, signe, ratio_j, everything())
  })

  output$ratios <- DT::renderDataTable({
    donnees_ratios() %>% 
      creer_DT() %>% 
      formatter_DT(input)
  })
}

creer_DT <- function(donnees) {
  datatable(donnees, 
            rownames = FALSE, 
            class = 'cell-border stripe compact hover',
            extensions = c("Buttons"),
            options = list(
              dom = 'Blfrtip',
              buttons = list(
                list(extend = "pdf", 
                     exportOptions = list(stripHtml = FALSE,
                                          columns = ':visible'),
                     orientation = 'landscape',
                     customize = JS("function(doc){console.dir(doc);}")),
                list(extend = "print", 
                     exportOptions = list(stripHtml = FALSE,
                                          columns = ':visible')),
                "excel", "csv", "colvis"),
              language = list(
                decimal = ",",
                thousands = "&#8239;"  # small unbreakable space
              )
            )
  )
}

formatter_DT <- function(table, input) {
  table %>% 
    formatPercentage(columns = c("ratio_j"),
                     digits = 1L, dec.mark = ",", mark = "&#8239;") %>%
    formatRound(columns = c("height", "mass"),
                digits = 1L, dec.mark = ",", mark = "&#8239;") %>%
    format_seuil("ratio_j", input$seuil_j)
}

format_seuil <- function(table, column, seuil) {
  # Threshold for the aboslute value, and different coloring if higher or lower
  formatStyle(table, column, 
              fontWeight = styleInterval(
                c(-seuil / 100, seuil / 100), c("bold", "normal", "bold")),
              color = styleInterval(
                c(-seuil / 100, seuil / 100), c("red", "black", "orange")
              ))
}

shinyApp(ui, server)

您可以修改默认样式.这是一个更改tableHeader样式的字体颜色的示例:

You can modify a default style. Here's one example changing the font color of the tableHeader style:

customize = JS("function(doc){doc.styles.tableHeader.color='yellow';}"))

要进行进一步的自定义,您必须编写自己的JavaScript函数.这是一个用百分比格式化第五列的示例:

For further customization, you have to write your own JavaScript function. Here's an example to format the fifth column with percent:

customize = JS("function(doc){doc.content[1].table.body.forEach(function(el,idx){if(idx>0){el[4].text=String((parseFloat(el[4].text)*100).toFixed(1))+'%'}})}"))

这篇关于使用DT导出表格时保持格式(DataTables按钮扩展)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆