R和Microsoft Word:基于另一个Word文档中的文本更新一个Word文档中的文本

3
我的问题有所更新。以下是生成两个Word文档的代码。第一个文档包含一系列表格标题,每个标题都带有相应的书签。第二个文档包含实际的表格。
我想要做的是根据第一个文档中指定的内容确定第二个文档中的表格标题。我认为这种机制可能涉及查找第一个文档中相关的书签,在移动到实际标题所在行之前,然后复制标题,以便在第二个文档中使用。
library(officer)
library(magrittr)
library(flextable)

read_docx() %>%

body_add_par(value = "Fred Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "FredBMK") %>%
body_add_par("") %>%

body_add_par(value = "Sally Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "SallyBMK") %>%
body_add_par("") %>%               

body_add_par(value = "George Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "GeorgeBMK") %>%
body_add_par("") %>%                               

body_add_par(value = "Sample Data from the mtcars Dataset", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "mtcarsBMK") %>%
body_add_par("") %>%                                               

body_add_par(value = "Susan Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "SusanBMK") %>%
body_add_par("") %>%                               

print(target = "Test Report Skeleton.docx")


read_docx() %>%
body_add_par(value = "Table Title (Corresponding to mtcarsBMK) from Other Document Goes Here", style = "table title") %>%
body_add_par("") %>%
body_add_flextable(flextable(mtcars[1:12, 1:3])) %>%
print(target = "Test Target Table.docx")

原问题:

我正在使用R officer包生成Word文档。想象一种情况,文本最初在两个Word文档中同步。一个是较大的报告,另一个是生成的表格,然后自动插入到报告中。表格的标题最初在两个文档中都相同。现在假设医学撰稿人手动更改了报告中表格的标题。我希望能够检测到这一点,然后自动更新表格中的标题,使其与报告中的相匹配。

officer包的文档显示如何用用户指定的文本字符串替换单个文档中的文本。但我不清楚它是否可用于完成我想要实现的功能。在officer包内也不清楚它是否无法完成此任务。

以下是一些代码,用于创建两个Word文档。一个表示已对表格标题进行了更改的报告。另一个代表需要更新标题以与报告匹配的原始表格。区别很小,一个标题中有全部大写字母,而另一个则没有。

我希望有人能清楚地看出如何检测第一个文档中的更改,然后更新第二个文档中的标题。

library(officer)
library(magrittr)

read_docx() %>%
body_add_par(value = "AWESOME Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "AwesomeBMK") %>%
body_add_par("(Awesome table appears here immediately after AwesomeBMK bookmark)") %>%
print(target = "Awesome Report.docx")

read_docx() %>%
body_add_par(value = "Awesome Table", style = "table title") %>%
body_add_par("") %>%
body_bookmark(id = "AwesomeBMK") %>%
body_add_par("(Awesome table appears here immediately after AwesomeBMK bookmark)") %>%
print(target = "Awesome Table.docx")

对我来说,您的团队打算如何处理这个问题还不清楚。您是为每个人创建docx文件吗?文档中只有表格作为内容,还是它们添加了更多内容?并且为什么要更改表格标题呢? 此外,我看到您想使用 body_bookmark(id =“SusanBMK”) 作为某种标记,这似乎是个好主意,但人们可能会意外删除它? - Johannes Stötzer
谁做什么以及何时完成尚未完全确定。这可能在尝试在生产环境中实施时变得清晰。人们可以删除书签。计划采取措施来减轻这种情况。一直在处理大量代码。试图产生某种概念证明。目前的问题是我的一个难点。本来希望有人能立即知道答案并愿意与我分享。我想我需要找时间自己更全面地调查这个问题。 - Paul
2个回答

1
我不确定应该更改哪个文档才是正确的,我希望能有一个流程图来更好地遵循您的工作流程。
对于我的解决方案,首先我创建您的文档并保存路径以便稍后读取(您应该稍后从目录中读取它们)。然后我使用docx_summary()读取docx文件,比较两个文档并查找更改。您不能使用此代码更改多个更改,但应该可行。最后,我使用officer函数替换文本。
library(officer)
library(magrittr)

doc_copy <- read_docx() %>%
  body_add_par(value = "AWESOME Table", style = "table title") %>%
  body_add_par("") %>%
  body_bookmark(id = "AwesomeBMK") %>%
  body_add_par("(Awesome table appears here immediately after AwesomeBMK bookmark)") %>%
  print(target = "Awesome Report.docx")

doc_orginal <- read_docx() %>%
  body_add_par(value = "Awesome Table", style = "table title") %>%
  body_add_par("") %>%
  body_bookmark(id = "AwesomeBMK") %>%
  body_add_par("(Awesome table appears here immediately after AwesomeBMK bookmark)") %>%
  print(target = "Awesome Table.docx")


#detect change
doc_copy_summary <- read_docx(doc_copy) %>%
  docx_summary()

doc_orginal_summary <- read_docx(doc_orginal) %>%
  docx_summary()

test <- as.data.frame(doc_copy_summary == doc_orginal_summary)

old <- doc_orginal_summary[which(test==F, arr.ind = T)]
change <- doc_copy_summary[which(test==F, arr.ind = T)]

#instert text
my_doc <- read_docx(doc_orginal)  %>% 
  cursor_reach(keyword = paste0(old)) %>% 
  body_add_par(value = paste0(change), pos = "on")%>%
  print(target = "Change Awesome Table.docx")

谢谢Johannes。写一个好问题并不容易。我将更新我的问题,试图更好地说明我想做什么。 - Paul

0
以下是我认为的解决方案。我对XML的了解还很初步,但我觉得这个方法可能有效。
代码的第一部分生成一个Word文件,第二部分使文件下面的XML可访问,第三部分读取XML中相关的部分。第五部分捕捉表格和图形标题,这些标题紧随一个书签之后。第六部分捕获立即在表格或图形标题之前的书签。Word文件/XML中存在未匹配的表格标题和书签。表格标题无法匹配是因为后面没有书签,而书签无法匹配是因为前面没有立即出现的表格或图形标题。最后一部分将表格/图形标题与其相应的书签链接起来。
本来打算在这里提供XML,但因为任何Word文档的XML都非常冗长,所以放弃了。你们想运行这段代码的人可能没有我使用的包含表格标题1和图形标题1样式的Word文档模板。不过,我相信可以很容易地设计一个合适的Word模板,其中包括自己版本的表格标题和图形标题样式。
希望有一天这对某些人会有所帮助。
#### Make Word file ####

library(officer)
library(magrittr)
library(xml2)

read_docx("Report Template Blank.docx") %>%            

body_remove() %>%
body_add_par(value = "Fred Table", style = "Table Title 1") %>%
body_add_par("") %>%
body_bookmark(id = "FredtblBMK") %>%
body_add_par("") %>%

body_add_par(value = "Fred Figure", style = "Figure Title 1") %>%
body_add_par("") %>%
body_bookmark(id = "FredfigBMK") %>%
body_add_par("") %>%

body_add_par(value = "Sally Table", style = "Table Title 1") %>%
body_add_par("") %>%
body_bookmark(id = "SallytblBMK") %>%
body_add_par("") %>%

body_add_par(value = "Sally Figure", style = "Figure Title 1") %>%
body_add_par("") %>%
body_bookmark(id = "SallyfigBMK") %>%
body_add_par("") %>%

body_add_par(value = "Unmatched Table", style = "Table Title 1") %>%
body_add_par("") %>%

body_add_par("Some text separating the unmatched title and unmatched bookmark.") %>%
body_add_par("") %>%

body_bookmark(id = "UnmatchedBMK") %>%
body_add_par("") %>%

print(target = "Test Report Skeleton.docx")

#### Make XML underlying Word document accessible ####

file.copy("Test Report Skeleton.docx", "Test Report Skeleton.zip", overwrite = TRUE)
unzip("Test Report Skeleton.zip", exdir = "Test Report Skeleton XML")

#### Read XML ####

doc <-  read_xml("./Test Report Skeleton XML/word/document.xml")

#### Find qualifying table and figure titles ####

xml_tbl <-
xml_find_all(
doc,
"//w:p[w:pPr/w:pStyle[@w:val='TableTitle1' or @w:val='FigureTitle1'] and
./following-sibling::w:p[1][./w:bookmarkStart]]"
) %>%
xml_text()

#### Find qualifying bookmarks ####

xml_bmk <-
xml_find_all(
doc,
"//w:p[./w:bookmarkStart and
./preceding-sibling::w:p[1][./w:pPr/w:pStyle[@w:val='TableTitle1' or @w:val='FigureTitle1']]]
/w:bookmarkStart"
) %>%
xml_attr("name")

xml_tbl_bmk <- data.frame(title = xml_tbl, bookmark = xml_bmk)

#### Show results ####

xml_tbl_bmk

         title    bookmark
1   Fred Table  FredtblBMK
2  Fred Figure  FredfigBMK
3  Sally Table SallytblBMK
4 Sally Figure SallyfigBMK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接