简体   繁体   English

R 官包:添加反映当前幻灯片位置的幻灯片编号

[英]R officer package: Add slide numbers that reflect current slide position

I'm an avid user of the Reporters and Officer packages and currently trying to transition to Officer for a Powerpoint workflow.我是 Reporters 和Officer 软件包的狂热用户,目前正在尝试过渡到Officer 的Powerpoint 工作流程。 I'm using a slide template that includes slide number placeholders in the master.我使用的幻灯片模板在母版中包含幻灯片编号占位符。

When using Reporters, I am able to add the slide numbers using doc <-addPageNumber( doc ) and the page numbers reflect the current position each slide has in the deck.使用 Reporters 时,我可以使用doc <-addPageNumber( doc )添加幻灯片编号,并且页码反映每张幻灯片在幻灯片中的当前位置。 I am looking for the same functionality in Officer, and looking for the slide numbers to update appropriately when I move the slides.我正在 Office 中寻找相同的功能,并寻找在移动幻灯片时适当更新的幻灯片编号。

When I use ph_with_text(doc, type = "sldNum", str = "slide 1") , I am required to supply a string with a static number or text, and it does not update according to where the slide appears in the deck.当我使用ph_with_text(doc, type = "sldNum", str = "slide 1") ,我需要提供一个带有静态数字或文本的字符串,并且它不会根据幻灯片在幻灯片中出现的位置进行更新。 For example, if I know my slide will be slide 2, I can enter str = "2" , but then the slide number will read as 2 even if I move that slide to the slide 3 position in the presentation.例如,如果我知道我的幻灯片将是幻灯片 2,我可以输入str = "2" ,但是即使我将该幻灯片移动到演示文稿中幻灯片 3 的位置,幻灯片编号也会读取为 2。

I tried leaving the string empty with str = "" or with ph_empty(type= "sldNum") but these result in the string "Slide Number" appearing on the slide.我尝试使用str = ""ph_empty(type= "sldNum")将字符串留空,但这会导致幻灯片上出现字符串“幻灯片编号”。

Any help or pointers in the right direction would be appreciated!任何正确方向的帮助或指示将不胜感激!

I've successfully added page numbers using officer 0.3.4 with a for loop after I'm done with the presentation.完成演示后,我已使用带有 for 循环的官员 0.3.4 成功添加了页码。

library(officer)
library(magrittr)

my_pres <- read_pptx()  %>% 
  add_slide('Title Only', 'Office Theme') %>%
  ph_with(value = 'Slide 2 Title', location = ph_location_type(type = "title")) %>%
  add_slide('Title Only', 'Office Theme') %>%
  ph_with(value = 'Slide 3 Title', location = ph_location_type(type = 'title')) 

# add slide numbers starting on slide 2

n_slides <- length(my_pres)
for (i_slide in 2:n_slides) {
  my_pres <- my_pres %>%
    on_slide(index = i_slide) %>%
    ph_with(value = i_slide, location = ph_location_type('sldNum'))
}

Having faced a similar issue with officer and taking a look in the source code I came up with the following solution在与官员面临类似问题并查看源代码后,我想出了以下解决方案

ph_with_text_fld(doc, type = "sldNum", str = "2")

The code for that function follows:该函数的代码如下:

library(htmltools)
library(xml2)

ph_with_text_fld <- function( x, str, type = "title", index = 1 ){

  stopifnot( type %in% c("ctrTitle", "subTitle", "dt", "ftr", "sldNum", "title", "body") )

  slide <- x$slide$get_slide(x$cursor)
  sh_pr_df <- slide$get_xfrm(type = type, index = index)
  sh_pr_df$str <- str
  xml_elt <- do.call(pml_shape_str_fld, sh_pr_df)
  node <- as_xml_document(xml_elt)

  xml_add_child(xml_find_first(slide$get(), "//p:spTree"), node)

  slide$fortify_id()
  x
}

pml_shape_str_fld <- function(str, ph, offx, offy, cx, cy, ...) {

  sp_pr <- sprintf("<p:spPr><a:xfrm><a:off x=\"%.0f\" y=\"%.0f\"/><a:ext cx=\"%.0f\" cy=\"%.0f\"/></a:xfrm></p:spPr>", offx, offy, cx, cy)
  # sp_pr <- "<p:spPr/>"
  nv_sp_pr <- "<p:nvSpPr><p:cNvPr id=\"\" name=\"\"/><p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr><p:nvPr>%s</p:nvPr></p:nvSpPr>"
  nv_sp_pr <- sprintf( nv_sp_pr, ifelse(!is.na(ph), ph, "") )
  paste0( pml_with_ns("p:sp"),
          nv_sp_pr, sp_pr,
          "<p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:fld id=\"{GUID FROM THE MASTER TEMPLATE}\" type=\"slidenum\"><a:rPr/><a:t>",
          htmlEscape(str),
          "</a:t></a:fld></a:p></p:txBody></p:sp>"
  )
}

pml_with_ns <- function(x){
  base_ns <- "xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:p=\"http://schemas.openxmlformats.org/presentationml/2006/main\""
  sprintf("<%s %s>", x, base_ns)
}

The important part is重要的部分是

<a:fld id=\"{GUID FROM THE MASTER TEMPLATE}\" type=\"slidenum\">

where GUID FROM THE MASTER TEMPLATE needs to be replaced with the GUID from the Slidemaster Layout for that Field其中主模板中的GUID需要替换为该字段的 Slidemaster 布局中的 GUID

I came here looking for a more elegant solution than I have, but I thought I would at least offer this because it does technically solve your/our problem, just inelegantly.我来这里是为了寻找一个比我更优雅的解决方案,但我想我至少会提供这个,因为它确实在技术上解决了你/我们的问题,只是不雅。

It makes it easier to move around the slides without worrying about the slide numbers, but it does at a little cruft as well and you have to be careful to increment it even if you don't have a slide number slot (as in the case of my "Title" slide).它可以更轻松地在幻灯片中移动而无需担心幻灯片编号,但它也有点笨拙,即使您没有幻灯片编号槽,您也必须小心地增加它(如在这种情况下)我的“标题”幻灯片)。

An alternative is to write yourself a simple increment operator a la this question .另一种方法是为自己编写一个简单的增量运算符 a la this question

presentation_name_here <- officer::read_pptx("Presentations/Template.pptx")

slide_number <- 1

# Title slide -----------------------------------------------------------
presentation_name_here <- presentation_name_here %>%
  add_slide(layout = "Title Slide", master = "Office Theme") %>%
  ph_with(value = "Title", location = ph_location_label(ph_label = "Title")) %>%
slide_number <- slide_number + 1

# Executive summary -----------------------------------------------------
presentation_name_here <- presentation_name_here %>%
  add_slide(layout = "Title and Content", master = "Office Theme") %>%
  ph_with(value = "Executive summary", location = ph_location_label(ph_label = "Title")) %>%
  ph_with(value = slide_number, location = ph_location_label(ph_label = "Slide Number")) %>%
slide_number <- slide_number + 1

# Dashboard ---------------------------------------------------------------
presentation_name_here <- presentation_name_here %>%
  add_slide(layout = "Title and Content", master = "Office Theme") %>%
  ph_with(value = "Dashboard", location = ph_location_label(ph_label = "Title")) %>%
  ph_with(value = slide_number, location = ph_location_label(ph_label = "Slide Number"))

I've add my own code to look up the GUIDs based on András's answer :我添加了自己的代码来根据András 的回答查找 GUID:

get.guid = function(doc, xml.file){

  xml.file.path = doc$slideLayouts$.__enclos_env__$private$collection[[xml.file]]$file_name()

  layout.xml = read_xml(xml.file.path)

  layout.xml %>% 
    xml_find_first("//a:fld[@type=\"slidenum\"]") %>%
    xml_attr("id") 

}

ph_with_text_fld <- function( x, str, type = "title", index = 1, slide_layout_name){

  stopifnot( type %in% c("ctrTitle", "subTitle", "dt", "ftr", "sldNum", "title", "body") )

  slide <- x$slide$get_slide(x$cursor)

  xml.file = slide$get_metadata()$layout_file %>% basename 
  guid = get.guid(x, xml.file)

  sh_pr_df <- slide$get_xfrm(type = type, index = index)
  sh_pr_df$str <- str
  sh_pr_df$guid <- guid
  xml_elt <- do.call(pml_shape_str_fld, sh_pr_df)
  node <- as_xml_document(xml_elt)

  xml_add_child(xml_find_first(slide$get(), "//p:spTree"), node)

  slide$fortify_id()
  x
}

pml_shape_str_fld <- function(str, ph, offx, offy, cx, cy, guid, ...) {

  sp_pr <- sprintf("<p:spPr><a:xfrm><a:off x=\"%.0f\" y=\"%.0f\"/><a:ext cx=\"%.0f\" cy=\"%.0f\"/></a:xfrm></p:spPr>", offx, offy, cx, cy)
  # sp_pr <- "<p:spPr/>"
  nv_sp_pr <- "<p:nvSpPr><p:cNvPr id=\"\" name=\"\"/><p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr><p:nvPr>%s</p:nvPr></p:nvSpPr>"
  nv_sp_pr <- sprintf( nv_sp_pr, ifelse(!is.na(ph), ph, "") )
  paste0( pml_with_ns("p:sp"),
          nv_sp_pr, sp_pr,
          "<p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:fld id=\"", guid, "\" type=\"slidenum\"><a:rPr/><a:t>",
          htmlEscape(str),
          "</a:t></a:fld></a:p></p:txBody></p:sp>"
  )
}

pml_with_ns <- function(x){
  base_ns <- "xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:p=\"http://schemas.openxmlformats.org/presentationml/2006/main\""
  sprintf("<%s %s>", x, base_ns)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM