我制作了一个闪亮的应用程序,有人上传文件,计算一些比率,并且可以使用阈值滑块来格式化这些比率。我使用
DT::formatStyle
来实现这一点,而且效果非常好。据我了解这个函数,它创建一个回调来处理条件格式。
然后,我想使用
DT
中的按钮扩展导出数据。我想在导出为 pdf 或打印时保留格式。事实证明这不起作用:数据在没有任何格式的情况下导出。我尝试设置exportOptions(list(stripHtml = FALSE))
,但还是不行。
让我感到惊讶的是,即使我直接从 Firefox 打印(作为文件/打印...;我只尝试过使用 Firefox,并且该应用程序只能在 Firefox 中运行),颜色也会丢失,但字体会丢失重量被保留。我怀疑我可能需要调整 CSS,但我不知道该怎么做。
我希望有一种方法可以使 pdf 和/或打印“按原样”,最接近我在浏览器中看到的内容。 下面是一个例子:
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,但这会是工作量的两倍,而且感觉好像我错过了使用按钮扩展的东西。
PDF
和 print
按钮具有非常不同的行为。
print
按钮行为当您单击
print
按钮时,您可以使用用户代理(在本用例中为浏览器)将 HTML
文档呈现为分页文档 (PDF)。有一个名为 CSS 分页媒体 的 W3C 标准,它定义了如何将 CSS 规则应用于分页媒体。@media print
at-rule 中。处理 CSS 分页媒体并不简单:
wkhtmltopdf
、weasyprint
、XML Prince
...)用于使用 CSS 分页媒体生成 PDF。使用这些用户代理之一非常容易,因为 pandoc 2.0
:它们可以替换 LaTeX
引擎。 HTML
文件时,浏览器默认不应用 @media print
(它们应用 @media screen
规则)。因此,很难弄清楚@media print
规则。我知道跟踪这些规则的唯一方法是使用 Chrome 开发人员工具(打开菜单,选择 More tools
和 Rendering
。在 Rendering
面板中,您可以模拟分页媒体,选择 print
)。既然要使用浏览器来生成样式化的
PDF
,我认为CSS分页媒体规则是一种不切实际的方式。此外,使用带有动态 HTML 文档的无头用户代理作为 Shiny 应用程序非常复杂。所以,我的建议是忘记 print
按钮。
PDF
按钮行为DataTables
库依赖于 pdfmake
JavaScript 库来生成 PDF 文件。您可以应用自定义样式,将 JavaScript 函数传递给 customize
按钮的
pdfHtml5
选项。此函数自定义发送到 pdfmake
API的文档对象。
为了了解
JSON
传递给DataTables
的pdfmake
文档对象的结构,可以将其输出到浏览器控制台:
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
样式的字体颜色的示例:
customize = JS("function(doc){doc.styles.tableHeader.color='yellow';}"))
为了进一步定制,您必须编写自己的 JavaScript 函数。以下是使用百分比格式化第五列的示例:
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))+'%'}})}"))