在 officer 中插入自定义目录的最佳方法

Best way to insert a custom TOC in officer

我需要将自定义目录插入到 officer 文档中。在这种情况下,我需要插入使用级别 6 headers 创建的 table 列表。我需要插入的目录字段是:

{TOC \o "6-6" \* MERGEFORMAT}

block_toc 函数似乎不允许我这样做。所以想做的是使用该函数中的内部函数(例如,run_seqfieldto_wml 等)来完成此操作。我想知道是否有人有任何其他利用更标准的官员功能的想法。

在下面的示例中,我尝试使用带有 block_toc 的样式选项来创建 table 的列表。当我 运行 时,它给我“找不到 table 的内容条目。”

library(officer)
library(flextable)
library(magrittr)


tab_seq_id = "Table"

# empty report
rpt = read_docx()

bt <- block_toc(style = "Table Caption")
out <- to_wml(bt, add_ns = TRUE)
rpt <- body_add_xml(rpt, str = out, pos = "after")

mytxt = paste(rep("The quick brown fox jumped over the lazy dog.", 30), collapse=" ")
# Making a table
ft = flextable(head(mtcars))

# Creating some sections with text
rpt = body_add_fpar(rpt, fpar("A section"), style="heading 1")

fptxt  = fpar(mytxt)

rpt = officer::body_add_fpar(rpt, fptxt)

rpt = body_add_fpar(rpt, fpar("Another section"), style="heading 1")

fptxt  = fpar("This is a cross reference to the first table (Table ",
              run_reference("my_table"), 
              ") and this is a reference to the second table (Table ",
              run_reference("my_second_table"), ")." ,
              ") and a third table in a new section (Table ",
              run_reference("my_third_table"), ")." )

long_cap = "This is my table caption. It can span many lines and take up much space on the page." 

#-------------------------------------------------------
# Normal table
run_num = officer::run_autonum(seq_id     = tab_seq_id,
                               pre_label  = "Table ",
                               post_label = ".",
                               bkm        = "my_table")

caption = officer::block_caption(long_cap,
                                 style  = "Table Caption",
                                 autonum = run_num )

rpt = officer::body_add_fpar(rpt, fptxt)


rpt  = flextable::body_add_flextable(rpt, value=ft)
rpt = officer::body_add_caption(rpt, caption)
#-------------------------------------------------------
# Table with the section number in it
runs =        list(
  run_word_field("STYLEREF 1 \s"),
  ftext("-"),
  officer::run_autonum(pre_label = "", seq_id = tab_seq_id, post_label=""))
rb_res = run_bookmark("my_second_table", runs)

rpt  = flextable::body_add_flextable(rpt, value=ft)
rpt  = officer::body_add_fpar(rpt, fpar("Table ", rb_res, ".    ", long_cap), style = "Table Caption")


# Creating some sections with text
rpt = body_add_fpar(rpt, fpar("A third section"), style="heading 1")
#-------------------------------------------------------
# Table with the section number in it
runs =        list(
  run_word_field("STYLEREF 1 \s"),
  ftext("-"),
  officer::run_autonum(pre_label = "", seq_id = tab_seq_id, start_at = 1, post_label=""))
rb_res = run_bookmark("my_third_table", runs)

rpt  = flextable::body_add_flextable(rpt, value=ft)
rpt  = officer::body_add_fpar(rpt, fpar("Table ", rb_res, ".    ", long_cap), style = "Table Caption")
print(rpt, "fig_sec_num.docx")

这应该有帮助(还记得在 Word 中刷新目录):

library(officer)
library(flextable)
library(magrittr)

mytxt <- paste(rep("The quick brown fox jumped over the lazy dog.", 30), collapse = " ")
long_cap <- "This is my table caption. It can span many lines and take up much space on the page."
tab_seq_id <- "Table"

ft <- flextable(head(mtcars))

get_caption <- function(bookmark){
  par <- list(
    ftext("Table "),
    run_word_field("STYLEREF 1 \s"),
    ftext("-"),
    run_word_field("SEQ Table \u005C* Arabic")
  )
  run_bookmark(bookmark, par)
}


fptxt <- fpar(
  "This is a cross reference to the first table (",
  run_reference("my_table1"),
  ") and this is a reference to the second table (",
  run_reference("my_table2"), ").",
  ") and a third table in a new section (",
  run_reference("my_table3"), ")."
)


rpt <- read_docx() %>% 
  body_add_toc(style = "Table Caption") %>% 
  body_add_par("A section", style = "heading 1") %>% 
  body_add_par(value = mytxt, style = "Normal") %>% 
  body_add_par("Another section", style = "heading 1") %>% 
  body_add_fpar(fptxt) %>% 
  body_add_flextable(value = ft) %>% 
  body_add_fpar(value = fpar(get_caption(bookmark = "my_table1"), " ", long_cap), style = "Table Caption") %>% 
  body_add_flextable(value = ft) %>% 
  body_add_fpar(value = fpar(get_caption(bookmark = "my_table2"), " ", long_cap), style = "Table Caption") %>% 
  body_add_par("A third section", style = "heading 1") %>% 
  body_add_flextable(value = ft) %>% 
  body_add_fpar(value = fpar(get_caption(bookmark = "my_table3"), " ", long_cap), style = "Table Caption")
  


print(rpt, "fig_sec_num.docx")

TLDR;我需要将 separator="," 添加到上面的 body_add_toc() 调用

我开始查看指定词样式时生成的目录域代码。 David 提供的示例可以在他的计算机上运行,​​但我无法让它在我这边生成 TOC。我开始使用生成的字段代码来尝试解决问题。在 Davids 解决方案中由官员为我生成的字段代码是:

{TOC \h \z \t "Table Caption;1"}

那对我不起作用。然后我发现,如果我将字段代码更改为以下之一,它将正确生成 TOC:

{TOC \h \z \t "Table Caption"}
{TOC \h \z \t "Table Caption,1"}

在第一个示例中,我完全省略了“;1”,在第二个示例中,我更改了“;”到 ”,”。所以我开始谷歌搜索,如果我没看错的话,可能是某种区域设置导致了这个问题:

https://answers.microsoft.com/en-us/msoffice/forum/all/table-of-contents-word-2016-word-2013/842156d0-51dd-4726-9c36-343e57bf9f92

然后我阅读了 body_add_toc 的文档,意识到有一个选项可以解决这个问题。我以前见过它,但我不知道它为什么在那里,但这为我解决了所有问题。

感谢大卫的耐心等待。