在 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函数中evalparent.frame()renderInlineCode。显然,那里没有包含所需的对象,而是在其 parent.frame() 中。所以你必须依靠 R 的作用域,它在这里不能正常工作。我很高兴得到更详尽的解释。