[英]Keep formatting when exporting table with DT (DataTables buttons extension)
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. 我为此使用
DT::formatStyle
,它工作得非常好。 As far as I understand this function, it creates a callback to handle the conditional formatting. 据我了解这个函数,它创建一个回调来处理条件格式。
Then, I want to export the data, using the buttons extension in DT
. 然后,我想使用
DT
的按钮扩展名导出数据。 I want to keep the formatting when exporting to pdf or printing. 我想在导出为pdf或打印时保留格式。 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. 我试图设置
exportOptions(list(stripHtml = FALSE))
,但它仍然不起作用。
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. 让我感到惊讶的是,即使我直接从Firefox打印(如文件/打印......;我只尝试使用Firefox,而应用程序只能在Firefox中运行),颜色会被删除,但字体重量保持。 I suspect that I may have to tweak the CSS but I do not know how to do that.
我怀疑我可能不得不调整CSS,但我不知道该怎么做。
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. 我想有办法使pdf和/或打印“按原样”,最接近我在浏览器中看到的内容。 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)
I can export to pdf or print, but the display is modified. 我可以导出为pdf或打印,但显示被修改。 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. 我也可以使用
rmarkdown
和knitr
生成一个pdf,但这将是工作的两倍,感觉就像我使用按钮扩展错过了一些东西。
I hope that is clear and thanks for helping! 我希望这很清楚,谢谢你的帮助!
Florian 弗洛里安
PDF
and print
buttons have very different behaviors. PDF
和print
按钮具有非常不同的行为。
print
button behavior print
按钮行为 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). 单击
print
按钮时,使用用户代理(在此用例中为浏览器)将HTML
文档呈现为分页文档(PDF)。 There's a W3C standard named CSS Paged Media that defines how CSS rules are applied for paged media. 有一个名为CSS Paged Media的W3C标准,它定义了CSS规则如何应用于分页媒体。
Theses CSS rules are enclosed in CSS @media print
at-rule. 这些CSS规则包含在CSS
@media print
at-rule中。
There's a comprehensive guide about CSS Paged Media here: print-css.rocks . 这里有一个关于CSS分页媒体的综合指南: print-css.rocks 。
Dealing with CSS Paged Media is not straightforward: 处理CSS分页媒体并不简单:
wkhtmltopdf
, weasyprint
, XML Prince
...) are used to generate PDF with CSS Paged Media. wkhtmltopdf
, weasyprint
, XML Prince
...)用于使用CSS Paged Media生成PDF。 Using one of these user agents is quite easy since pandoc 2.0
: they can replace a LaTeX
engine. pandoc 2.0
:它们可以取代LaTeX
引擎。 HTML
file, browsers do not apply @media print
by default (they apply @media screen
at-rule). HTML
文件时,浏览器默认不应用@media print
(它们在@media screen
上应用规则)。 So, it can be hard to figure out @media print
rules. @media print
规则。 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
). More tools
和Rendering
。在Rendering
面板中,您可以模拟分页媒体选择print
)。 Since you want to use a browser to generate a styled PDF
, I think CSS paged media rules is an impracticable way. 由于您希望使用浏览器生成样式化
PDF
,我认为CSS分页媒体规则是不切实际的方法。 Moreover, using a headless user agent with a dynamic HTML document as a Shiny App is extremely complex. 此外,将无头用户代理与动态HTML文档一起用作Shiny App非常复杂。 So, my advise is to forget the
print
button. 所以,我的建议是忘记
print
按钮。
PDF
button behavior PDF
按钮行为 DataTables
library relies on pdfmake
JavaScript library to generate a PDF file. DataTables
库依赖于pdfmake
JavaScript库来生成PDF文件。 You can apply custom styles passing a JavaScript function to the customize
option of the pdfHtml5
button . 您可以将传递JavaScript函数的
customize
定义样式应用于pdfHtml5
按钮的customize
选项 。 This function customizes the document object sent to the pdfmake
API . 此函数自定义发送到
pdfmake
API的文档对象。
In order to understand the structure of the JSON
document object passed by DataTables
to pdfmake
, you can output it to the browser console: 为了理解
DataTables
传递给pdfmake
的JSON
文档对象的结构,您可以将其输出到浏览器控制台:
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)
You can modify a default style. 您可以修改默认样式。 Here's one example changing the font color of the
tableHeader
style: 这是更改
tableHeader
样式的字体颜色的一个示例:
customize = JS("function(doc){doc.styles.tableHeader.color='yellow';}"))
For further customization, you have to write your own JavaScript function. 要进一步定制,您必须编写自己的JavaScript函数。 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))+'%'}})}"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.