【问题标题】:Print a Shiny reactive value on WordR在 Word 上打印一个闪亮的反应值
【发布时间】:2021-01-04 12:33:55
【问题描述】:

我正在寻求一些帮助,请使用 WordR 将 Shiny 会话中的反应值打印到 docx 中。下面展示了我的应用程序的一个非常精简的版本。

docx 模板的代码是`r reactive({declared_user()})`(以 MS Word 的格式符号结尾)。我不知道如何在 SO 上显示格式符号或在此处提供 docx 模板,但这是唯一适用的代码。

我尝试了多种方法将declared_user() 包装在 r 文件和 docx 中的反应式上下文中,但似乎仍然无法在 rprt_out.docx 中看到打印输出的 'slt_input' 中的值/用户。

所有打印出来的是…… function () { .dependents$register() if (.invalidated || .running) { ..stacktraceoff..(self$.updateValue()) } if (.error) { stop(.value) } if (.visible) .value 否则不可见(.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)

【问题讨论】:

    标签: r shiny docx officer wordr


    【解决方案1】:

    这里有一个解决方案。我认为有两件事使问题复杂化:

    • 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 的范围,这在闪亮的情况下无法正常工作。我很高兴得到一些更全面的解释。

    【讨论】:

    • 谢谢。并为迟到的反应道歉。您的解决方案最重要的方面是将我更多地引向了官员包,我现在意识到它提供了更多的服务器端控制,特别是使用反应器的“管道”和字符串操作。您的解决方案解决了这个问题,所以我会接受它作为首选
    猜你喜欢
    • 1970-01-01
    • 2020-03-14
    • 2013-07-16
    • 1970-01-01
    • 2017-03-10
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    相关资源
    最近更新 更多