在 Word 上打印闪亮的反应值
Print a Shiny reactive value on WordR
我正在寻找一些帮助,请使用 WordR 将 Shiny 会话中的反应值打印到 docx 中。下面展示了我的应用程序的一个非常精简的版本。
docx 模板的代码是 `r reactive({declared_user()})`
(以 MS Word 的格式符号结尾)。我不知道如何在 SO 上显示格式符号或提供 docx 模板,但这是唯一适用的代码。
我已经尝试了多种方法将 declared_user()
包装在 r 文件和 docx 的反应性上下文中,但似乎仍然无法在 'slt_input 中看到任何 value/user ' 在 rprt_out.docx.
中打印出来
打印出来的是……
function () { .dependents$register() if (.invalidated || .运行) { ..stacktraceoff..(self$.updateValue()) } if (.error) { 停止(.value) } if (.visible) .value else invisible(.value) }
library(shiny)
library(WordR)
library(officer)
library(dplyr)
ui <- fluidPage(
selectInput('slt_input', 'name', choices = c("god", 'devil')),
actionButton("btn_inline", 'inline')
)
server <- function(input, output, session) {
declared_user <- reactive({
input$slt_input
})
observeEvent(input$btn_inline,{
renderInlineCode("rprt_tmplt.docx", "rprt_out.docx")
})
}
shinyApp(ui, server)
这是一个解决方案。我认为有两件事使问题复杂化:
renderInlineCode
从 .docx 模板中提取 R 代码并使用 eval
评估代码。不知何故,它无法使用正确的环境进行评估。因此,我稍微更改了代码,以便您可以将环境作为参数传递给函数。
- 它仍然无法评估闪亮的代码。因此,我在 docx 渲染之前直接从反应中生成了一个普通变量,并在模板中使用它
library(shiny)
library(WordR)
library(officer)
library(dplyr)
renderInlineCode_2 <- function (docxIn, docxOut, eval_envir = parent.frame(), debug = F)
{
if (debug) {
browser()
}
doc <- officer::read_docx(docxIn)
smm <- officer::docx_summary(doc)
styles <- officer::styles_info(doc)
regx <- "^[ ]*`r[ ](.*)`$"
smm$expr <- ifelse(grepl(regx, smm$text), sub(regx, "\1",
smm$text), NA)
smm$values <- sapply(smm$expr, FUN = function(x) {
eval(parse(text = x), envir = eval_envir)
})
smm <- smm[!is.na(smm$expr), , drop = F]
i <- 3
for (i in seq_len(nrow(smm))) {
stylei <- switch(ifelse(is.na(smm$style_name[i]), "a",
"b"), a = NULL, b = styles$style_name[styles$style_id ==
paste0(styles$style_id[styles$style_name == smm$style_name[i] &
styles$style_type == "paragraph"], "Char")])
doc <- officer::cursor_reach(doc, keyword = paste0("\Q",
smm$text[i], "\E")) %>% officer::body_remove() %>%
officer::cursor_backward() %>% officer::slip_in_text(smm$values[i],
pos = "after", style = stylei)
}
print(doc, target = docxOut)
return(docxOut)
}
ui <- fluidPage(
selectInput('slt_input', 'name', choices = c("god", 'devil')),
actionButton("btn_inline", 'inline')
)
server <- function(input, output, session) {
declared_user <- reactive({
input$slt_input
})
observeEvent(input$btn_inline,{
eval_user <- declared_user()
renderInlineCode_2("rprt_tmplt.docx", "rprt_out.docx")
})
}
shinyApp(ui, server)
在模板中,使用:
`r eval_user`
编辑
仔细想想,我认为在原来的renderInlineCode
函数中eval
的parent.frame()
是renderInlineCode
。显然,那里没有包含所需的对象,而是在其 parent.frame()
中。所以你必须依靠 R 的作用域,它在这里不能正常工作。我很高兴得到更详尽的解释。
我正在寻找一些帮助,请使用 WordR 将 Shiny 会话中的反应值打印到 docx 中。下面展示了我的应用程序的一个非常精简的版本。
docx 模板的代码是 `r reactive({declared_user()})`
(以 MS Word 的格式符号结尾)。我不知道如何在 SO 上显示格式符号或提供 docx 模板,但这是唯一适用的代码。
我已经尝试了多种方法将 declared_user()
包装在 r 文件和 docx 的反应性上下文中,但似乎仍然无法在 'slt_input 中看到任何 value/user ' 在 rprt_out.docx.
打印出来的是…… function () { .dependents$register() if (.invalidated || .运行) { ..stacktraceoff..(self$.updateValue()) } if (.error) { 停止(.value) } if (.visible) .value else invisible(.value) }
library(shiny)
library(WordR)
library(officer)
library(dplyr)
ui <- fluidPage(
selectInput('slt_input', 'name', choices = c("god", 'devil')),
actionButton("btn_inline", 'inline')
)
server <- function(input, output, session) {
declared_user <- reactive({
input$slt_input
})
observeEvent(input$btn_inline,{
renderInlineCode("rprt_tmplt.docx", "rprt_out.docx")
})
}
shinyApp(ui, server)
这是一个解决方案。我认为有两件事使问题复杂化:
renderInlineCode
从 .docx 模板中提取 R 代码并使用eval
评估代码。不知何故,它无法使用正确的环境进行评估。因此,我稍微更改了代码,以便您可以将环境作为参数传递给函数。- 它仍然无法评估闪亮的代码。因此,我在 docx 渲染之前直接从反应中生成了一个普通变量,并在模板中使用它
library(shiny)
library(WordR)
library(officer)
library(dplyr)
renderInlineCode_2 <- function (docxIn, docxOut, eval_envir = parent.frame(), debug = F)
{
if (debug) {
browser()
}
doc <- officer::read_docx(docxIn)
smm <- officer::docx_summary(doc)
styles <- officer::styles_info(doc)
regx <- "^[ ]*`r[ ](.*)`$"
smm$expr <- ifelse(grepl(regx, smm$text), sub(regx, "\1",
smm$text), NA)
smm$values <- sapply(smm$expr, FUN = function(x) {
eval(parse(text = x), envir = eval_envir)
})
smm <- smm[!is.na(smm$expr), , drop = F]
i <- 3
for (i in seq_len(nrow(smm))) {
stylei <- switch(ifelse(is.na(smm$style_name[i]), "a",
"b"), a = NULL, b = styles$style_name[styles$style_id ==
paste0(styles$style_id[styles$style_name == smm$style_name[i] &
styles$style_type == "paragraph"], "Char")])
doc <- officer::cursor_reach(doc, keyword = paste0("\Q",
smm$text[i], "\E")) %>% officer::body_remove() %>%
officer::cursor_backward() %>% officer::slip_in_text(smm$values[i],
pos = "after", style = stylei)
}
print(doc, target = docxOut)
return(docxOut)
}
ui <- fluidPage(
selectInput('slt_input', 'name', choices = c("god", 'devil')),
actionButton("btn_inline", 'inline')
)
server <- function(input, output, session) {
declared_user <- reactive({
input$slt_input
})
observeEvent(input$btn_inline,{
eval_user <- declared_user()
renderInlineCode_2("rprt_tmplt.docx", "rprt_out.docx")
})
}
shinyApp(ui, server)
在模板中,使用:
`r eval_user`
编辑
仔细想想,我认为在原来的renderInlineCode
函数中eval
的parent.frame()
是renderInlineCode
。显然,那里没有包含所需的对象,而是在其 parent.frame()
中。所以你必须依靠 R 的作用域,它在这里不能正常工作。我很高兴得到更详尽的解释。