使用DT导出表格时保持格式(DataTables按钮扩展) [英] Keep formatting when exporting table with DT (DataTables buttons extension)
问题描述
我制作了一个闪亮的应用程序,其中有人上载文件,计算了一些比率,并且可以使用阈值滑块设置这些比率的格式.我为此使用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 = " " # small unbreakable space
)
)
)
}
formatter_DT <- function(table, input) {
table %>%
formatPercentage(columns = c("ratio_j"),
digits = 1L, dec.mark = ",", mark = " ") %>%
formatRound(columns = c("height", "mass"),
digits = 1L, dec.mark = ",", mark = " ") %>%
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或打印,但是显示已修改.我也可以使用rmarkdown
和knitr
生成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函数.
PDF
和print
按钮的行为完全不同.
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标准;无头用户代理(
- 打开
HTML
文件时,默认情况下浏览器不应用@media print
(规则中应用@media screen
).因此,很难弄清@media print
规则.我知道要跟踪这些规则的唯一方法是使用Chrome开发者工具(打开菜单,选择More tools
和Rendering
.在Rendering
面板中,您可以模拟选择print
的分页媒体). /li>
wkhtmltopdf
,weasyprint
,XML Prince
...)用于通过CSS Paged Media生成PDF.由于pandoc 2.0
,使用这些用户代理之一非常容易:它们可以替换LaTeX
引擎.
- 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 sincepandoc 2.0
: they can replace aLaTeX
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, selectMore tools
andRendering
. In theRendering
panel, you can emulate a paged media selectingprint
).
由于要使用浏览器生成样式化的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
传递给pdfmake
的JSON
文档对象的结构,可以将其输出到浏览器控制台:
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 = " " # small unbreakable space
)
)
)
}
formatter_DT <- function(table, input) {
table %>%
formatPercentage(columns = c("ratio_j"),
digits = 1L, dec.mark = ",", mark = " ") %>%
formatRound(columns = c("height", "mass"),
digits = 1L, dec.mark = ",", mark = " ") %>%
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屋!